Back to The Times of Claw

How to Track Customer Health Score in DenchClaw

Learn how to build and track customer health scores in DenchClaw CRM using product usage, support signals, and engagement data to predict churn.

Mark Rachapoom
Mark Rachapoom
·8 min read
How to Track Customer Health Score in DenchClaw

How to Track Customer Health Score in DenchClaw

Customer health scores are the closest thing SaaS companies have to a churn crystal ball. When you're tracking the right signals — product usage, support volume, NPS, engagement — you can see an account going sideways 60-90 days before they actually cancel. That's enough time to intervene.

DenchClaw lets you build a custom health scoring model in your local CRM, store scores in DuckDB alongside all your other customer data, and have your AI agent surface at-risk accounts before your team is even awake.

What Goes Into a Health Score#

There's no universal health score formula — it depends on your product and business model. But the common signal categories are:

  1. Product usage — login frequency, feature adoption, session depth
  2. Support signals — ticket volume, unresolved issues, escalations
  3. Relationship health — NPS/CSAT, QBR completion, executive sponsor engagement
  4. Financial signals — overdue invoices, downgrades, payment failures
  5. Engagement signals — email open rates, webinar attendance, community activity

In DenchClaw, each of these becomes fields on your accounts object — and the health score is a calculated number derived from them.

Step 1: Define Your Health Score Model#

Start by deciding what signals matter for your business and how to weight them. A simple model:

SignalWeight
Sessions last 30 days30%
Feature adoption score25%
Days since last support escalation20%
NPS score15%
Contract payment status10%

Simpler is better when you're starting out. You can always refine the model later.

Step 2: Add Health Score Fields to Your Accounts Object#

Tell the agent:

"Add these fields to the company object: Health Score (number 0-100), Health Tier (enum: Green/Yellow/Red), Last Health Update (date), NPS Score (number), Support Tickets Open (number), Feature Adoption Score (number 0-100), Sessions Last 30d (number), Payment Status (enum: Current/Overdue/Failed)"

Your .object.yaml additions:

- name: Health Score
  type: number
- name: Health Tier
  type: enum
  options: [Green, Yellow, Red]
- name: Last Health Update
  type: date
- name: NPS Score
  type: number
- name: Support Tickets Open
  type: number
- name: Feature Adoption Score
  type: number
- name: Sessions Last 30d
  type: number
- name: Payment Status
  type: enum
  options: [Current, Overdue, Failed]

Step 3: Build the Scoring Formula#

The health score calculation runs as a SQL query in DuckDB. Here's a working example for the 5-signal model above:

-- Calculate health score for all accounts
WITH signal_values AS (
  SELECT 
    e.id as entry_id,
    MAX(CASE WHEN f.name = 'Sessions Last 30d' THEN ef.value::int ELSE 0 END) as sessions,
    MAX(CASE WHEN f.name = 'Feature Adoption Score' THEN ef.value::int ELSE 0 END) as adoption,
    MAX(CASE WHEN f.name = 'Support Tickets Open' THEN ef.value::int ELSE 0 END) as tickets,
    MAX(CASE WHEN f.name = 'NPS Score' THEN ef.value::int ELSE 0 END) as nps,
    MAX(CASE WHEN f.name = 'Payment Status' THEN ef.value ELSE 'Current' END) as payment
  FROM entries e
  JOIN entry_fields ef ON e.id = ef.entry_id
  JOIN fields f ON ef.field_id = f.id
  WHERE e.object_id = (SELECT id FROM objects WHERE name = 'company')
  GROUP BY e.id
),
scored AS (
  SELECT 
    entry_id,
    -- Sessions: 0 = 0pts, 1-5 = 15pts, 6-15 = 25pts, 16+ = 30pts
    CASE 
      WHEN sessions = 0 THEN 0
      WHEN sessions <= 5 THEN 15
      WHEN sessions <= 15 THEN 25
      ELSE 30
    END +
    -- Adoption score: 0-100 scaled to 0-25
    LEAST(25, adoption * 25 / 100) +
    -- Tickets: 0 = 20pts, 1-2 = 15pts, 3-5 = 8pts, 6+ = 0pts
    CASE
      WHEN tickets = 0 THEN 20
      WHEN tickets <= 2 THEN 15
      WHEN tickets <= 5 THEN 8
      ELSE 0
    END +
    -- NPS: <0 = 0pts, 0-6 = 5pts, 7-8 = 10pts, 9-10 = 15pts
    CASE
      WHEN nps < 0 THEN 0
      WHEN nps <= 6 THEN 5
      WHEN nps <= 8 THEN 10
      ELSE 15
    END +
    -- Payment: Current = 10pts, Overdue = 3pts, Failed = 0pts
    CASE payment
      WHEN 'Current' THEN 10
      WHEN 'Overdue' THEN 3
      ELSE 0
    END as health_score
  FROM signal_values
)
SELECT entry_id, health_score,
  CASE 
    WHEN health_score >= 70 THEN 'Green'
    WHEN health_score >= 40 THEN 'Yellow'
    ELSE 'Red'
  END as health_tier
FROM scored;

Step 4: Automate Score Recalculation#

Tell the agent to run the scoring query automatically:

"Every morning at 7am, recalculate health scores for all accounts using the scoring formula, update the Health Score and Health Tier fields, update the Last Health Update field to today, and message me if any account moved from Green to Yellow or Yellow to Red"

The agent creates a daily cron job. You'll get a Telegram message like:

"⚠️ Health score changes overnight:

  • Acme Corp: Green → Yellow (sessions dropped to 3 last 30d)
  • Beta Inc: Yellow → Red (2 open tickets + payment overdue)"

Step 5: Build Health Score Views#

Create views organized by health tier:

Red Accounts (Intervention Needed)#

- name: Red Accounts
  filters:
    - field: Health Tier
      operator: equals
      value: Red
  sort:
    - field: Contract Value
      direction: desc

Recently Declined Accounts#

Ask the agent: "Create a view showing accounts whose health score dropped by more than 15 points in the last 7 days"

For this, you'll need to store previous health scores — add a Previous Health Score field and a Score Delta field that the cron job updates each run.

Green VIPs (Expansion Targets)#

- name: Healthy High Value
  filters:
    - field: Health Tier
      operator: equals
      value: Green
    - field: Contract Value
      operator: greater_than
      value: 25000
  sort:
    - field: Health Score
      direction: desc

Step 6: Build the Health Score Dashboard#

Ask the agent to build a Dench App:

"Build a health score dashboard showing: accounts by health tier (donut chart), health score distribution (histogram), top 5 at-risk accounts by contract value, and health tier breakdown by industry segment"

// Health tier distribution
const tiers = await dench.db.query(`
  SELECT ef.value as tier, COUNT(*) as count,
    SUM(cv.value::decimal) as arr
  FROM entry_fields ef
  JOIN fields f ON ef.field_id = f.id AND f.name = 'Health Tier'
  JOIN entry_fields cv ON ef.entry_id = cv.entry_id
  JOIN fields fcv ON cv.field_id = fcv.id AND fcv.name = 'Contract Value'
  GROUP BY ef.value
`);

The dashboard gives your CS team an at-a-glance view of portfolio health without running queries.

Step 7: Health Score-Triggered Workflows#

Use health scores to trigger customer success playbooks:

"When an account drops to Red tier, create a task in my tasks object: 'CS intervention needed for [Account Name]' with a due date of 48 hours from now, and notify the account owner via Telegram"

"When an account in Red tier hasn't had an outreach logged in 7 days, send me a reminder with the account details and their last interaction date"

This closes the loop from data → alert → action.

Keeping Your Model Honest#

A common mistake: building a health score model and never validating it. Every quarter, look at accounts that churned and check what their health scores looked like 90 days prior. If your Red accounts are still churning but Yellow accounts are too, your thresholds need adjustment.

Ask the agent: "Show me the health scores of the 5 accounts that churned this quarter, as of 90 days before their churn date"

This kind of lookback analysis is trivial with DuckDB and a timestamped health history — another reason to track Last Health Update and consider keeping a health_history table over time.

Frequently Asked Questions#

What's a good starting health score threshold for Green/Yellow/Red?#

A common starting point: 70+ = Green, 40-69 = Yellow, under 40 = Red. But your business may be different. Run your model on historical data first, check which threshold would have flagged your actual churned accounts, and adjust accordingly.

How often should health scores be recalculated?#

Daily is sufficient for most teams. Real-time scoring adds complexity without proportional benefit — most customer health signals don't change hour by hour. Daily recalculation catches meaningful trend shifts quickly enough to act.

Can I track health score history over time?#

Yes. Create a health_history table in DuckDB and INSERT a new row each time scores are recalculated. This gives you trend lines — you can track whether an account's health is improving or deteriorating over weeks, not just its current state.

What if I don't have NPS data for all accounts?#

Default missing values to a neutral score (e.g., treat unknown NPS as 7 — middle of the range). Flag accounts with no NPS data as "survey needed." Don't penalize accounts for missing data, but do track which accounts need a survey.

Can DenchClaw calculate health scores without product usage data?#

Yes, though the score will be less predictive. Even with just support ticket volume and payment status, you can build a meaningful first version. Add usage signals when you can pipe them in.

Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →

Mark Rachapoom

Written by

Mark Rachapoom

Building the future of AI CRM software.

Continue reading

DENCH

© 2026 DenchHQ · San Francisco, CA