Metric

What is a customer health score, and how do you build one?

Definition

A customer health score is a composite indicator of how likely an account is to keep paying and expand — usually a 0–100 number built from product usage, support experience, relationship depth, and commercial signals. It is a model, not a measurement: the score is only as good as its components, its weighting, and your ability to explain both to the CSM who has to act on it.

Formula: Health score = Σ (normalized component score × component weight), with weights summing to 1

What data do you need?

  • Product usage at account grain (active users, key events, breadth of feature use)
  • Adoption relative to entitlement — seats used vs. seats purchased
  • Support signals: open tickets, escalations, response and resolution times
  • Relationship signals: exec sponsor present, last QBR, last touchpoint
  • Commercial signals: payment status, contract length, expansion history
  • A scored_at date so every score is a point-in-time row, never overwritten

SQL pattern

A transparent weighted health score (PostgreSQL)PostgreSQL
-- Each component is normalized to 0-100 first, then weighted.
-- Keep the components as columns so a CSM can see *why* a score moved.
WITH usage AS (
  SELECT
    account_id,
    SUM(active_users) AS active_user_days,
    COUNT(DISTINCT usage_date) FILTER (WHERE active_users > 0) AS active_days
  FROM product_usage_daily
  WHERE usage_date >= CURRENT_DATE - INTERVAL '28 days'
  GROUP BY account_id
), components AS (
  SELECT
    a.account_id,
    -- Adoption: seats active vs. seats purchased, capped at 100.
    LEAST(
      100.0 * COALESCE(u.active_user_days, 0)
        / NULLIF(a.licensed_seats * 28.0, 0), 100.0
    ) AS adoption_score,
    -- Engagement: share of the last 28 days with any activity.
    100.0 * COALESCE(u.active_days, 0) / 28.0 AS engagement_score,
    -- Support: 100 with no escalations, falling 20 points per escalation.
    GREATEST(100.0 - 20.0 * COALESCE(t.escalations_90d, 0), 0.0)
      AS support_score,
    -- Relationship: decays after 90 days without a logged touchpoint.
    GREATEST(
      100.0 - (CURRENT_DATE - COALESCE(a.last_touchpoint_date,
        CURRENT_DATE - 180)) * 100.0 / 180.0, 0.0
    ) AS relationship_score
  FROM cs_accounts a
  LEFT JOIN usage u USING (account_id)
  LEFT JOIN support_ticket_rollups t USING (account_id)
  WHERE a.status = 'active'
)
SELECT
  account_id,
  ROUND(adoption_score, 1) AS adoption_score,
  ROUND(engagement_score, 1) AS engagement_score,
  ROUND(support_score, 1) AS support_score,
  ROUND(relationship_score, 1) AS relationship_score,
  ROUND(
    0.35 * adoption_score
    + 0.25 * engagement_score
    + 0.20 * support_score
    + 0.20 * relationship_score, 1
  ) AS health_score
FROM components
ORDER BY health_score;

Common pitfalls

Reporting a vendor's black-box score as the company health metric.→ Re-derive the components in the warehouse. Vendor scoring rules can be changed in an admin screen without notice, which rewrites the meaning of your trend line retroactively.
Overwriting each account's score in place.→ Append a row per account per scoring run with a scored_at date — movement is the useful signal, and you cannot measure movement you deleted.
Weighting components by intuition and never revisiting it.→ Back-test: check whether accounts that churned actually scored lower 90 days out. If they didn't, the weights are decoration.
Scoring tiny accounts and enterprise accounts on one scale.→ Normalize usage by entitlement (seats, contracted volume) and consider separate weight sets per segment.

Where does this metric apply?

This metric commonly uses data from Gainsight, Vitally, Planhat, Salesforce, HubSpot, plus any warehouse models built on account, subscription, and product-usage tables at the same grain.

Dashboards

Integrations

Metrics

Analytics

FAQ

How many components should a health score have?
Four to six. Fewer and it tracks a single behavior; more and no one can explain a 6-point drop. Every component should map to an action a CSM can actually take.
How often should scores be recalculated?
Daily is typical, weekly is fine. What matters more is the lookback window inside each component — a 28-day usage window smooths weekends and holidays, while a 7-day window will make every December look like a churn wave.