CSR call audits

Your booking rate is only as honest as the call labels

Our carpet cleaning client pays CSR bonuses off booking rate, and booking rate comes from how each call gets labeled in ServiceTitan. A caller who asks for a price and hangs up should count as an unbooked lead. Labeled "not a lead," it disappears from the math, and the rate goes up.

Nobody can listen to 600 calls every two weeks. So we built something that does, then shows the owner the gap between the official number and the real one.

Built for
Carpet cleaning franchise (40+ locations)
Status
Running every audit cycle
Example flagged callNeeds review

CSR labeled

Not a lead

Audit says

Unbooked lead

Evidence (verified in transcript)

"How much would it be for a living room and the hallway? ... Okay, let me talk to my husband and call you back."

Caller asked for a price on a specific job and didn't book. Under the company's rules that's an unbooked lead, and it counts against the booking rate.

664

office calls answered in the 13-day run

367

of those audited call by call

92.1%

of labels the audit agreed with

26 to 3

mislabels that helped the CSR vs. hurt them

How a call gets audited

The rule we cared about most: the AI never gets the last word. It has to show its work with a quote from the call, a script confirms that quote is real, and a person signs off before anything in ServiceTitan changes. Even then only one correction is allowed, from "Not a lead" to "Unbooked lead." Keeping it that narrow is what makes the owner comfortable letting it write to the system at all.

The audit pipeline

Pull

Every recorded call

From ServiceTitan's call-recordings report, with the label the CSR picked.

Split

CSR and caller separated

Stereo recordings put each side on its own channel, so we always know who said what.

Transcribe

Whisper, run locally

Call audio never leaves our machine for transcription.

Classify

Claude re-labels the call

Against the company's own call-reason rules, with a quote from the call as evidence.

Check

Quote must match word for word

If the evidence isn't actually in the transcript, the finding is thrown out.

Review

A person signs off

Flagged calls get a human listen before anything changes.

Fix

Corrected in ServiceTitan

Only one kind of change is allowed: "Not a lead" to "Unbooked lead."

Report

Dashboard updates

Official vs. adjusted booking %, by CSR and by week.
Nothing gets written back to ServiceTitan until a person has looked at it.

What the first full run turned up

92% agreement sounds great, and honestly it is. These are good CSRs. The other 8% is where it gets useful. When labels were wrong, they were wrong in the CSR's favor 26 times out of 29.

Ten calls were corrected in ServiceTitan after review. The office-wide booking rate moved from 84.3% to 82.0%. Not a scandal. Just the real number, which is the one you want to pay bonuses on and the one you want to measure an AI phone agent against.

One 13-day run, October 2026

Office booking rate

Official (as labeled)84.3%
Adjusted (after audit)82.0%

The audit agreed with the CSR's label on 92.1% of calls.

Which way the mislabels leaned

26 made the CSR look better 3 made them look worse
Mislabels almost always lean the same direction. Calling an unbooked lead "not a lead" takes it out of the denominator, and the booking rate goes up.

What the owner sees

A password-protected page in the same dashboard as their ad spend: official vs. adjusted booking % for each CSR, label accuracy, a list of every mislabel with the quote that proves it, and a week-by-week trend. When someone disputes a number, the argument turns into a 30-second listen.

dashboard / csr-audit

CSR Call Audit

Oct 5 to Oct 18 · 4 locations

Demo data

Calls audited

402

Label accuracy

93.0%

Official booking

85.8%

Adjusted booking

80.3%

By CSR

CSROfficialAdjustedMislabels
Avery M.88.5%82.1% ▼6.36 helped / 0 hurt
Jordan T.85.7%82.2% ▼3.54 helped / 1 hurt
Morgan L.86.4%78.1% ▼8.37 helped / 0 hurt
Riley S.81.4%78.7% ▼2.73 helped / 1 hurt
Casey D.86.3%80.0% ▼6.35 helped / 1 hurt

Weekly trend

Official Adjusted
75%80%85%90%Sep 21: official 86.1%Sep 28: official 85.7%Oct 5: official 84.9%Oct 12: official 84.6%Sep 21: adjusted 81.2%Sep 28: adjusted 82.3%Oct 5: adjusted 82.6%Oct 12: adjusted 83.1%Sep 21Sep 28Oct 5Oct 12

The gap is closing as labels get more careful.

Flagged calls

  • Morgan L."What would three bedrooms run me? ... Okay, I'll think about it."Not a lead→Unbooked lead
  • Avery M."Can you do the sectional too? ... Let me check with my wife first."Not a lead→Unbooked lead
  • Riley S."I'm just calling to update my card on file."Unbooked lead→Not a lead

A demo copy of the real page. Names and numbers are made up.

What it runs on

  • ServiceTitan call recordings
  • Whisper (local transcription)
  • Claude (Anthropic)
  • Node.js + Python
  • Next.js dashboard on Vercel

Questions we get about this one

Is this about catching CSRs doing something wrong?+

Mostly it's about getting the number right. Plenty of mislabels are honest: the call was messy, the caller was vague, the CSR was moving fast. But if bonuses are paid off booking rate, a few wrong labels a week adds up to real money paid on numbers that aren't true. Owners and CSRs both deserve a number they can trust.

How accurate is the AI's label?+

Every finding has to quote the call word for word, and we check that quote against the transcript in code. If the quote isn't there, the finding is thrown out. On top of that, nothing changes in ServiceTitan until a person has listened to the flagged call.

Do you need ServiceTitan?+

This version is built around ServiceTitan's call recordings and call-reason labels. Any phone system that keeps stereo recordings and some kind of call outcome could work the same way.

Where does the call audio go?+

Transcription runs on our own machine with Whisper, so the recordings aren't sent to an outside transcription service. Only the text goes to the model for labeling.

Want one of these for your shop?

Most of what's on this page started as a 30-minute call about something that was bugging the owner. Tell us what's bugging you.