Event Schema Design That Teams Can Trust
on this page ▾
A signup funnel that says 42% converted is only useful if everyone agrees on what `signup_completed` means. Does it fire when a user submits the form, verifies their email, creates a workspace, or lands in the product? If product, marketing, and engineering each answer differently, the metric is not a source of truth. It is a future argument.
Event schema design is the work of defining the behavioral language your product uses to measure, understand, and act. Done well, it gives every team the same answer to simple but expensive questions: Who reached the paywall? Which plan did they see? Did they hit an error? Did they come back after support helped them? Done poorly, it creates duplicate tracking, broken funnels, generic campaigns, and dashboards nobody fully trusts.
For event-driven products, the schema is not a documentation exercise. It is operating infrastructure.
What event schema design needs to solve
An event schema should make user behavior useful across the entire workflow: measure behavior, see what happened behind the metric, respond to the right people, and test a fix safely. That requires more than a tidy list of event names.
Every event needs a clear behavioral meaning, a consistent actor, the right context, and a reliable point in time. Consider a marketplace checkout. `checkout_started` tells you that a person began the process. To explain a conversion leak, though, you may also need the cart value, currency, item count, payment method selected, device type, experiment variant, and whether the user was anonymous or identified.
The goal is not to collect every possible field. It is to capture the context that changes a decision. If a property will never affect analysis, segmentation, support, messaging, or release evaluation, it probably does not belong in the event.
This is where teams often overcorrect. They start with five vague events and no useful properties, then swing toward an event catalog so large that nobody can implement it consistently. The better answer is a small, stable behavioral core with meaningful context attached.
Start with decisions, not instrumentation
Before engineers add tracking calls, write down the decisions the data must support. This keeps the schema connected to revenue, retention, and product work instead of becoming a developer-side checklist.
For a SaaS onboarding flow, the questions may be: where do new accounts stall, which activation step predicts retention, and which users need help before their trial expires? For ecommerce, the questions may be: which traffic sources produce abandoned carts, where does payment fail, and which incentive should reach high-intent visitors?
Those questions lead to a focused event sequence. An onboarding model might include `account_created`, `workspace_created`, `teammate_invited`, `integration_connected`, and `first_value_received`. The last event matters most because it describes customer value, not just interface activity.
Avoid treating clicks as outcomes. `button_clicked` can be useful in session-level investigation, but it is weak as a core business event unless the button itself represents an important state change. Events should generally describe what happened in the product, not merely what someone touched.
Use names that describe completed facts
Good event names are specific, consistent, and readable without opening a tracking plan. Past-tense names make it clear that the event represents a completed action: `report_exported`, `invoice_paid`, `feature_enabled`, `message_sent`.
Choose one naming convention and keep it. Snake case is common because it travels cleanly across SDKs, warehouses, and APIs. What matters more than the format is semantic discipline. Do not mix `User Signed Up`, `user_signup`, and `sign_up` for the same behavior. That is three definitions of one metric waiting to happen.
Be equally strict about event ownership. `subscription_canceled` should mean a subscription actually entered a canceled state. If a customer opens the cancellation screen, use `cancellation_started`. If they select a reason but leave, record `cancellation_reason_selected`. Separating intent from completion lets a team find the leak, see why it happened, and intervene before revenue is lost.
A short event description should answer four questions: what occurred, when it fires, who or what performed it, and what is deliberately excluded. That final question prevents gradual semantic drift. For example, `payment_failed` may exclude validation errors before a payment processor is contacted. State that explicitly.
Design properties for analysis and action
Properties turn a timeline into context. They should be consistent enough to power funnels and cohorts without forcing every team to guess what a field means.
Use stable property names for recurring concepts. If revenue is represented as `amount` in one event, `price` in another, and `total_cents` in a third, downstream analysis becomes fragile. Define whether monetary values are integers in cents or decimal amounts, always include currency when relevant, and document the choice.
Separate event properties from person, account, and object data. A user's plan can be attached as a current account property, but the plan visible at the time of checkout should also be captured on the checkout event. Current state answers, "What plan are they on now?" Historical event context answers, "What did they see when they made this decision?"
For B2B products, account context is usually as important as person context. Include an `account_id` or workspace identifier consistently, along with fields such as account tier or team size when they affect the workflow. But do not put sensitive data into events by default. Avoid raw email content, payment details, private support text, and any payload that does not need to be available to the teams using the data.
Identity is part of the schema
Anonymous behavior and known-user behavior must connect cleanly. Otherwise, the trial visitor who viewed pricing, started signup, and invited a teammate becomes three unrelated records the moment they log in.
Define the anonymous identifier, authenticated user ID, and account ID before rolling out event tracking. Decide which system owns each identifier and make that ownership durable. Email addresses change. Internal user IDs should not. For authenticated events, signed identity verification adds a useful control: the client can report behavior, but it cannot casually impersonate another user.
Identity rules also need to cover mergers. When an anonymous visitor becomes an identified user, their prior session history should attach to the verified person. When someone belongs to multiple workspaces, events should preserve the active workspace context. These cases are easy to ignore during a first implementation and painful to repair after six months of campaigns, support conversations, and experiments depend on them.
Keep client and server events honest
Client-side events are close to the experience. They are useful for page views, form interactions, UI errors, and the exact path a person took through an onboarding flow. Server-side events are closer to business truth. They are better for successful payments, permission changes, account creation, fulfillment, and background job completion.
Many important actions need both, but they should not become duplicates. A checkout button click can be captured in the client, while `order_completed` should be confirmed by the server after the transaction succeeds. Use an event ID or idempotency strategy when retries are possible. A payment webhook delivered twice should not double your revenue chart or trigger two thank-you campaigns.
Timestamps deserve the same care. Capture when the event occurred, not only when it arrived. Late mobile events, offline behavior, retries, and queue delays are normal. A schema that cannot distinguish event time from ingestion time will eventually produce confusing funnel results.
Govern changes without freezing progress
Schemas evolve because products evolve. The mistake is either allowing anyone to change events without review or making every change a committee meeting. Give core events an owner, keep a lightweight tracking plan in version control or a shared system, and review changes that affect conversion, revenue, experiments, or customer messaging.
Do not silently change the meaning of an existing event. If `trial_started` used to fire after email verification and now fires after workspace creation, historical comparisons are compromised. Create a new event or version the contract, then update reporting deliberately. It may feel slower for a week. It is much faster than explaining a mysterious 30% conversion swing to leadership.
Validation closes the loop. Test events in development, inspect payloads in staging, and monitor production for missing required properties, unexpected values, and sudden volume changes. Autocapture can accelerate investigation, but it should complement intentional events, not replace them. Critical business definitions deserve explicit instrumentation.
One schema, fewer handoffs
A good schema should not stop at a dashboard. If a cohort reaches checkout but fails payment, that same cohort should be available for a targeted message, a support view with product context, or a controlled feature-flag rollout for a payment fix. No CSV exports. No dashboards to rebuild. No waiting for five tools to reconcile their version of the customer.
That is the practical advantage of a unified event pipeline. Kilden can use the same verified identity and event history across analytics, replay, messaging, support, surveys, and feature flags, so the action taken matches the behavior measured.
Start with the few customer moments that matter most: activation, conversion, expansion, and churn risk. Define them precisely, instrument them once, and review them as the product changes. Your event schema should make the next decision easier, not create another data cleanup project.