Automation · Customer success
How to build customer health signals
A score says 82 and the customer churns six weeks later. Here is the model behind a health signal you can defend, the prompts that build it, and what it takes to run in production.
Built with Tray Headless
- System Amplitude
- System Zendesk
- Step Score per category
- Step Back-test
- System Salesforce
Categories stay visible instead of collapsing into one number, and the weights are back-tested against accounts that actually churned.
The short answer
What is a customer health signal?
There are four parts to customer health: a small set of signals chosen because they predict churn instead of because they were available, category scores that stay visible instead of collapsing into one number, weights back-tested against customers who actually left, and alerts on movement instead of on level. The part that goes wrong most often is the single number. A score of 62 tells nobody what to do, and two accounts at 62 can need completely different conversations.
What matters here
- Choose signals because they predicted churn in your data, not because they were easy to get.
- Never collapse to one number alone. Two accounts scoring 62 can need entirely different conversations.
- Back-test against customers who actually left. A score nobody validated is a shared opinion with a colour attached.
- Alert on a category moving, not on a total crossing a line. The total moves slowly and hides the change.
- Track whether flagged accounts actually churned. If they did not, the model is decoration.
Who this is for
You run customer success operations. There is a health score somewhere, nobody quite trusts it, and the accounts that churn were usually green the month before.
How it works in practice
The path from a customer going quiet to somebody doing something about it.
- 1
Signals are gathered per category
Usage, support, engagement and commercial, kept separate rather than merged on collection.
- 2
Each category is scored on its own
So a healthy product user with a support problem does not average out to fine.
- 3
Weights come from a back-test
Fitted against accounts that actually churned, not chosen in a workshop.
- 4
The categories stay visible on the record
Alongside the total, because the total says whether and the categories say why.
- 5
Alerts fire on a category moving
Not on the total crossing a threshold, which happens late and slowly.
- 6
Every flag is tracked to an outcome
Did the flagged account churn. That number decides whether anybody should trust this.
What a health signal is made of
Four parts, though the third is what separates a model from a colour.
Predictive signals
Chosen from what actually preceded churn in your history: usage decline, support escalations, champion departure, engagement gaps and payment behaviour.
Visible categories
Usage, support, engagement, commercial. Each scored and shown, because the reason is more actionable than the verdict.
Back-tested weights
Fitted against accounts that left. Weights chosen by committee encode what people believe, not what happened.
Outcome tracking
Whether flagged accounts churned, and whether unflagged ones did. The second number is the one that finds the missing signal.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up, then look at who actually left
The history is the only honest source of weights.
Headless skills
build-workflowtray-patternsUse build-workflow. The systems in play are Snowflake and Salesforce, or whatever we run in those seats. Before building a score, pull the last two years of churned accounts and show me, for each, what the six months before looked like: usage trend, support volume and escalations, meeting frequency, payment behaviour, and whether a named champion left. I want to see which of those actually moved before churn and how far ahead. That is where the weights come from. Anything that did not move should not be in the model regardless of how sensible it sounds.
- 2
Score categories separately, and keep them separate
Averaging is how a real problem disappears.
Headless skills
build-workflowUse build-workflow. Score four categories independently: Usage: active users against seats, breadth, and direction of travel Support: ticket volume against the norm for that size, escalations, and satisfaction where we have it Engagement: days since a meeting, executive contact, champion still present Commercial: payment behaviour, contract value trend, open expansion Score each 0 to 100 and store all four on the account alongside the total. Do not let a good category hide a bad one. An account with usage at 90 and support at 20 averages to fine and is not fine, and the categories are the only thing that shows it.
- 3
Fit the weights against real churn
Otherwise the model encodes what people believe instead of what happened.
Fit the category weights against the churned cohort rather than choosing them in a workshop. Then back-test: run the scoring over historical data and check how many accounts that churned were flagged, how far in advance, and how many that were flagged did not churn. Report both error types. A model that flags everything catches every churn and is useless. A model that flags nothing looks precise and is also useless. Show me the back-test before this goes near a customer success team. A health score nobody validated is a shared opinion with a colour attached, and it takes one wrong call for people to stop looking at it.
The false positive rate is the one that decides adoption. If CSMs chase five healthy accounts for every real one, they stop chasing.
- 4
Alert on movement in a category
The total moves late and slowly. Categories move first.
Headless skills
tray-gotchasUse tray-gotchas, then alert on movement instead of level: A category dropping more than a band in a period Two or more categories declining together, which is a stronger signal than one falling further Any decline on an account with a renewal inside two quarters A champion leaving, which should alert on its own regardless of score Route to the account owner and the customer success manager with which category moved and what changed inside it. Never alert only on the total. It moves last, by which point the conversation is a rescue, not a check-in.
- 5
Track outcomes, and be willing to delete signals
A model nobody measures becomes decoration within two quarters.
For every flag, record what happened: nothing, intervention, saved, churned. Report quarterly: churn rate among flagged versus unflagged accounts, average warning time before churn, false positive rate per signal, and accounts that churned without ever being flagged. That last list is the most useful thing here. It is where the missing signal is, and it is the only way the model improves. Retire any signal whose weight fits to near zero on the back-test. A score built from twelve inputs where four do the work is harder to trust and no more accurate.
- 6
Prove it works, then hand the weights over
Because the model changes as the product and the segments do.
Run the per-step schema checks and the whole-workflow audit before this touches production. Then open the same workflow in Tray Build so customer success operations can adjust the category weights and the alert bands in the visual canvas, and re-run the back-test after every change rather than trusting that it still holds.
What it connects to
Health is assembled from four systems and lands in the one where relationships live.
Snowflake
Hold the history the back-test runs against, and compute the category scores where that is cheap.
Reads and writes
Salesforce
Write the four category scores and the total as read-only fields, and read contract and renewal context.
Reads and writes
Zendesk
Read ticket volume, escalations and satisfaction, which is the support half of the score.
Reads
Amplitude
Read usage and its direction, which is usually the earliest signal that anything is wrong.
Reads
Slack
Alert the account owner on a category moving, with the specific change instead of a new number.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, Google BigQuery, Microsoft Teams, Jira, Looker or HubSpot.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
People make retention decisions on this. An unvalidated score is worse than none.
It runs on the platform, not on your laptop
Scoring across four sources and the periodic back-test run on the same engine, with history for every score change.
Every score is reconstructable
The inputs and the weight version behind each score. When somebody disputes a red account, that is the answer.
Credentials are held by the platform, never hardcoded
Four systems, four authentications, each read-only and scoped. A scoring workflow needs to read a great deal and write almost nothing.
Customer success owns the weights
Category weights and alert bands open in Tray Build, with the back-test re-run after every change instead of assumed.
Outcomes are tracked or the model rots
Flagged against churned, every quarter. A health score nobody validates becomes decoration in about two quarters.
Questions people ask
Why not a single health score?
Because 62 tells nobody what to do, and two accounts at 62 can need completely different conversations. The total says whether and the categories say why.
Why back-test?
Because weights chosen in a workshop encode what people believe, not what happened. Fitting against accounts that actually left is the only thing that makes the score defensible when somebody disputes a red flag.
Why alert on movement, not the total?
Because the total moves last and slowly. A category dropping a band is an early warning; the total crossing a threshold usually means the conversation is now a rescue.
What is the most useful report?
Accounts that churned without ever being flagged. That list is where the missing signal is, and it is the only thing that improves the model.
When should a signal be removed?
When the back-test fits its weight to near zero. A score built from twelve inputs where four do the work is harder to trust and no more accurate.
Vibe-coding app guides
Vibe-code an entire app with Helix
This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.
How to build a customer health dashboard (opens helix.tray.ai in a new tab)
Related guides
Customer success
How to build a product usage to CRM sync
Send the three signals that change a conversation, aggregated and labelled, without turning the CRM into an analytics tool. The Headless prompts that build it.
Customer success
How to build a closed-won to onboarding handoff
Carry what was promised, not only what was sold. Generate the plan from the deal, and start the clock at close. The Headless prompts that build it.
Customer success
How to build an NPS and survey to CRM sync
Attach responses to the account and the person, route detractors before they escalate, and stop surveying people you just surveyed. The prompts that build it.
Last reviewed September 2026.