CSAT driver-analysis worksheet
A spreadsheet-grade worksheet for turning a folder of CSAT survey responses into a ranked list of the operational drivers that actually move your score — use it when you know your CSAT number but not what to fix.
CSAT tells you how satisfied customers are. It does not tell you why. This worksheet is how you turn a folder of survey responses into a ranked list of the operational things that actually move the score — so you spend next quarter fixing the two drivers that matter instead of the six that don't.
Treat CSAT as an output, not a dial you push directly. You improve it by improving the inputs that feed it, which means first finding out which inputs those are — COPC makes this case for treating CSAT as an output metric and using key-driver analysis to find the inputs. What follows is a manual, spreadsheet version of that. It won't match a regression a data scientist would run, but it gets a small team most of the way with a pivot table and an afternoon. If you have someone who can run a proper regression, let them — this worksheet still frames the inputs they'll test.
Section 0 — Frame the analysis
Lock these down before you touch data. Changing them halfway makes every number incomparable.
- The exact survey question and scale:
[e.g. "How satisfied were you?" 1-5] - What counts as "satisfied": pick one definition — top-2-box (4s and 5s) or mean — and keep it all the way through
- The population:
[channel / queue / date range] - Minimum responses: aim for
[200+]. Below ~100 total, the driver buckets get too thin to trust - Response rate noted, and who's missing. A low response rate skews the sample toward the very happy and very angry — read csat-response-rate-is-lying before you generalise a bucket
Section 1 — Inventory the candidate drivers
List every operational attribute you can attach to a survey response. Keep it to things you can actually change or route on: "the customer was already angry" is not a driver you can act on; "we made them repeat themselves three times" is. Edit the examples below to your reality.
| Candidate driver | How to bucket it | Data source | Hypothesised direction |
|---|---|---|---|
| Resolved on first contact (FCR) | yes / no | reopen + touch data | resolved → higher |
| Full resolution time | [<4h] / [4-24h] / [>24h] | ticket timestamps | faster → higher |
| First response time | [<1h] / [1-8h] / [>8h] | timestamps | faster → higher |
| Number of replies (touches) | 1 / 2-3 / 4+ | thread length | fewer → higher |
| Transferred or escalated | yes / no | routing log | transferred → lower |
| Reopened | yes / no | ticket status | reopened → lower |
| Channel | chat / email / phone / self-serve | helpdesk | — (test it) |
| Issue type / topic | [your tags] | ticket tags | varies |
| Agent or team | [id] | assignment | — (handle with care) |
| Customer segment | new / established / [VIP] | CRM | — |
| AI involvement | none / AI-only / AI-then-human | bot logs | — (test it) |
Rule: a driver you can't influence is trivia, not a driver. Cut it.
Section 2 — Build the analysis table
Export one row per survey response. Columns: the CSAT score, plus one column per driver holding that response's bucket. This is the sheet everything else pivots off.
| Response | Score | FCR | Resolution time | Touches | Escalated | Channel | Issue type |
|---|---|---|---|---|---|---|---|
| #48213 | 5 | yes | [<4h] | 1 | no | chat | billing |
| #48197 | 2 | no | [>24h] | 4+ | yes | integration | |
| ... |
Compute your overall baseline first — the single % satisfied across every row. Every driver gets compared against this number.
Section 3 — Driver impact table (the core)
For each driver, pivot the score by bucket. A driver only matters if its gap is large and common — a 30-point gap on 2% of tickets is a footnote; a 12-point gap on 40% of tickets is your quarter. Rank by Priority = gap x prevalence.
| Driver | Bucket | n | % satisfied | Gap vs baseline | Prevalence | Priority |
|---|---|---|---|---|---|---|
| FCR | no | 140 | 54% | -28 pts | 22% | 6.2 |
| Touches | 4+ | 95 | 58% | -24 pts | 15% | 3.6 |
| Resolution time | [>24h] | 210 | 66% | -16 pts | 33% | 5.3 |
| Channel | phone | 60 | 74% | -8 pts | 9% | 0.7 |
| Escalated | yes | 80 | 70% | -12 pts | 12% | 1.4 |
(Baseline in this example ≈ 82% satisfied. Fill your own.)
- Every driver from Section 1 pivoted
- Baseline calculated once and reused
- Buckets under
[30]responses flagged as unreliable, not ranked - Sorted by Priority, highest first
Section 4 — Read the verbatims
Numbers rank the drivers; comments explain them. Pull the free-text from the lowest-scoring bucket of your top-priority driver and tally the themes.
| Theme | Count | Representative quote (trimmed) | Fixable by us? |
|---|---|---|---|
| Had to re-explain the issue | [n] | "third person I told the same thing to" | yes — context handoff |
| Answer was wrong first time | [n] | "the fix they gave broke it worse" | yes — KB / training |
| No update while waiting | [n] | "heard nothing for two days" | yes — proactive status |
| Policy the customer hates | [n] | "can't believe you charge for that" | no — flag to product |
The "Fixable by us?" column is the whole point: it splits problems you own from problems you can only escalate.
Section 5 — Correlation is not cause
Before you act, stress-test the top driver. Most first-pass findings are a proxy for something else.
- Confounder check. Does the gap survive within one issue type? If "phone scores lower" disappears once you hold issue type constant, the real driver was issue complexity, not the channel
- Reverse causation. Did the bad outcome cause the extra touches, or the extra touches cause the bad outcome? Often both — note which you can break
- Selection. Does this bucket have a different response rate than the rest? A bucket only angry people answer will look worse than it is
- Noise. Is the gap bigger than the swing you'd see from
[30]-response buckets bouncing around week to week? If not, park it
Section 6 — Pick and act
Choose one or two drivers — the top of your Priority column that survived Section 5. For each, commit to a change and the metric you'll watch.
| Driver | Hypothesis | Change we'll make | Metric to watch | Re-check date |
|---|---|---|---|---|
FCR on [issue type] | Repeat contacts drive the -28pt gap | [new macro / KB fix / routing rule] | FCR + CSAT for that queue | [date] |
Resolution time [>24h] | Slow closes drag the mid-tier | [backlog triage / staffing] | % closed <24h | [date] |
- No more than two drivers picked — a plan that fixes everything fixes nothing
- Each change names an owner and a date
- The metric you'll watch is the driver, not CSAT itself (CSAT moves last)
Section 7 — Re-run cadence
- Re-run quarterly with the same definitions so the numbers compare
- After a change ships, confirm the acted-on driver's gap actually narrowed before claiming the win
- Retire drivers that never move; add new ones as the product and channels change
Effort-shaped drivers — FCR, repeat touches, re-explaining — tend to dominate this table for a reason. The classic finding is that reducing customer effort predicts loyalty better than trying to delight people (HBR, Stop Trying to Delight Your Customers). And tolerance for a single bad experience is thin: Zendesk's 2025 CX Trends report found 63% of consumers willing to switch to a competitor after just one. Driver analysis is how you find those specific bad experiences — by name, by ticket type, by queue — while you can still fix them.
Continue exploring