Integration · Customer success
How to build a product usage to CRM sync
A rep opens a renewal call believing the customer is happy, and logins have been falling for two months. Here is how usage reaching the account team actually works, the prompts that build it, and what running it demands.
Built with Tray Headless
- System Amplitude
- System Snowflake
- Step Aggregate per account
- Step Label the signal
- System Salesforce
Aggregation happens in the warehouse and only labelled signals cross into the CRM, which is what stops it becoming an analytics tool.
The short answer
What is a product usage to CRM sync?
There are four parts to a product usage to CRM sync: aggregation done in the warehouse rather than in the CRM, a small number of labelled signals instead of raw metrics, a trend instead of a snapshot, and alerts on movement rather than on level. The mistake that costs most is sending too much. A CRM holding forty usage fields is one where nobody knows which three matter, and reps ignore all of them.
What matters here
- Aggregate outside the CRM. It is a system of record for relationships, not an analytics engine, and it performs like one when you try.
- Send three signals, not forty fields. A rep scanning an account reads a label; they skip a table of numbers.
- Label, not number. Adoption falling is actionable; a 12% decline in weekly active users is homework.
- Send the trend. A snapshot cannot distinguish a small customer who is thriving from a large one who is leaving.
- Alert on movement, not on level. A low number that has always been low is a segment, not a problem.
Who this is for
You run customer success operations or revenue operations. Product data lives in analytics, the account team lives in the CRM, and the two only meet when somebody builds a slide for a QBR.
How it works in practice
What happens between a customer using the product and a rep knowing about it.
- 1
Events land in the warehouse, not the CRM
Raw event volume belongs where it can be aggregated cheaply.
- 2
Aggregation happens per account, per period
Weekly and monthly rollups on a small set of metrics that were chosen deliberately.
- 3
A handful of signals are derived and labelled
Adoption, breadth, depth and direction of travel, expressed as states instead of figures.
- 4
Only the labels cross into the CRM
A few read-only fields on the account. Not a usage table the CRM was never designed to hold.
- 5
The trend travels with the value
Improving, flat or declining against the previous two periods, because the direction is the story.
- 6
Alerts fire on movement, not level
A sharp drop on a large account with a renewal approaching is worth an interruption. A consistently small customer is not.
What the sync is made of
Four parts, and the second is the discipline that makes it useful.
Warehouse aggregation
Event volume rolls up where that is cheap. Pushing raw events at a CRM produces a slow CRM and an unusable dataset.
A few labelled signals
Three or four states a rep can read at a glance, instead of a wall of metrics that gets ignored uniformly.
A trend, not a snapshot
Direction against the previous periods, because usage falling from a high base is the signal and a low flat number usually is not.
Alerts on movement
A change worth interrupting somebody for. Level-based alerts fire constantly on small accounts and train people to dismiss them.
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 choose the three metrics that matter
Choosing what not to send is most of this build.
Headless skills
build-workflowUse build-workflow. The systems in play are Snowflake and Salesforce, or whatever we run in those seats. Before anything is built, help me choose. I want at most four signals, and each has to pass one test: would a rep behave differently if it changed. My starting set: weekly active users against licensed seats, breadth of features used, depth in the one workflow that indicates real adoption, and days since last meaningful activity. Tell me which of those our data can actually support. A signal we cannot compute reliably is worse than one we never promised.
- 2
Aggregate in the warehouse, per account, per period
The CRM is a system of record for relationships, not an analytics engine.
Headless skills
build-workflowUse build-workflow. Do the aggregation in Snowflake, never in the CRM. Build weekly and monthly rollups per account: active users, licensed seats, features touched, core workflow completions, and last meaningful activity. Map product accounts to CRM accounts explicitly, through an id rather than a name. Name matching between a product database and a CRM fails on exactly the largest customers, which have several entities. Handle a parent with child accounts: roll usage to the parent for the relationship view but keep the child breakdown, because that is where an expansion conversation starts.
- 3
Derive labels, not numbers
A rep scanning a list reads a label and skips a figure.
Turn the aggregates into a small number of labelled states: Adoption: strong, steady, light, dormant. Banded on active users against licensed seats, not on raw users, because 50 users is excellent on 60 seats and alarming on 500. Breadth: how much of what they bought they actually use. Direction: improving, flat, declining, computed against the previous two periods rather than the last one, so a quiet fortnight does not read as churn. Last meaningful activity, in days. Write these to read-only fields on the account. Set field level security so nobody edits them in the CRM: a rep correcting a usage figure creates a number that disagrees with the warehouse and gets believed.
- 4
Alert on movement, and only where it matters
Level-based alerts train people to dismiss all alerts.
Headless skills
tray-gotchasUse tray-gotchas, then alert on combinations instead of thresholds: Adoption dropping a band on an account above a value with a renewal inside two quarters A previously strong account going dormant Breadth falling after an expansion, which means the expansion did not land A champion who has stopped logging in entirely, where we track that Send to the account owner and the customer success manager, not to a shared channel. Never alert on a low level alone. A small customer who has always been small is a segment, not a problem, and firing on that is how the whole feed gets muted.
The expansion case is the most valuable and the least obvious: breadth falling after an upsell means you sold something they are not using, and the renewal is already at risk.
- 5
Keep it honest about freshness
A stale signal is worse than no signal, because it is believed.
Stamp the last successful sync on every account and show it beside the labels. A usage label that silently stopped updating six weeks ago is worse than an empty field, because a rep will act on it. Alert if the sync has not completed for any account group within its expected window. Then report: coverage, meaning the share of accounts with usage data at all, alert volume against action taken, and how often an account flagged as declining actually churned. That last number is what tells you whether the signals are worth anything.
- 6
Prove it works, then hand the bands to customer success
Because what counts as strong adoption is a judgement about your product.
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 move the adoption bands and the alert combinations in the visual canvas. Those change as the product does, and they belong to the team reading them.
What it connects to
Events land in one place, get aggregated in another, and only labels reach the third.
Snowflake
Hold the event history and do the aggregation. This is where the work happens.
Reads and writes
Salesforce
Write a small number of read-only labelled signals to the account, and nothing else.
Writes
Slack
Alert the account owner on movement that matters, with the account and the change in the message.
Writes
Zendesk
Read ticket volume, because usage falling while tickets rise is a different story from usage falling quietly.
Reads
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
Reps make renewal decisions on these labels. Freshness and honesty matter more than richness.
This runs as infrastructure, not as a script
Warehouse aggregation and the CRM write run on separate schedules on the same engine, so a slow rollup does not delay everything else.
Freshness is visible on the record
Last successful sync stamped beside the labels. A silently stale signal is worse than an empty field because somebody will act on it.
Credentials live in the workspace, never in the repo
The warehouse credential reads every customer usage record you hold. It is read-only, scoped to the rollup tables, and lives in your workspace.
Customer success owns the bands
Adoption bands and alert combinations open in Tray Build, tuned by the team that acts on them.
The CRM stays a CRM
A few read-only fields, never a usage table. The moment it becomes an analytics tool it is a slow one, and nobody trusts either system.
Questions people ask
Why aggregate outside the CRM?
Because a CRM is a system of record for relationships and performs badly as an analytics engine. Pushing raw events at it produces a slow CRM and a dataset nobody can query properly.
Why labels rather than numbers?
Because a rep scanning an account list reads a state and skips a figure. Adoption declining prompts a call; a 12% fall in weekly active users is homework somebody will not do.
Why send a trend?
Because a snapshot cannot tell a thriving small customer from a large one halfway out the door. Direction against the previous two periods is the part that changes behaviour.
Why alert on movement instead of level?
Because a consistently small account fires a level-based alert every week, and after a fortnight everybody mutes the channel. Movement on an account that matters is worth an interruption.
What is the most valuable alert?
Breadth falling after an expansion. It means you sold something the customer is not using, the renewal is already at risk, and almost nobody watches for it.
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)
Further reading
Background on the same subject, for the case rather than the build.
Related guides
Customer success
How to build customer health signals
Weight the signals that predict churn, keep the categories visible instead of one number, and back-test before anybody trusts it. The prompts that build it.
Data operations
How to build a CRM to warehouse sync
Capture history instead of current state, handle deletes and field changes, land raw then model, and prove the row counts. The Headless prompts that build it.
Last reviewed September 2026.