# Event taxonomy: build a tracking plan that stays trustworthy

> Design an event taxonomy from business questions to tested payloads: naming, properties, identity, privacy, versioning, QA, and evidence-bound AI prompts.
> Author: Roman Belov · Published: 2026-04-01 · Source: https://futurecraft.pro/blog/event-taxonomy-ai/

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](https://amplitude.com/taxonomy-generator)).

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](https://app-canary.segment.com/academy/collecting-data/how-to-create-a-tracking-plan/)).

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](/blog/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:

```text
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:

```text
Account Created
Invite Accepted
Report Exported
```

Lowercase snake_case is convenient in code and warehouses:

```text
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:

1. Pick one case and tense for custom events.
2. Use domain language, not button labels.
3. Describe a completed observation, not an intended result.
4. Put variation in properties when the underlying event meaning is the same.
5. Reserve vendor-defined names and prefixes.
6. 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:

```text
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_id` is 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](https://commission.europa.eu/law/law-topic/data-protection/information-business-and-organisations/principles-gdpr_en), [ICO](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/data-sharing/anonymisation/pseudonymisation/)).

For every property, record:

```text
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:

```text
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](/blog/retention-curve-pmf/) 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](/blog/automated-metric-alerts/) 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:

```yaml
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

1. List the decisions and questions the data must support.
2. Define metrics, entity, cohort, and time windows.
3. Choose event grain, producer, source of truth, and identity behavior.
4. Adopt one naming and property grammar.
5. Draft contracts with privacy and lifecycle metadata.
6. Use AI to map supplied evidence, not to create product truth.
7. Implement the smallest useful slice.
8. Test raw payloads, validate schemas, and reconcile critical facts.
9. Monitor quality by event and producer.
10. 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](https://amplitude.com/taxonomy-generator)
- [Amplitude: CSV tracking-plan branches](https://amplitude.com/docs/data/csv-import-export)
- [Amplitude: official events and properties](https://amplitude.com/docs/data/official-events-and-properties)
- [Twilio Segment: create a tracking plan](https://app-canary.segment.com/academy/collecting-data/how-to-create-a-tracking-plan/)
- [Twilio Segment: tracking-plan validation](https://segment.com/data-hub/data-validation/)
- [PostHog: analytics naming guidance](https://newsletter.posthog.com/p/what-engineers-get-wrong-about-analytics)
- [European Commission: GDPR processing principles](https://commission.europa.eu/law/law-topic/data-protection/information-business-and-organisations/principles-gdpr_en)
- [ICO: pseudonymisation guidance](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/data-sharing/anonymisation/pseudonymisation/)
