An event schema defines the name, properties, and expected values of every product analytics event you emit.
An event schema is the explicit definition of what a product analytics event contains — its name, its properties, the type and expected values of each property, and when it should fire. Events like button_clicked, checkout_started, subscription_upgraded flow from your product into Amplitude, Mixpanel, PostHog, Segment, and your data warehouse. Without schema discipline, the event stream becomes a graveyard of near-duplicates (checkout_started, checkoutStarted, Checkout_Start) that nobody can trust and every analysis has to reconcile.
Pick one convention and enforce it. The Segment recommendation — object_action in snake_case, past tense (user_signed_up, order_completed) — is the de facto standard and worth adopting even if you'd have chosen differently starting from scratch. Object first, action second so events group naturally when listed alphabetically. Past tense because events describe things that happened. Snake_case avoids the JavaScript vs. Ruby vs. Python casing debates. Whatever you pick, document it in a one-page tracking plan and reject PRs that violate it — inconsistency compounds fast.
A tracking plan is a living document (spreadsheet, Notion page, or dedicated tool like Avo or Iteratively) listing every event, its properties, types, examples, and the trigger condition. Every new event proposal starts as a row in the plan reviewed by product and data; only approved events ship. This sounds bureaucratic and is worth it — the cost of correcting a bad event name after 6 months of data has accumulated (rename in code, backfill history, update every dashboard) is 10-100x the cost of getting the review right up front.
Two categories of properties: (a) event properties — specific to this event (plan_tier on subscription_upgraded). (b) user properties — attributes of the user that update over time and are attached to every event (plan_tier as a user property, email, signup_date). Send both. Common mistake: encoding state in event names ('upgraded_to_pro' as separate event from 'upgraded_to_enterprise') instead of one 'plan_upgraded' event with a new_plan property. The property-based version enables slicing without exploding your event count.
Events evolve — properties get added, semantics shift. Handle changes explicitly: for additive changes (new optional property), just add it. For semantic changes (property meaning changes), version the event (checkout_started_v2) or add a schema_version property, and update dashboards to filter appropriately. Never silently redefine an existing event or property — every downstream analysis that assumed the old meaning will produce quietly wrong numbers, and nobody will know for months.
Validate events at the collection layer against the tracking plan schema. Options: Segment Protocols, PostHog's schema enforcement, or a custom middleware. Invalid events (unknown names, missing required properties, wrong types) get rejected or quarantined, not silently ingested. Without validation, well-intentioned engineers add events that mostly-work-except-one-property-is-a-string-when-it-should-be-a-number, and the analytics team discovers this when a dashboard breaks two weeks later.
Investor directory · Fundraising library · Articles A–Z · Company funding database