An event tracking plan is the living spec of every event you record — its name, its properties, when it fires, and who owns it. For a startup, start small: the eight to ten events that map your funnel from signup to activation to revenue. Add more only when a real question needs them.
A tracking plan is a living spec, not a one-time doc: name, properties, trigger, and owner for every event.
2
Start with 8-10 events across signup -> activation -> revenue. Add an event only when a real question needs it.
3
Pick one naming convention (object_action, e.g. subscription_started) and never break it — drift quietly kills analytics.
4
Decide who owns the plan and where the data lives (first-party, self-hosted or SaaS) before the first track() call.
What a tracking plan is
A tracking plan is a single document that lists every event your product records, the properties attached to each, the exact moment it fires, and the person accountable for it. It is the contract between the code that emits data and the dashboards that read it. Treat it as a living spec that changes with the product, not a doc you write once and forget. For the one-line version, see tracking plan; this guide covers how to build one.
Event
A discrete action a user or system takes, recorded once each time it happens — for example signup_completed or subscription_started.
Property
A key-value detail attached to an event that describes its context: plan_name, referrer, or amount_usd. Properties answer 'which one' and 'how much'.
Naming convention
The fixed rule for how you name events and properties, such as object_action in snake_case. Pick one and apply it everywhere.
Tracking plan
The living spec that lists every event, its properties, when it fires, and who owns it — the source of truth both code and analytics point to.
Four terms that make up a tracking plan, from the smallest unit (an event) to the spec that governs them all.
Why a plan beats ad-hoc tracking
Without a plan, tracking accretes. One engineer fires signup, another fires Sign Up, a third fires user_registered — three names for one action, and every funnel that touches signup silently splits or breaks. That is drift, and it is the main reason analytics stops being trusted. A plan fixes the vocabulary before the code ships, so the numbers you pull in six months still mean what you think. Clean, consistent events are also what an experimentation roadmap runs on — you cannot measure a test against a metric you record three different ways.
Name events object_action, and hold the line
The convention most analytics tools recommend is object_action: the thing, then what happened to it — subscription_started, invite_sent, checkout_completed. Segment, Amplitude, and PostHog each describe a variant (Segment uses 'Object Action', PostHog lowercase snake_case, Amplitude a noun plus a past-tense verb). The exact casing matters far less than picking one and never breaking it. Two rules carry most of the value: keep verb tense consistent, and never build event names dynamically — an event called plan_${name}_upgraded creates one event per customer and is unqueryable.
The 8-10 events that map your funnel
Resist tracking everything. Start with the handful of events that trace a user from first touch to paying — signup, activation, and revenue — and instrument those well before adding depth. Below is a starter set for a typical B2B SaaS; rename them to your product's nouns. Each becomes a row in your plan and, together, they are your first first-party dataset — the raw material for every funnel, cohort, and retention curve you will build. Where each event is instrumented — browser or server — is its own decision: server-side vs client-side tracking covers the split.
Event
When it fires
Why it matters
account_created
User finishes signup and a record exists
Top of funnel; the denominator for every conversion rate
onboarding_started
User enters the first-run flow
Separates signups who begin setup from those who bounce
activation_reached
User hits your defined aha moment (e.g. first project shared)
The most predictive early event; validate it, don't assume it
feature_used
A core feature is used, with a feature_name property
Depth of engagement; input to segments and retention
invite_sent
User invites a teammate
Leading indicator of expansion and stickiness in B2B
trial_started
A trial or free plan begins
Opens the revenue funnel; anchors trial-to-paid rate
subscription_started
User converts to a paid plan
The revenue moment; ties growth work to money
subscription_cancelled
User churns off a paid plan
Churn signal; feeds win-back and retention analysis
Properties carry the detail; owners keep it clean
Keep events few and generic; push specifics into properties. Instead of a separate event for every plan, fire subscription_started with plan_name and amount_usd properties — one event, richly described, stays queryable. Keep each event's property set lean — a handful you actually query beats dozens you never do. Then decide ownership: in most small teams this sits with a growth engineer or whoever ships instrumentation, and every new event should pass through them so the plan and the code never diverge. Finally, know where the events land. Sending them to a hosted analytics tool or CDP is fast but puts your behavioural data on someone else's servers; keeping it first-party — self-hosted Postgres, your own warehouse — keeps it yours, which is the core open source vs. SaaS trade-off for engagement tooling. If you want the engagement tool on your side of that line too, our comparison of open-source marketing automation tools is the place to start.
Start with eight to ten — the events that map signup, activation, and revenue — and add more only when a specific question needs them. Tracking everything up front creates noise you have to maintain and rarely query. It is easier to add a well-named event later than to untangle a hundred inconsistent ones.
What is the best event naming convention?
object_action (the noun, then what happened) is the most widely recommended: subscription_started, invite_sent. Segment, Amplitude, and PostHog each publish a variant. The best convention is whichever one you apply consistently — casing and tense matter less than never breaking the rule or generating names dynamically.
What is the difference between an event and a property?
An event is the action (subscription_started); a property is a detail about that action (plan_name, amount_usd). Keep events few and generic and push specifics into properties, so one well-described event stays queryable instead of splintering into dozens of near-duplicates.
Should tracking data live in a SaaS tool or self-hosted?
Both work. A hosted analytics tool or CDP is faster to start; self-hosting (your own Postgres or warehouse) keeps behavioural data on your infrastructure and avoids lock-in. For a technical team that treats customer data as first-party, self-hosting is often the better long-run call. Decide before you instrument, because migrating events later is painful.
fromHello is open-source marketing automation: messages triggered by what people do.
fromHello Cloud is in early access through the waitlist.