Skip to content
Academy
Marketing Academy · Field Work●Product Marketing
CoreBuild the Asset· 50 minutes

Building a Trigger-to-Message Map from Synthetic Usage Data

Adyen

Objective: Given 6 rows of raw account usage data, classify each into a real upgrade trigger or noise, then build complete earned-context, named-constraint, reversible-step copy for each real trigger.

You're on the lifecycle marketing team at Adyen, the Amsterdam-founded global payments platform for enterprise merchants, given a weekly usage export across 6 accounts to turn into an expansion messaging plan.

Classify the usage rows first, then write the message only for the rows that are real triggers.

Before you start

What you'll need

Free path (everything below is enough to finish)

FreeClassify the 6 raw usage rows into trigger types

Free, fast filtering for a small usage export

FreemiumStore the trigger-to-message map as a reusable workflow reference table

Free tier supports custom properties and workflow tables without a paid seat

The process

2 steps

Step 01 of 02

Classifying raw usage events into the three real trigger signals versus noise

The lesson names three signals that do most of the work: hitting a hard limit, requesting a locked feature, and team growth via new unfamiliar logins; the signal, not the calendar, should trigger the message.

Given 6 usage rows (a merchant nearing its transaction-volume cap, a merchant that clicked into a locked fraud-scoring setting, a merchant with 4 new team logins this month, a merchant that logged in once after 3 months idle, a merchant that opened the product changelog email, and a merchant that hit its API call limit), tag each as hard-limit / locked-feature / team-growth / noise.

Google Sheets— Import the 6-row usage export, add a 'trigger type' column, filter out anything tagged noise.

Procedure

  1. Read each row's raw event description
  2. Tag hard-limit for transaction-volume or API-call caps being approached
  3. Tag locked-feature for any click into a gated setting
  4. Tag team-growth for a meaningful jump in unique logins
  5. Tag noise for anything that isn't a self-evident signal (a single login, an email open) and exclude it from the message plan
Sample output
Merchant A, nearing transaction-volume cap -> hard-limit
Merchant B, clicked locked fraud-scoring setting -> locked-feature
Merchant C, 4 new team logins this month -> team-growth
Merchant D, single login after 3 months idle -> noise, exclude
Merchant E, opened changelog email -> noise, exclude
Merchant F, hit API call limit -> hard-limit

4 real triggers, 2 excluded as noise.

Healthy

Only rows with a self-evident, account-specific signal make it into the message plan; the rest are excluded.

Unhealthy

Treating every row as a trigger, including a single login or an email open, because 'more messages can't hurt' - this is exactly the blast-in-disguise pattern the lesson warns against.

What this means

A trigger has to be something the account did that makes the upgrade argument for you; anything weaker is noise.

So what do I do about it?

SymptomActionEffort
Every usage uptick, however small, gets queued for an expansion emailRestrict the trigger list to hard-limit, locked-feature, and team-growth events only, exclude everything else5 min
YouYou can do this yourself, no engineering access required.

Step 02 of 02

Building an expansion message with earned context, named constraint, and a reversible next step

The lesson's framework requires 3 moves in every expansion message: earned context (the specific thing the account did), a named constraint (what they'll hit if they don't act), and a reversible next step (a trial, downgrade path, or no-penalty opt-out).

For the 4 real triggers classified in Step 1, write the earned-context opener, the named constraint, and the reversible CTA for each, in a single reference table.

HubSpot CRM— Build the trigger-to-message map as a workflow reference table inside HubSpot CRM's free tier so lifecycle sends can pull from it directly.

Procedure

  1. For each real trigger, write one sentence naming the specific account behavior (earned context)
  2. Write one sentence naming the exact limit or gate the account is approaching (named constraint)
  3. Write one CTA that offers a trial, downgrade path, or opt-out, never a hard upgrade-only button (reversible next step)
  4. Load all 4 rows into the HubSpot workflow reference table, tagged by trigger type
Sample output
TRIGGER: hard-limit (transaction volume)
Earned context: 'Your processed volume is on pace to cross your current plan's cap next month.'
Named constraint: 'At your current growth rate you'll hit the cap around the 20th.'
Reversible CTA: 'See a 14-day preview of the next tier, no commitment, cancel any time.'

TRIGGER: locked-feature (fraud scoring)
Earned context: 'Your team opened the advanced fraud-scoring settings last week.'
Named constraint: 'That control is available on the Enterprise plan only.'
Reversible CTA: 'Try it for 14 days on us, no charge until you confirm.'

Healthy

Every one of the 4 real-trigger rows has all 3 moves present and specific to that account's actual behavior.

Unhealthy

Reusing the same generic constraint sentence across all 4 rows just with the account name swapped in.

What this means

The map is only useful if each row could not be sent to any other account without editing it.

So what do I do about it?

SymptomActionEffort
Message map rows are identical except for the merchant nameRewrite each row's earned-context sentence to name the exact behavior from that account's usage data30 min
YouYou can do this yourself, no engineering access required.

Final deliverable

A trigger-to-message map covering the 4 real usage signals, with complete earned-context, named-constraint, and reversible-step copy for each, ready to load into a lifecycle tool.

See a reference example
Sample output
Adyen Merchant Expansion Map (excerpt)

TRIGGER: team-growth (4 new logins)
Earned context: 'Your workspace added 4 new teammates this month.'
Named constraint: 'Your current plan supports up to 6 seats before per-seat billing kicks in.'
Reversible CTA: 'Add the next 3 seats on a 30-day trial rate, downgrade any time.'

The same discipline shows up in how Intercom times its Pro-only publish prompts: the copy only fires the moment a team clicks into the gated setting, never on a fixed send date.

Success criteria

You're done when you can:

  • Correctly excludes the 2 noise rows from the message plan
  • All 4 real-trigger rows contain a distinct, account-specific earned context, named constraint, and reversible CTA