SaaS Copy Weekly

Event Schema Design for Triggerable Adoption Campaigns

Schema choices determine campaign precision far more than sending volume or frequency ever will.

Contributing Editor · · 13 min read
Cover illustration for “Event Schema Design for Triggerable Adoption Campaigns”
Triggered Messaging · September 15, 2026 · 13 min read · 2,912 words

Adoption campaigns fail for reasons that have nothing to do with send volume. They fail because the event data feeding them is too blunt to justify sending anything at all. A campaign engine that only knows "this user hasn't touched feature X" is working with a different quality of evidence than one that knows a specific person, on a specific plan, with specific permissions, is still doing something manually that the product already automates for them. That gap gets set almost entirely by choices made when the event schema was first built. Most teams get those choices wrong, and the rest of this piece is about why.

Product-led growth is the default motion in B2B SaaS now, and companies running it well report revenue growth roughly double that of sales-led peers. That raises the cost of getting activation wrong. Yet activation rates sit stubbornly low across the industry, a 2024 benchmark across 62 companies puts the median around 37%. Most signups never reach the point where the product earns its keep. The instinct is to fix this with more messaging, more nudges, more campaigns. That instinct is wrong. The constraint sits upstream: the events available to trigger a message are too coarse to say anything specific about the person receiving it.

An event, at its core, is a timestamped record of something a user did, paired with properties describing the context: what happened, who did it, when, and under what conditions. A schema is the agreed structure governing which events get tracked, what they're named, and what properties travel with them. Every downstream system, analytics dashboards, campaign triggers, suppression rules, depends on that contract being honored.

"Track everything and sort it out later" sounds like the responsible option. It isn't. Teams following that instinct end up with a library of hundreds of events, most of which nobody ever queries, while the two or three events that would actually answer a real question sit buried in the noise. A better discipline runs closer to 20 to 30 core events, expanded only when a specific, unanswered question demands a new one. More events is not more rigor; it's usually just more noise to sort through later, and later rarely comes.

There's a bus-factor problem hiding in most instrumentation work, too. If only the engineer who shipped the tracking code knows what user_action_v2 actually means, the schema has a single point of failure. Analytics, campaign logic, suppression rules: all of it depends on an interpretation that lives in one person's memory instead of documentation anyone else can check.

Underspecification shows up downstream as a forced reliance on blunt signals: login frequency, session counts, page views. Not because those are the best available proxies for adoption, but because nobody captured the behavioral events that would justify something sharper. Three failure modes recur constantly. Events go missing entirely, a real behavior happened but nothing recorded it. Names go ambiguous, so an event exists but nobody agrees on what it means. Properties go thin, so an event fires but carries too little context to filter on meaningfully.

Naming events so a campaign engine can reason about individual behavior

Name the action, not the button. bulk_export_initiated tells a campaign engine something export_button_clicked never can, because it encodes intent rather than UI mechanics. A click event describes an interaction with a pixel. An action event describes a decision a user made. That distinction is worth more than it sounds like it should be.

The naming convention has to be legible to someone who isn't the engineer who wrote the tracker. A growth marketer or product manager building audience logic for a campaign has to be able to read an event name and know, without asking anyone, what it means and when it fires. An object-action pattern, noun then verb, holds up well across a large event library: project_shared, report_scheduled, team_member_invited. It's scannable, and it keeps naming consistent across teams that otherwise drift toward their own conventions.

Every product has a core action, the thing the whole value proposition hinges on. For a messaging tool like Slack, it's sending a message. For a design tool, it's completing a core creative action. That core action deserves a name specific enough to serve, on its own, as a campaign trigger.

Version suffixes, _v2, _new, and the like, should not exist in a production schema. They encode the history of how the tracking code changed, not what the user did, and they break campaign logic the moment an event gets renamed after a product update. Naming discipline governs suppression just as much as triggering. If the event marking "already activated" carries an ambiguous name, nobody can write a suppression rule with confidence, and messages go out to people who should have been excluded.

A useful test for any event name: show it, on its own, to someone in growth or product who didn't write the tracker. If they can't construct the correct audience rule from the name alone, the name needs work, full stop.

What properties to attach and how property depth determines campaign precision

An event name answers what happened. Properties answer under what conditions, by whom, and in what state. Four categories carry the most weight for adoption campaigns specifically.

Identity context, the user ID, account ID, and role within the account, separates person-level behavior from account-level behavior, which matters once a campaign needs to target an individual rather than an entire organization. Feature context captures which variant of a feature was in play, which workflow path the user took, and what configuration state was active when the event fired. Outcome context distinguishes success from partial completion from outright failure, since a failed export attempt is a meaningfully different signal from one the user simply skipped. Sequence context tracks whether an occurrence was the first, second, or fifteenth, because repeat use tells a different story than a single first-time attempt.

Property depth is what separates a campaign that can only say "this person has never used bulk export" from one that can say this specific person attempted a manual workaround three separate times this week, in a context where bulk export applied, and their plan already includes it. That second sentence is the difference between a message that lands as useful and one that reads as a generic nudge.

Over-propertying carries a real cost of its own, though, and teams underrate it. Every property attached to an event is a data contract that has to survive future product changes. Attach properties that will actually get queried. Skip the ones that just seem interesting in the abstract.

Cardinality matters here too. High-cardinality properties, raw text fields, timestamps stored as strings, free-form labels, tend to break campaign audience builders that expect clean filters. Wherever a property will be used to filter an audience, an enumerated value or a bucketed range holds up better than an open field. And properties capturing plan tier, permission level, and configuration state at the moment the event fired are especially valuable, because they let a campaign reason about what a user could have done differently, not just what they actually did.

Joining behavioral events to database state, why events alone are not enough

Event data tells a story over time: what a user did, and when. Database state tells a different story, anchored in the present tense: what plan they're on right now, what roles they've been assigned, which features are enabled for their account, how big their team is, whether their billing is current. A campaign built purely on event history can observe that a user hasn't touched a feature. Only a join against current database state can tell you whether that user is even eligible to use it, whether their role permits it, and whether it would help their actual workflow.

Skip that join, and campaigns fail in one of two directions. They over-target, sending messages about features a user can't even access. Or they under-target, missing users who have full access but simply haven't shown an adoption signal yet.

The join has to happen at the moment a campaign evaluates eligibility, not back when the event was first ingested, because database state shifts between those two moments, sometimes by months. Three dimensions of state matter most for adoption work. Entitlement covers whether a person's plan and role grant access to the feature in question. Configuration covers whether their account is set up in a way that makes the feature relevant to how they actually work. Account context covers whether team-level signals, size, usage patterns among teammates, bear on whether this person's behavior looks unusual relative to peers.

Instrument user state explicitly rather than inferring it fresh each time a campaign runs. Whether someone counts as "signed up," "first action taken," or "activated" should exist as a queryable field, not something recomputed on the fly from raw events. And the event schema itself has to carry stable IDs, user ID and account ID, so the join to the current database record resolves reliably. A campaign system that can't confidently tie an event to a live person record has nothing to act on.

Defining adoption for each feature before designing the trigger logic

Activation and adoption get used interchangeably, and that habit causes real damage downstream. Activation is the first meaningful use of a feature. Adoption is sustained engagement, the point where a feature becomes part of someone's actual workflow rather than a thing they tried once. Both need explicit, event-level definitions before anyone builds trigger logic on top of them.

A denominator problem needs naming directly here. Dividing feature users by the total user base, when only a subset of that base is even eligible for the feature, produces an adoption rate that misleads everyone reading it. The honest frame is eligible-cohort adoption: feature MAUs divided by total eligible user logins in the period, not total users overall.

Available benchmarks put core feature adoption in B2B SaaS at an average around 24.5%, with a median closer to 16.5%, while top-quartile products exceed 45%. That spread between median and top quartile isn't purely a product quality gap. A meaningful share of it is a measurement and campaign design problem, and it's the more fixable half.

"Completed onboarding" is not adoption, and pretending otherwise is where most adoption metrics quietly go wrong. Watching a product tour isn't adoption; sending a real volume of messages in a live workspace is. Completing a setup wizard isn't adoption; sending a first campaign to a real audience is. Signing up isn't adoption; closing one actual support ticket with an AI agent is.

For every feature, two thresholds need to exist before anyone writes a trigger rule. The first is a triggering threshold, the event pattern that justifies reaching out at all. The second is an adoption confirmation threshold, the subsequent behavior that proves the outreach actually worked. Features that see repeated use within the first week of exposure show notably stronger 90-day retention than features where repeat engagement is delayed, roughly 3.2 times higher by available measures, and that's precisely the pattern trigger logic should be calibrated to accelerate. Setting these thresholds up front prevents the common failure: a campaign that fires after a single touch and counts an email open as proof the job is done.

Translating schema design into trigger rules that fire on strong individual evidence

Diagram: Context-Triggered vs. Time-Based Outreach: The Engagement Gap. Visualizes: Show the magnitude contrast between two outreach approaches: context-triggered outreach (based on behavioral signals) versus time-based announcements.

A trigger rule needs four components, at minimum: the qualifying event pattern, the database-state conditions that have to hold true, the behavioral gap that justifies sending anything, and the recency window within which the evidence had to occur.

The qualifying event pattern is rarely a single event. It's usually a sequence or a count. "Exported records one at a time on three or more occasions in the past two weeks" is a far stronger signal than "used export at least once," because it shows a pattern instead of an isolated instance. The database-state condition sits alongside it: is this person on a plan that includes bulk export, and does their role carry the permission to use it? Those come from the backend at evaluation time, not from event properties.

The behavioral gap is what actually justifies the message. A campaign earns its place only when the evidence shows someone doing something the hard way while an easier path already exists and is available to them. That's the difference between a message that feels genuinely useful and one that reads as arbitrary noise. Recency matters too: a signal from four months ago carries different weight than one from last week, and trigger windows should track the natural cadence of the workflow the feature actually serves.

Context-triggered outreach outperforms time-based announcements by a wide margin. A 2025 Forrester study on SaaS engagement found engagement roughly 6.2 times higher for the former, and that gap is a direct downstream effect of the schema decisions covered above. It doesn't happen by accident.

Weak-evidence skip logic belongs inside the trigger rule itself, not bolted on afterward as an exception. If the behavioral pattern doesn't clearly clear the threshold, the rule should produce no outreach at all. A message sent on thin evidence does more damage than no message, because it teaches the recipient to ignore the channel. Every one of these requirements traces back to schema design: trigger rules this precise need event names that encode intent, properties that carry eligibility state, and IDs stable enough to survive the database join. Each gap left in the schema forces a corresponding simplification, and usually a weakening, of the trigger rule built on top of it.

Suppression and send-time constraints as part of the schema contract

Suppression deserves as much design attention as triggering, arguably more. The strongest adoption sequences pull a person out of a sequence the instant they activate. Sending "try bulk export" to someone who used bulk export yesterday is about the fastest way to teach a user that the messaging channel isn't paying attention. Get suppression wrong at scale, and a meaningful share of outreach lands on people who already did the thing being asked of them. That's a schema failure, not a campaign logic failure: the activation confirmation event either wasn't captured, wasn't named consistently, or wasn't queryable fast enough.

Suppression events carry their own requirements. The event marking "adopted" has to fire reliably and promptly, because a delayed or missing event opens a suppression gap where messages keep going out after they should have stopped. It has to be specific enough to distinguish "used the feature once" from "built it into their workflow," where those represent genuinely different thresholds for the campaign in question. And account-level adoption should, where it makes sense, suppress person-level outreach. If most of a team has already adopted a feature, individual nudges to the remaining holdouts may not need to exist at all.

Frequency caps, quiet hours, and never-contact rules operate at send time regardless of how strong the behavioral evidence looks. No signal, however precise, overrides those constraints. The schema implication runs parallel to triggering: suppression needs the same naming discipline and the same ID stability, since an event that can't be reliably joined to a person record can't function as a suppression signal either. A useful audit question for any trigger rule in production: what event, the moment it fires, removes this person from eligibility? If the schema can't answer that clearly, the suppression logic isn't finished.

Measuring whether campaigns produced adoption, not just activity

Opens and clicks measure awareness. They do not measure adoption, and treating them as a proxy is how teams end up optimizing for the wrong thing. Adoption gets confirmed only when the target behavior actually happens in the product after the message went out. Honest measurement narrows to a specific question that most dashboards obscure: among the eligible cohort that received guidance, what share went on to perform the target behavior successfully, more than once, within the adoption window?

Post-message adoption, on its own, isn't proof of causal lift. People already close to adopting a feature will often adopt it whether or not a message ever reached them. The schema needs to support a real cohort comparison, messaged against eligible-but-not-messaged, to separate genuine signal from coincidence. The most diagnostic view tends to be a retention curve: plot retention for users who adopted the feature against those who didn't. If the curves diverge, that's evidence the feature is actually driving retention. If they sit on top of each other, the campaign optimized for an activity that never touched the outcome that mattered.

Honest measurement carries its own schema requirements, and they aren't optional extras. The adoption confirmation event has to be distinct from the trigger event, since counting the trigger itself as proof of adoption is circular reasoning dressed up as a result. Repeat usage has to be trackable separately from first use, because a single occurrence isn't adoption by any reasonable definition. And the eligible cohort has to be reconstructable after the fact, meaning anyone auditing the campaign can determine who had access, who was in scope, and who was excluded, and can reach that answer through the same database-state join the campaign used in the first place.

Passive discovery, product announcements with no targeting behind them, still accounts for the large majority of how features reach users in SaaS today. That's the baseline every schema decision above is meant to beat. The event schema decides whether adoption campaigns compete with that baseline on genuine precision, or just repeat it with better copy.

Sources

  1. Product-Led Growth — Complete 2026 Guide
  2. ustechautomations.com

More in Triggered Messaging