Skip to content
SlashClone

Customer health score

@usagemetrics/customer-health-score

Score customer health from usage, support, and billing signals with weights you can read and edit. Bands every account green, yellow, or red, names the top drivers, tracks change since the last score, and flags at-risk accounts renewing soon. Works from one CSV.

SkillDatav1.0.0 (latest)Tested
Activity
New: be the first to try it
  1. 1---
  2. 2name: customer-health-score
  3. 3description: Build a customer health score from usage, support, and billing signals with an editable weights file, band accounts green, yellow, or red, explain the drivers for each, and flag at-risk accounts that renew soon. Use when the user asks for a health score, "which customers are at risk", account health for a customer success review, a red/yellow/green list, or wants to combine product usage with tickets and billing data.
  4. 4license: MIT
  5. 5---
  6. 6
  7. 7# Customer health score
  8. 8
  9. 9A health score people trust is one they can read. Every signal, its weight, and what counts as good or bad live in one small JSON file the team owns. The script does the math the same way every week, and every account gets its top drivers so the score leads to an action.
  10. 11## Inputs
  11. 131. **`data/accounts.csv`**: one row per account. Required: `account_id`. Useful: `name`, `arr`, `renewal_date`, `previous_score` (last run's score, for change). Then one column per signal, for example:
  12. 15 | Signal column | From | Example |
  13. 16 | --- | --- | --- |
  14. 17 | `seat_utilization` | active users / paid seats, last 30 days | 0.62 |
  15. 18 | `usage_trend` | change in events, last 28 days vs prior 28 | -0.12 |
  16. 19 | `core_feature_users` | users of the key feature, last 30 days | 4 |
  17. 20 | `open_tickets`, `urgent_tickets_90d`, `csat` | help desk export | 2, 0, 4.4 |
  18. 21 | `days_past_due` | billing system | 32 |
  19. 22 | `exec_sponsor` | CRM (1 = yes) | 1 |
  20. 24 The `saas-usage-dashboard` JSON output has usage trend and active users per account; use it to fill usage columns.
  21. 252. **`data/health-weights.json`**: copy `examples/weights.json` if the user has none. Each signal has `column`, `weight`, `bad`, `good`, and an optional `label` and `group`. A value at `bad` scores 0, at `good` scores 100, linear in between and clamped. `good` can be lower than `bad` (for tickets and days past due).
  22. 27## Steps
  23. 291. Check which signal columns exist and how many accounts have each. Signals with no column are skipped; tell the user.
  24. 302. Review the weights with the user before the first run. Defaults: usage 50%, support 25%, billing 15%, relationship 10%. Ask whether that matches how they lose customers; adjust in `data/health-weights.json`.
  25. 313. Run:
  26. 33 ```bash
  27. 34 node scripts/health.mjs data/accounts.csv --weights data/health-weights.json --as-of 2026-11-01 --out out/health
  28. 35 ```
  29. 374. Report from `out/health.md`: accounts and ARR per band, the priority accounts (red, or yellow and down 10+ points, renewing within 90 days), and the biggest drops.
  30. 385. **Sanity check with the user:** name two accounts they consider healthy and two they worry about, and see where they landed. If the score disagrees with the team's judgment, adjust weights or thresholds, not individual scores, and rerun.
  31. 396. Remind the user to bring this run's `score` column (in `out/health.csv`) into next run's accounts file as `previous_score`, so changes show up.
  32. 407. For each priority account, offer the `churn-risk-review` kit to plan the save.
  33. 42## Rules the script follows
  34. 44- Score = weighted average of the signals that have a value. Missing values are left out and the weights renormalized.
  35. 45- Accounts with data for less than 60% of the total weight (`min_weight_coverage`) are not banded; they show as `unknown` so a thin record never looks healthy.
  36. 46- Bands default to green 70+, yellow 45 to 69, red under 45 (`bands` in the weights file).
  37. 47- Drivers are the signals scoring under 60, ordered by how many points they cost.
  38. 49## Output template
  39. 51```markdown
  40. 52**Health, Nov 1:** 5 green ($274k), 3 yellow ($138k), 2 red ($50k), 1 not enough data.
  41. 53Priority (renewing in 90 days): Bluebird Labs (25, down 39; usage trend -68%, seat use 35%), ...
  42. 54Biggest drops: Bluebird -39, Fable -37, Harbor -33.
  43. 55```
  44. 57## Guardrails
  45. 59- A score is a prompt for a conversation, not a verdict. Never present it to the customer.
  46. 60- Do not edit a single account's score by hand. Change the weights file and rerun, so every account is treated the same way.
  47. 61- Do not paste contact names or ticket text into chat.