Event taxonomy: build a tracking plan that stays trustworthy
What is an event taxonomy?
An event taxonomy is the controlled vocabulary and semantic rules used to name product events and properties. A tracking plan applies that taxonomy to a concrete implementation by defining what fires, when it fires, which source owns it, what each field means, and how the payload is validated.
TL;DR
- -An event taxonomy defines the language of analytics; a tracking plan specifies the events, properties, producers, owners, and checks implemented with that language.
- -Start from decisions and business questions. A generated list of 30 plausible events is not an analytics strategy.
- -Pick one naming convention and document semantics. Title Case versus snake_case matters less than stable meaning and enforcement.
- -Define identity, event time, source of truth, property types, nullability, privacy class, and duplicate behavior before instrumentation.
- -AI can map supplied journeys and questions into a draft plan. It must cite each proposed event to an input and return UNKNOWN rather than inventing requirements.
- -Validate payloads in development and production, monitor missing fields and volume changes, and version breaking semantic changes.
The fastest way to ruin product analytics is to instrument every screen.
You get plenty of events, dashboards that render, and no agreement about what the numbers mean. Subscription Created may fire when checkout opens, when a payment succeeds, or when a database row appears. The name looks clean in all three cases. The metric is still ambiguous.
An event taxonomy solves the language problem. A tracking plan solves the implementation problem. AI can help draft both, but only after the team decides which questions matter and which system owns each fact.
Taxonomy and tracking plan are different artifacts
Amplitude’s current taxonomy guide makes a useful distinction: the taxonomy defines how things are named, while the tracking plan defines what is collected, including firing conditions and properties (Amplitude).
Keep that distinction in the document:
Taxonomy
- event naming pattern;
- property naming pattern;
- vocabulary for shared concepts;
- data types and units;
- rules for identity, time, and versions;
- deprecation policy.
Tracking plan
- business question and metric supported;
- event name and exact definition;
- producer and source of truth;
- trigger and exclusions;
- property contract;
- privacy classification;
- owner and lifecycle status;
- test and monitoring requirements.
A name such as Invoice Paid belongs to the taxonomy. “Fire once on the server after the payment provider confirms settlement; retries reuse the same event ID” belongs to the tracking plan.
Step 1: start with decisions, not screens
Twilio Segment’s planning guidance starts with what the team wants to learn, then maps those questions to events and properties. That order prevents instrumentation from becoming a catalog of UI controls (Segment).
Write a decision table before naming events:
| Decision | Question | Metric or analysis | Evidence needed |
|---|---|---|---|
| Improve onboarding | Where do eligible accounts stop before first value? | step conversion by account cohort | account created, required steps completed, value event |
| Change trial design | Which eligible accounts convert after meaningful use? | conversion by predeclared activation behavior | trial eligibility, activation event, paid conversion |
| Fix collaboration | Do invited teammates become active members? | invite-to-activation funnel | invite sent, invite accepted, core action |
This step exposes vague metrics. “Activation” is not an event until the product team defines the behavior, actor, time window, and entity being activated. For a B2B product, the unit may be an account rather than a person. Define that beside the North Star metric and retention model, not inside an SDK call.
If no current decision or analysis uses an event, leave it out of the first release. You can add evidence later. Historical data that nobody can define is not an asset.
Step 2: choose the event grain and source of truth
Before naming an event, complete this sentence:
One row represents one ___ performed by ___ against ___ when ___.
For example:
One Invoice Paid row represents one settled invoice,
owned by one workspace, confirmed by the billing service,
at the provider's settlement timestamp.
Then define:
- actor: anonymous device, user, service, or admin;
- subject: account, project, invoice, document, or another entity;
- grain: once per click, attempt, state transition, or business transaction;
- producer: web client, mobile client, backend service, webhook processor;
- source of truth: the system allowed to assert the fact;
- event time: when the action happened, not merely when the vendor received it;
- deduplication key: stable ID for retries where the pipeline supports one.
Client-side events are appropriate for interactions only the client observes, such as a panel exposure. Server-side events are usually safer for billing, permissions, successful jobs, and other authoritative state transitions. If both sides emit related signals, give them different meanings: Checkout Submitted from the client and Invoice Paid from the billing service.
Never let two producers emit the same event name with slightly different semantics. A dashboard cannot repair that later.
Step 3: choose one naming grammar
Object Action in past tense is readable:
Account Created
Invite Accepted
Report Exported
Lowercase snake_case is convenient in code and warehouses:
account_created
invite_accepted
report_exported
Both are valid if the meanings stay stable. Current first-party guidance is not universal: Amplitude presents object-plus-action with either Title Case or snake_case, while PostHog has published a lowercase snake_case convention. Platform support is not the same as a mandate.
Use these rules:
- Pick one case and tense for custom events.
- Use domain language, not button labels.
- Describe a completed observation, not an intended result.
- Put variation in properties when the underlying event meaning is the same.
- Reserve vendor-defined names and prefixes.
- Never construct event names dynamically.
Report Exported with format: "csv" is easier to govern than CSV Report Exported, PDF Report Exported, and a new event for every format. But do not compress genuinely different facts into one vague Action Completed event.
Property names need the same discipline:
workspace_id string
billing_interval enum: monthly | annual
amount_minor integer
currency ISO 4217 string
is_first_invoice boolean
occurred_at RFC 3339 timestamp
Document units. amount: 99 is unusable until the plan says whether it means cents, dollars, or another currency.
Step 4: write a real event contract
A useful tracking-plan row contains enough information for a developer, analyst, and reviewer to reach the same interpretation.
| Field | Example |
|---|---|
| Event | invoice_paid |
| Purpose | Revenue and trial-conversion analysis |
| Definition | Billing provider confirmed settlement |
| Fires | Once per settled invoice |
| Does not fire | Checkout opened, payment pending, retry received |
| Producer | billing-webhook |
| Subject | workspace |
| Event ID | provider invoice ID + settlement transition |
| Required properties | workspace_id, invoice_id, amount_minor, currency, plan_id |
| Optional properties | coupon_id |
| Owner | Billing engineering |
| Privacy | pseudonymous account data; no free text |
| Status | proposed / implemented / verified / deprecated |
Separate event properties from mutable profile or entity properties. The invoice amount at the time of payment belongs on the event. The workspace’s current plan may belong on an account profile, but a mutable current value must not silently rewrite historical meaning.
Avoid generic free-text properties such as feedback_text, URLs with query strings, search queries, document names, or raw errors until privacy and cardinality are reviewed. They often capture secrets or personal data and create unbounded values.
Step 5: design identity before funnels
Identity mistakes create fake users, broken funnels, and cross-account leakage.
Document at least:
- anonymous identifier creation and rotation;
- the moment a known
user_idis assigned; - anonymous-to-known merge behavior;
- logout and shared-device behavior;
- account or group identity;
- user membership in multiple accounts;
- deletion and suppression flow;
- server-to-client consistency.
Do not assume the SDK handles identity the way your product needs. Amplitude, Mixpanel, PostHog, Segment, and warehouse-first pipelines use different identity models and reserved fields. Keep one conceptual model, then add destination-specific mappings.
A persistent user_id is not anonymous just because it excludes an email. The ICO notes that pseudonymised data can still be re-identified using separately held information. For EU data subjects, purpose limitation, data minimisation, storage limitation, and accountability apply to personal-data processing (European Commission, ICO).
For every property, record:
purpose | legal basis/approval | classification | destinations |
retention | deletion path | access group
Get privacy or legal review for the jurisdictions and data involved. A taxonomy spreadsheet is not a lawful basis.
Step 6: let AI draft only from supplied evidence
The unsafe prompt is “generate 30 events for my SaaS.” It optimizes for a complete-looking table. It does not know your decisions, implementation, privacy obligations, or event grain.
Give the model bounded inputs instead:
You are drafting a tracking plan from supplied evidence.
Inputs:
- approved business questions and metric definitions
- user journeys and state-transition diagrams
- existing event export
- relevant API contracts and code locations
- taxonomy rules
- privacy classification rules
For each proposed event:
1. Cite the business question and input that require it.
2. Define actor, subject, grain, trigger, exclusions, producer,
source of truth, event time, and deduplication behavior.
3. List required and optional properties with type, unit,
allowed values, nullability, and privacy class.
4. Map duplicate or legacy events.
5. Return UNKNOWN for missing facts.
6. Flag high-cardinality, free-text, identity, and PII risks.
Do not invent:
- activation definitions
- implementation locations
- legal bases
- retention periods
- thresholds
- vendor capabilities
Use a human review, schema validation, and test payloads as the quality gate. A second LLM can find inconsistencies, but agreement between two models does not prove that either matches the product.
Step 7: reduce the plan to a first slice
A project-management product does not need a generic list of 30 events on day one. Suppose the current questions concern account activation and team collaboration. A smaller first slice might be:
| Event | Producer | Why it exists | Key properties |
|---|---|---|---|
account_created | backend | cohort denominator | account_id, created_by_user_id, signup_source |
onboarding_step_completed | backend or trusted client | step funnel | account_id, step_id, flow_version |
project_created | backend | first setup behavior | account_id, project_id, creation_method |
task_created | backend | core object created | account_id, project_id, task_id |
task_completed | backend | completed core work | account_id, project_id, task_id |
invite_sent | backend | collaboration funnel start | account_id, invite_id, role |
invite_accepted | backend | collaboration funnel progress | account_id, invite_id, user_id |
subscription_started | billing service | paid conversion | account_id, subscription_id, plan_id, currency |
This is still only a draft. “Account activation” should normally be calculated from underlying facts, not emitted as First Value Moment Reached. A derived metric can evolve without asking the application to guess when value occurred.
Connect the events to a declared retention analysis before adding “return” or “reactivation” events. Sessions may help some questions, but they are not retention by definition.
Step 8: validate before and after release
A spreadsheet reviewed once will drift. Put checks near the producers.
Before merge
- schema file or generated typed wrapper is updated;
- event owner approves semantic changes;
- required and forbidden properties are tested;
- representative payload contains no raw PII or secrets;
- duplicate and retry behavior is tested;
- old consumers are identified;
- change is recorded in a changelog.
In staging
Inspect the raw payload at the collector, not only the final chart. Verify one expected event for each trigger, no event for exclusions, correct timestamp and IDs, and consistent properties across web, mobile, and backend sources.
In production
Monitor per event and producer:
- observed versus expected event names;
- required-property presence;
- type and enum violations;
- duplicate rate;
- delay between event time and ingestion time;
- volume and distinct-ID changes;
- new high-cardinality properties;
- unexpected personal or free-text fields.
Do not copy a universal 99% completeness target or 50% anomaly threshold. Set service levels from business criticality and normal variance. A billing event may require near-complete reconciliation against the ledger; a low-value UI exposure can tolerate more loss.
Route critical failures through the same owned metric-alert process as product and infrastructure signals. An alert without an owner, runbook, and reconciliation path becomes background noise.
Managed tools can store, branch, endorse, and enforce schemas. Amplitude currently supports tracking-plan branches and official designations; Segment Protocols can validate events against a plan. A small team can start with versioned JSON or CSV plus runtime validation and CI tests. The important part is one authoritative contract and an owner, not the logo on the tool.
Handling changes without breaking history
Classify each change:
- Additive: new optional property or new event.
- Compatible tightening: enum documentation or validation that matches existing data.
- Breaking: renamed event, changed grain, changed firing point, type change, or new meaning under an old name.
- Deprecation: stop new writes while preserving historical interpretation.
For a breaking change, create a new version or event name, run old and new definitions in parallel only when necessary, update dependent dashboards, then retire the old producer. Never relabel historical data to a new meaning just to make the catalog tidy.
Record:
change: invoice_paid v1 -> v2
reason: event now represents settlement, not authorization
effective_at: 2026-09-01T00:00:00Z
owners:
producer: billing-engineering
consumers: finance-analytics
migration:
- add v2 payload and validation
- reconcile v2 against payment ledger
- update revenue dashboards
- deprecate v1 after named consumers move
The practical sequence
- List the decisions and questions the data must support.
- Define metrics, entity, cohort, and time windows.
- Choose event grain, producer, source of truth, and identity behavior.
- Adopt one naming and property grammar.
- Draft contracts with privacy and lifecycle metadata.
- Use AI to map supplied evidence, not to create product truth.
- Implement the smallest useful slice.
- Test raw payloads, validate schemas, and reconcile critical facts.
- Monitor quality by event and producer.
- Version semantic changes and retire obsolete data deliberately.
A trustworthy event taxonomy is not the longest list of events. It is the smallest shared language that lets product, engineering, and analytics reproduce the same answer.
Sources
- Amplitude: taxonomy versus tracking plan
- Amplitude: CSV tracking-plan branches
- Amplitude: official events and properties
- Twilio Segment: create a tracking plan
- Twilio Segment: tracking-plan validation
- PostHog: analytics naming guidance
- European Commission: GDPR processing principles
- ICO: pseudonymisation guidance