DEV Community

Cover image for What changed after our IVR started pulling data from the CRM
Jack Morris
Jack Morris

Posted on

What changed after our IVR started pulling data from the CRM

Last year we rebuilt the IVR for a mid-size financial services company. Around 2,500 inbound calls a day, mix of existing customers and new leads, five departments handling everything from account inquiries to collections.

The original IVR had been running for three years. It worked. Calls got answered, menus got navigated, people eventually reached a human. Nobody was complaining loudly enough for it to become a priority.

Then someone pulled the actual numbers, and the picture wasn't great.

How the old IVR worked

Every caller got the same experience regardless of who they were. You'd hear a welcome message, sit through five menu options, pick one, and wait in a queue. If you picked wrong, you'd get transferred and wait again.

Agents had zero context when the call connected. The first 20-30 seconds of every call was spent on "can I get your name and account number?" Even for callers who'd been customers for years. Even for someone who called yesterday about the same issue.

The IVR had no idea who was calling. It couldn't. It was a standalone system with no connection to anything else in the business.

Here's what the numbers looked like:

  • Average handle time per call was around 4 minutes 40 seconds
  • Roughly 35-40 seconds of that was just identification and account lookup at the start
  • Call abandonment rate sat around 12%, mostly people dropping off during menu navigation or hold queues
  • Overdue accounts were going through the full standard menu before reaching collections. Some of them never got there they'd pick the wrong option, land in general support, and get transferred. The transfer added another 2-3 minutes to those calls
  • New leads from marketing campaigns were treated identically to everyone else. No priority routing, no personalized greeting, no assignment to the rep who was running the campaign

The support team had gotten used to it. That's how phones work, right? Caller comes in, you ask who they are, you pull up the account. Standard stuff.
We thought there was a better way.

The core idea
The concept was straightforward. Before the IVR plays its first word, it checks the caller's phone number against the CRM. If there's a match, the system now knows who's calling, what their account status is, who their assigned rep is, and whether they have any open tickets.

That data changes everything about how the call gets handled.

Instead of a one-size-fits-all menu, the IVR can make routing decisions based on actual business context. An overdue account doesn't need to hear about sales promotions. A VIP customer shouldn't wait in the general queue. A brand new lead who filled out a web form five minutes ago should hear their own name and get connected to the right rep immediately.

The IVR stops being a dumb phone tree and starts acting like a front desk that actually recognizes people when they walk in.

What we built
We used Asterisk as the IVR platform with Kamailio handling SIP routing in front of it. The CRM was Salesforce. Between Asterisk and Salesforce, we set up a small caching service backed by Redis so the IVR wasn't hammering the Salesforce API on every single call.

When a call comes in, the IVR queries the cache layer with the caller's phone number. If there's a recent record, it comes back in about 30-50 milliseconds. If not, the cache layer queries Salesforce, stores the result, and returns it. Either way, the IVR has CRM data before the caller hears anything.

We normalized all phone numbers to E.164 format on both sides. This turned out to be a bigger deal than expected about 40% of initial "caller not found" results were just formatting mismatches between how Asterisk received the number and how Salesforce stored it. Same person, same number, different format. Easy fix once we found it, but it was the single biggest source of lookup failures early on.

The whole lookup-to-greeting path takes under 200 milliseconds. No dead air, no awkward pause before the welcome message.

The five routing paths
After the CRM lookup, every call falls into one of five buckets:
Overdue accounts skip the menu entirely. The system routes them straight to the collections queue. The agent's screen already shows the account details, outstanding balance, and payment history before they even pick up the call. No "can I get your account number," no transfers, no wasted time.

VIP customers get a personalized greeting using their name and connect directly to their assigned account manager. If that person is unavailable, they go to a priority queue with shorter wait times. They never hear the standard five-option menu.

Active regular accounts get the standard menu but with a difference. The agent already has their account pulled up when the call connects. That 30-40 second identification ritual at the start of every call just disappears.

New leads hear a different greeting. Something like "Hi [Name], thanks for reaching out to us." They get routed to the sales rep assigned to that lead in Salesforce. If the lead came from a specific campaign, the rep knows that too before answering.

Unknown callers - people whose number isn't in the CRM - get the original standard menu. Nothing changes for them. The system degrades gracefully instead of breaking.

What changed in the numbers

We measured everything we could over the first 90 days. Some of the improvements were expected, some caught us off guard.

Handle time dropped by about 18%: The biggest contributor was eliminating the account identification step at the start of calls. When the agent already has the account on screen, the conversation starts with the actual issue immediately. Across 2,500 daily calls, those saved seconds add up fast.

Call abandonment went from 12% down to around 7%: Two things drove this. First, eliminating the dead air gap that happened when API lookups were slow (we solved that with the caching layer). Second, callers who got routed directly to the right place didn't have to navigate menus and wait in the wrong queue before getting transferred.

Collections contact rate improved noticeably: Overdue accounts were actually reaching the collections team now instead of getting lost in the general menu. Before, some of those callers would pick "general inquiries," sit in a queue, explain their situation, get transferred to collections, and sit in another queue. A lot of them gave up halfway through. Direct routing removed that entire detour.

New lead response time got faster: Marketing was running paid campaigns that drove phone calls. Previously, those callers were treated like everyone else. Now they were recognized and connected to the right sales rep within seconds. The sales team said it made a real difference in conversion conversations when the rep could greet someone by name and reference the specific thing they'd inquired about.

Agent satisfaction, surprisingly: We didn't measure this formally, but the feedback was consistent. Agents said not having to ask "who am I speaking with" on every call made their job feel less repetitive. Having context before the conversation started let them focus on solving the problem rather than playing detective for the first minute.

The problems we didn't expect

It wasn't all smooth. A few things caught us off guard.

Multiple accounts tied to one phone number: More common than we anticipated, especially with business lines. A single number might be associated with three different accounts in Salesforce. We solved this by defaulting to the most recently active account and giving the caller a quick confirmation: "We found your account under [Company Name]. Press 1 if that's correct, press 2 to search by account number." Worked fine, but we hadn't planned for it initially.

Stale CRM data causing wrong routing: An account marked as "overdue" in Salesforce that had actually just made a payment would still get routed to collections until the CRM record updated and the cache expired. We shortened the cache duration for accounts with recent status changes and added a webhook listener that invalidated the cache when certain Salesforce fields were modified. Took some back and forth to get right.

Agents trusting the screen pop too much: Because the system was accurate 97% of the time, agents started skipping verbal verification entirely. Usually fine, but occasionally the caller was using someone else's phone. We added a soft verification prompt to the agent script for sensitive transactions (payments, account changes) even when the screen pop was populated.

What I'd tell someone considering this

If your IVR handles more than a few hundred calls a day and your business logic depends on who the caller is, the CRM integration is worth doing. The impact on handle time and routing accuracy alone probably justifies the build.

But don't call the CRM API directly from the IVR for every single call. It seems like the obvious approach, and it works in testing, but it won't survive production call volumes. Put a caching layer between them. You'll avoid latency spikes, rate limit issues, and token management headaches.

And spend time on phone number normalization before anything else. It's not glamorous work, but mismatched number formats will quietly tank your lookup accuracy. We lost about two weeks troubleshooting "caller not found" results that turned out to be nothing more than formatting inconsistencies.

The whole project from planning to production took about 6 weeks. If we did it again knowing what we know now, we could probably cut that to four.

I work with the VoIP engineering team at Hire VoIP Developer we build custom IVR Systems and telephony systems, and CRM integrations are a regular part of that work. If you've done something similar, especially with a CRM other than Salesforce, I'd be curious how you handled the data sync and caching side.

Top comments (0)