Analytics Tracking Plan Template (Privacy-First, JSON Schema, GPC)
Privacy-first tracking plan: tiers, object_action naming, events, property dictionary, JSON Schema 2020-12, SchemaVer, consent and GPC gating, PII rules, QA
Cara menggunakan: Use it before instrumenting product analytics events on web, mobile or server. Fill the measurement questions and the tier of each event first, then the schemas and gating matrix. The main pitfall is collecting identifiers or free text 'just in case', which turns aggregate analytics into personal data processing.
Pratinjau
Analytics Tracking Plan: [Product name]
Privacy-first tracking plan for product analytics events. It covers measurement goals, event naming (object and action), the event catalogue, a property dictionary, event schemas written in JSON Schema 2020-12 with versioning through self-describing schemas (the Snowplow Iglu pattern is used as an example), the identity model, consent and Global Privacy Control (GPC) gating for each event, personal data rules, a platform coverage matrix, QA and validation, and the change process. The default is aggregate, cookieless measurement that needs no personal data; anything more is opt-in. Consent rules refer to the ePrivacy Directive 2002/58/EC Article 5(3) and GDPR Articles 6 and 7. Replace every
[bracketed]value and every row marked Example. This is a documentation format, not legal advice.
Document control
| Field | Value |
|---|---|
| Document ID | [ATP-PRODUCT-001] |
| Product and platforms | [Product name]: [Web / iOS / Android / Server] |
| Version | [1.0] |
| Status | [Draft / In review / Approved / Live / Superseded] |
| Owner | [@product-analytics-lead] |
| Approvers/reviewers | [@product-manager], [@privacy-reviewer or DPO], [@platform-engineering-leads], [@data-steward] |
| Last updated | YYYY-MM-DD |
| Classification | [Internal] |
| Schema registry | [Repository or registry URL] |
| Schema vendor namespace | [com.example.product] (Example: com.corvid.shop) |
| Default measurement tier | Tier A: aggregate, no identifiers, no device storage |
| Related documents | [Metric definitions], [DPIA reference if Tier B or C events exist], [Consent management configuration] |
Approvals
| Role | Name | Decision | Date |
|---|---|---|---|
| Product analytics lead | [@name] | [Approve / Approve with conditions / Reject] | YYYY-MM-DD |
| Privacy reviewer or DPO | [@name] | [Decision] | YYYY-MM-DD |
| Engineering lead (web) | [@name] | [Decision] | YYYY-MM-DD |
| Engineering lead (mobile) | [@name] | [Decision] | YYYY-MM-DD |
Revision history
| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | First draft |
| 1.0 | YYYY-MM-DD | [@name] | Example: Approved; checkout funnel events EVT-001 to EVT-008 |
| 1.1 | YYYY-MM-DD | [@name] | Example: Added experiment_exposed (EVT-010) for the checkout button test; schema 1-0-0 |
Contents
- Purpose, scope and measurement principles
- Measurement tiers and lawful basis
- Naming conventions
- Event catalogue
- Property dictionary
- Event schemas and versioning
- Identity model
- Consent and GPC gating
- Personal data rules
- Collection architecture and platform coverage
- QA and validation
- Change process and governance
- Retention, access and downstream use
- Glossary and references
- Standard and licence note
1. Purpose, scope and measurement principles
1.1 Purpose
This plan defines every analytics event that [Product name] sends, why it exists, what it contains, when it may be sent and how its quality is checked. It is the single source of truth for product managers, engineers, analysts and privacy reviewers. An event that is not in this plan must not be sent.
1.2 Principles
- Question first. Each event answers at least one measurement question (section 1.3).
- Aggregate by default. Prefer counts and distributions over per-person histories. Most funnels can be measured as step counts per day.
- No personal data required. No event requires a name, email, phone number, address, precise location, free text or a persistent device identifier.
- Cookieless by default. Tier A events store nothing on the device. Cookieless is not the same as consent-free: a client-side event is sent because our code instructs the device to send it, which is access under ePrivacy Article 5(3) (section 2.3).
- Consent and GPC respected. Client-side events fire only after consent unless a documented exemption applies in the market; Tier B and C events always need consent; nothing but server-side Tier A fires when GPC is on.
- First-party only. Events go to the organisation's own collection endpoint. No third-party tags, pixels or SDKs that send data to advertising networks.
- Schemas are contracts. Every event has a versioned schema and is validated at collection; invalid events are quarantined, not silently dropped.
1.3 Measurement questions
| ID | Question | Decision it informs | Metric (data/metric-definition) | Tier needed |
|---|---|---|---|---|
| MQ-01 (Example) | What share of checkouts started reach a completed order each day? | Checkout redesign priority | Checkout conversion rate | A (step counts) |
| MQ-02 (Example) | At which checkout step do most checkouts stop? | Which step to fix first | Step drop-off rate | A |
| MQ-03 (Example) | Which errors are shown most often during checkout? | Engineering backlog | Checkout error rate | A |
| MQ-04 (Example) | Does the new checkout button increase conversion per session? | Ship or roll back the A/B test | Conversion per exposed session | B (session key) |
| MQ-05 (Example) | How do product search results counts relate to add-to-cart? | Search relevance work | Search to cart rate | A |
| [MQ-nn] | [Question] | [Decision] | [Metric] | [A / B / C] |
1.4 Out of scope
- Advertising, retargeting and audience building for third parties.
- Cross-site or cross-app tracking, device fingerprinting and identity graphs.
- Session replay and keystroke capture.
- Anything not linked to a measurement question.
2. Measurement tiers and lawful basis
2.1 Tiers
| Tier | What it allows | Identifiers | Device storage or access | Consent | GPC on |
|---|---|---|---|---|---|
| A: Aggregate | Event counts and coarse context (page type, step, platform, country) | None | Nothing stored. Server-side events: no device access. Client-side events: our code instructs the device to send data, which is access under Art. 5(3) | Server-side: not needed. Client-side: required unless an exemption applies (section 2.3) | Server-side: allowed only if your privacy reviewer confirms they are outside opt-out scope. Client-side: off |
| B: Product analytics | Per-session sequences for funnels and experiments | Random session key, rotated per session | Session storage | Required (opt-in) | Off |
| C: Marketing measurement | Campaign attribution | Campaign parameters, persistent pseudonymous ID | Cookies or local storage | Required (opt-in) | Off |
Example: Corvid Commerce uses Tier A for all funnel and error events, Tier B only for the checkout experiment, and no Tier C events.
2.2 Lawful basis (EU and UK)
- Where an event involves storing information on the user's device or gaining access to information already there, Article 5(3) of the ePrivacy Directive (as implemented nationally) applies: consent is needed unless the storage or access is solely to carry out the transmission of a communication, or is strictly necessary to provide a service the user explicitly requested. Analytics is generally not strictly necessary for the service itself.
- Where an event processes personal data, the GDPR applies: choose a lawful basis under Article 6 (for analytics beyond strict necessity this is usually consent, which must meet Article 7 conditions: demonstrable, freely given, as easy to withdraw as to give).
- Record the lawful basis and purposes in the Record of Processing Activities (
compliance/gdpr-ropa). Tier B and C events normally need a DPIA screening (compliance/dpia). - Other jurisdictions: several US state privacy laws require businesses to honour opt-out preference signals such as GPC (for California, see the CCPA regulations, Cal. Code Regs. tit. 11, section 7025). Under the amendments effective 2026-01-01, a California business must display on its site whether it processed the signal as a valid opt-out (section 7025(c)(6)); check the current text at cppa.ca.gov. Check the current text for each market.
2.3 Cookieless is not automatically consent-free
The EDPB Guidelines 2/2023 on the technical scope of Article 5(3) of the ePrivacy Directive (version 2.0, adopted 7 October 2024) explain that "gaining access" covers any case where an entity instructs the terminal to send back information: cookies, but equally JavaScript that tells the browser to send requests with the targeted information, app code that calls an API endpoint, tracking pixels and URL tracking. A client-side analytics event without cookies or identifiers is therefore still within Article 5(3). The guidelines do not analyse the exemptions themselves.
Apply this to the tiers:
- Server-side Tier A events (Corvid Commerce: EVT-003, EVT-005, EVT-008) are recorded by the server while it handles a request the user made, such as adding an item or placing an order. No extra instruction is sent to the device, so they carry the lowest risk and need no consent under Article 5(3). The GDPR still applies if the record could relate to a person.
- Client-side Tier A events (EVT-001, EVT-002, EVT-004, EVT-006, EVT-007) need consent unless an exemption applies. The strictly-necessary exemption rarely covers analytics. Some supervisory authorities accept audience measurement without consent under strict national conditions (for example the conditions published by the French CNIL: first-party, aggregate statistics only, no cross-site tracking, limited retention, and information with a right to object). Such exemptions are national: list the markets where you rely on one, cite the national source, and gate the events behind analytics consent everywhere else.
- Tier B and C events always need consent.
Record the market-by-market reasoning in section 8.4 and review it when any Tier A event or property changes. If in doubt, gate client-side Tier A behind consent too.
3. Naming conventions
3.1 Event names: object and action
- Pattern:
<object>_<action>insnake_case, action in the past tense:cart_item_added,checkout_started,order_completed. - The object is a business noun from the domain glossary (
cart_item,checkout,order,product), not a UI element. - The action is a past-tense verb from a controlled list:
viewed,added,removed,started,completed,selected,searched,displayed,exposed,updated,failed. - Variation goes into properties, not names:
checkout_step_completedwithcheckout_step = "shipping", notshipping_step_completed. - Names are at most 40 characters, ASCII only, and never contain user data, IDs or dates.
3.2 Property names
snake_case, singular nouns, units in the name where relevant (price_amount_minor,duration_ms). Money is sent as an integer in minor units (cents) with a separatecurrency, never as a binary floating-point number.- Booleans start with
is_orhas_; enumerations list every allowed value in the schema. - Reserved envelope properties (section 5.1) are set by the collector or SDK, never by feature code.
3.3 Schema identifiers
Each event schema is identified by vendor, name, format and version, for example com.corvid.shop/cart_item_added/jsonschema/1-0-0. The vendor is the reversed domain of the organisation, optionally with a sub-namespace per product.
4. Event catalogue
| Event ID | Event name | Trigger (precise) | Tier | Platforms | Key properties | Questions | Owner | Status |
|---|---|---|---|---|---|---|---|---|
| EVT-001 (Example) | product_viewed | Product detail page rendered with a product loaded | A | Web, iOS, Android | product_id, category_id, page_type | MQ-05 | [@catalogue-pm] | Live |
| EVT-002 (Example) | product_searched | Search results returned to the user | A | Web, iOS, Android | results_count, category_id (no query text) | MQ-05 | [@search-pm] | Live |
| EVT-003 (Example) | cart_item_added | Server confirms the item was added to the cart | A | Server | product_id, quantity, price_amount_minor, currency | MQ-05 | [@checkout-pm] | Live |
| EVT-004 (Example) | checkout_started | User opens the first checkout step with a non-empty cart | A | Web, iOS, Android | checkout_step, platform | MQ-01, MQ-02 | [@checkout-pm] | Live |
| EVT-005 (Example) | checkout_step_completed | Server accepts the data of a checkout step | A | Server | checkout_step | MQ-02 | [@checkout-pm] | Live |
| EVT-006 (Example) | payment_method_selected | User confirms a payment method type | A | Web, iOS, Android | payment_method_type | MQ-02 | [@payments-pm] | Live |
| EVT-007 (Example) | error_displayed | An error message is shown in checkout | A | Web, iOS, Android | error_code, checkout_step | MQ-03 | [@checkout-eng] | Live |
| EVT-008 (Example) | order_completed | Order service confirms the order | A | Server | currency, item_count | MQ-01 | [@orders-pm] | Live |
| EVT-009 (Example) | checkout_session_linked | Same as EVT-004, adds the session key for experiment analysis | B | Web | session_key | MQ-04 | [@checkout-pm] | Live |
| EVT-010 (Example) | experiment_exposed | User sees the experiment surface for the first time in the session | B | Web | experiment_id, variant_id, session_key | MQ-04 | [@growth-pm] | Live |
| [EVT-nnn] | [object_action] | [Trigger] | [A / B / C] | [Platforms] | [Properties] | [MQ-nn] | [@owner] | [Status] |
Prefer server-side events (EVT-003, EVT-005, EVT-008) wherever the server already knows the fact: they are more reliable than client events, need no device access and cannot be blocked or duplicated by retries in the browser.
5. Property dictionary
5.1 Envelope properties (set by the collector or SDK)
| Property ID | Name | Type | Description | Example | Classification |
|---|---|---|---|---|---|
| PROP-001 | event_id | string (UUID) | Unique ID of this event, used for deduplication | 5b1c... (Example, truncated) | Internal |
| PROP-002 | event_ts | string (date-time, UTC) | Time the event occurred on the device or server | 2026-10-14T09:12:44Z | Internal |
| PROP-003 | schema | string | Self-describing schema URI | iglu:com.corvid.shop/cart_item_added/jsonschema/1-0-0 | Internal |
| PROP-004 | platform | enum | web, ios, android, server | web | Internal |
| PROP-005 | app_version | string | Application release version | 4.12.0 | Internal |
| PROP-006 | locale | string | Interface locale | de-DE | Internal |
| PROP-007 | country | string (ISO 3166-1 alpha-2) | Derived at the edge from the request; the IP address is then discarded | DE | Internal |
| PROP-008 | consent_state | object | Booleans per consent category at the time of the event | {"analytics": false} | Internal |
| PROP-009 | gpc | boolean | Whether a GPC signal was present | true | Internal |
5.2 Event properties
| Property ID | Name | Type and constraints | Description | Example | Classification | Could identify a person? |
|---|---|---|---|---|---|---|
| PROP-010 | page_type | enum: home, category, product, cart, checkout, confirmation | Template type, never the URL | product | Internal | No |
| PROP-011 | product_id | string, pattern ^PRD-[0-9]{6}$ | Catalogue product identifier | PRD-204118 | Internal | No |
| PROP-012 | category_id | string | Catalogue category | CAT-0042 | Internal | No |
| PROP-013 | results_count | integer, minimum 0 | Number of search results | 37 | Internal | No |
| PROP-014 | quantity | integer, 1 to 99 | Units added | 2 | Internal | No |
| PROP-015 | price_amount_minor | integer, minimum 0, in the minor unit of currency (for EUR, cents) | Unit price at time of event | 2490 (EUR 24.90) | Internal | No |
| PROP-016 | currency | string (ISO 4217) | Currency of amounts | EUR | Internal | No |
| PROP-017 | checkout_step | enum: cart_review, shipping, payment, review | Step of the checkout | shipping | Internal | No |
| PROP-018 | payment_method_type | enum: card, wallet, bank_transfer, invoice | Type only, never card or account data | wallet | Internal | No |
| PROP-019 | error_code | string, pattern ^CHK-E[0-9]{3}$ | Error code from the error catalogue, never the message text | CHK-E104 | Internal | No |
| PROP-020 | item_count | integer, minimum 1 | Items in the completed order | 3 | Internal | No |
| PROP-021 | session_key | string, 128-bit random, rotated each session | Links events within one session (Tier B only) | k7Qe... (Example, truncated) | Confidential | Yes, as a pseudonymous identifier within a session |
| PROP-022 | experiment_id | string | Experiment identifier from the A/B Test Plan (product/ab-test-plan) | EXP-2026-031 | Internal | No |
| PROP-023 | variant_id | enum per experiment | Variant shown | treatment | Internal | No |
Classification labels follow the Data Classification Policy (data/data-classification-policy).
6. Event schemas and versioning
6.1 Schema dialect and self-describing events
Write event schemas in JSON Schema 2020-12 (meta-schema https://json-schema.org/draft/2020-12/schema) unless your collection tool requires another dialect. Make every event self-describing: the payload names the exact schema and version it claims to follow, so the collector can validate it and the warehouse can load it into the right table version.
Snowplow's Iglu registry is a well-known open implementation of this pattern (Apache-2.0): a self-describing JSON object has a schema URI of the form iglu:<vendor>/<name>/jsonschema/<version> and a data object. Note that Snowplow's documentation describes its schemas as JSON Schema draft 4 documents with an Iglu self-describing meta-schema; if you adopt Snowplow, author schemas in its format. The example below uses the same envelope idea with a vendor-neutral JSON Schema 2020-12 schema.
6.2 Example schema
Example: com.corvid.shop/cart_item_added/jsonschema/1-0-0
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.corvid.example/com.corvid.shop/cart_item_added/jsonschema/1-0-0",
"title": "cart_item_added",
"description": "Server confirmed that a product was added to a cart. Tier A: no identifiers.",
"type": "object",
"properties": {
"product_id": { "type": "string", "pattern": "^PRD-[0-9]{6}$" },
"quantity": { "type": "integer", "minimum": 1, "maximum": 99 },
"price_amount_minor": { "type": "integer", "minimum": 0 },
"currency": { "type": "string", "pattern": "^[A-Z]{3}$" }
},
"required": ["product_id", "quantity", "price_amount_minor", "currency"],
"additionalProperties": false
}
Example event instance (Example, fictional data):
{
"schema": "iglu:com.corvid.shop/cart_item_added/jsonschema/1-0-0",
"data": {
"product_id": "PRD-204118",
"quantity": 2,
"price_amount_minor": 2490,
"currency": "EUR"
}
}
additionalProperties: false is deliberate: an engineer cannot add a property (for example an email address) without a reviewed schema change.
Money is an integer in minor units on purpose. A "type": "number" with "multipleOf": 0.01 looks natural but fails valid prices in common validators, because binary floating point cannot represent most decimal fractions exactly (0.29 / 0.01 evaluates to 28.999999999999996 in JavaScript). If a consumer needs decimals, send a string matching ^[0-9]+\.[0-9]{2}$ instead; never rely on multipleOf with a fractional divisor. Currencies with no minor unit (for example JPY) or with three decimals (for example KWD) follow the ISO 4217 exponent of currency.
6.3 Versioning rules
Use SchemaVer, as defined by Snowplow for Iglu: MODEL-REVISION-ADDITION, starting at 1-0-0.
| Change | Example | Version bump | Approval |
|---|---|---|---|
| Change that cannot validate existing data (new required property, type change, removed property) | quantity becomes required string | MODEL (1-0-0 to 2-0-0) | Plan owner, data steward, privacy reviewer; consumers notified |
| Change that may fail some existing data | Narrower enum or pattern | REVISION (1-0-0 to 1-1-0) | Plan owner and data steward |
| Change compatible with all existing data | New optional property | ADDITION (1-0-0 to 1-0-1) | Plan owner; privacy reviewer if the property is new to the dictionary |
Rules:
- Published schema versions are immutable. Fix mistakes with a new version.
- A MODEL change creates a new table or column family downstream; keep both versions loading until all clients have upgraded.
- Every new property passes the personal data rules of section 9 before review.
- Record schema versions consumed by each data product in its Data Contract (
data/data-contract).
7. Identity model
| Identifier | Tier | Scope | Storage | Created | Expires | Sent to third parties |
|---|---|---|---|---|---|---|
| None | A | Single event | None | n/a | n/a | No |
session_key (PROP-021) | B | One browser session | Session storage only | After analytics consent | End of session; never reused | No |
| Pseudonymous user ID | C (not used by Corvid Commerce) | Across sessions | [Cookie or local storage] | After consent | [Period] | No |
| Authenticated account ID | Not used in analytics | n/a | n/a | n/a | n/a | No |
Rules:
- No fingerprinting. Do not derive identifiers from device characteristics, IP address, fonts, canvas or similar signals.
- No raw IP storage. The edge derives
countryand discards the IP address before the event is stored. - No cross-device linking or aliasing of anonymous and authenticated identities. If a future question needs it, run a DPIA first and add it as a Tier C change.
- Server-side joins only by design. If a business question needs order data per session (for example revenue per experiment variant), compute it in the Checkout data product from server events under the data product's access controls, not by sending order identifiers from the client.
- Rotation. Session keys are random 128-bit values generated per session; they are not derived from any account or device data.
8. Consent and GPC gating
8.1 Consent categories
| Category | Covers | Default before choice | Withdrawal |
|---|---|---|---|
| Exempt audience measurement | Server-side Tier A events, and client-side Tier A events only in markets where the section 2.3 assessment records an exemption | On | Server-side: not applicable, disclosed in the privacy policy. Client-side under an exemption: the user can object in privacy settings, and a refusal or GPC stops these events |
| Analytics | Client-side Tier A events where no exemption applies, Tier B events and the session key | Off | One click in privacy settings; takes effect immediately |
| Marketing | Tier C events | Off | Same |
8.2 Gating decision
The SDK and the server apply this decision before any event leaves the device or the request handler. GPC is checked before consent, so a signal always wins over an earlier choice.
8.3 Per-event gating matrix
| Event | Tier | Before choice | Consent given | Consent refused | GPC on |
|---|---|---|---|---|---|
| EVT-003, EVT-005, EVT-008 (Example) | A, server-side | Send | Send | Send | Send (Corvid Commerce assessment: server-side Tier A is outside opt-out scope, see 8.4) |
| EVT-001, EVT-002, EVT-004, EVT-006, EVT-007 (Example) | A, client-side | Send only in markets with a recorded exemption; otherwise do not send | Send | Do not send (a refusal is also an objection under an exemption) | Do not send |
| EVT-009, EVT-010 (Example) | B | Do not send | Send | Do not send | Do not send, even if consent was given earlier |
| [EVT-nnn] | [Tier] | [Rule] | [Rule] | [Rule] | [Rule] |
8.4 GPC handling and assessment record
- Detection: read the
Sec-GPC: 1request header on the server andnavigator.globalPrivacyControlin the browser. Treat either as a valid signal. The GPC specification is a W3C Working Draft at the time of writing; check the current status at w3.org/TR/gpc. - Effect: GPC overrides an earlier consent for Tier B and C on that browser for as long as the signal is present. Do not show a prompt asking the user to override GPC.
- Disclosure: state in the privacy policy that GPC is honoured, and consider publishing a
/.well-known/gpc.jsonsupport resource as described in the specification. For California, display on the site whether the GPC signal was processed as a valid opt-out (CCPA regulations section 7025(c)(6), as amended effective 2026-01-01; check the current text). - Assessment record (Example): "Server-side Tier A events (EVT-003, EVT-005, EVT-008) carry no identifier, use no device storage and send no instruction to the device, so they need no consent under Article 5(3); they are outside GPC opt-out scope because nothing is sold or shared. Client-side Tier A events (EVT-001, EVT-002, EVT-004, EVT-006, EVT-007) are access under Article 5(3) (EDPB Guidelines 2/2023, version 2.0). They rely on [national audience-measurement exemption, with citation] in [markets], and are gated behind analytics consent in every other EU and EEA market and in the UK. In the US they are sent unless GPC or a refusal is present. Reviewed by [@dpo] on YYYY-MM-DD. Re-review when any Tier A event, property or market changes."
9. Personal data rules
| Rule ID | Rule | Enforced by |
|---|---|---|
| PII-01 | No names, emails, phone numbers, postal addresses, account numbers, card data or government IDs in any property | Schema review; collector pattern scan; quarantine on match |
| PII-02 | No free-text properties. Search terms, form inputs and error messages are never sent; use counts, enums and error codes | Schema review (additionalProperties: false, enums, patterns) |
| PII-03 | No full URLs, referrers or query strings; send page_type instead | SDK configuration; collector strips URL fields |
| PII-04 | No raw IP address or precise location stored; country only, derived at the edge | Edge configuration |
| PII-05 | No special-category data (health, religion, sexual orientation and others under GDPR Art. 9) inferred or recorded, including through product categories that reveal it | Schema review; category allow-list |
| PII-06 | No data about children beyond what the service strictly needs; no Tier B or C events on surfaces aimed at children | Product review |
| PII-07 | No third-party tags or SDKs that receive event data | Content security policy; dependency review |
| PII-08 | Events found to contain personal data are deleted from raw storage and handled as a data incident | Data Incident Postmortem (data/data-incident-postmortem) |
10. Collection architecture and platform coverage
10.1 Collection flow
The flow below keeps all events first-party, validates them against the registry and quarantines failures for review.
10.2 Platform coverage matrix
| Event | Web | iOS | Android | Server | Notes |
|---|---|---|---|---|---|
EVT-001 product_viewed (Example) | Live 1-0-0 | Live 1-0-0 | Live 1-0-0 | n/a | |
EVT-002 product_searched (Example) | Live 1-0-0 | Live 1-0-0 | Planned | n/a | Android in release [x.y] |
EVT-003 cart_item_added (Example) | n/a | n/a | n/a | Live 1-0-0 | Server only |
EVT-004 checkout_started (Example) | Live 1-0-0 | Live 1-0-0 | Live 1-0-0 | n/a | |
EVT-005 checkout_step_completed (Example) | n/a | n/a | n/a | Live 1-0-0 | Server only |
EVT-006 payment_method_selected (Example) | Live 1-0-0 | Live 1-0-0 | Live 1-0-0 | n/a | |
EVT-007 error_displayed (Example) | Live 1-0-0 | Live 1-0-0 | Live 1-0-0 | n/a | |
EVT-008 order_completed (Example) | n/a | n/a | n/a | Live 1-0-0 | Server only |
EVT-009 checkout_session_linked (Example) | Live 1-0-0 | Not tracked | Not tracked | n/a | Experiment on web only |
EVT-010 experiment_exposed (Example) | Live 1-0-0 | Not tracked | Not tracked | n/a | Experiment on web only |
| [EVT-nnn] | [Status version] | [Status version] | [Status version] | [Status version] | [Notes] |
11. QA and validation
11.1 Before release
| Check | How | Pass criterion (Example) |
|---|---|---|
| Schema lint and compatibility | CI validates every schema against the 2020-12 meta-schema and checks the version bump against the previous version | No errors; bump matches section 6.3 |
| Payload tests | Unit tests build each event and validate it against its schema | 100% of events covered |
| Consent tests | End-to-end tests with consent refused, and before choice in a market without an exemption: no client-side Tier A, Tier B or C requests leave the browser | Zero client-side analytics requests |
| GPC tests | End-to-end tests with the Sec-GPC: 1 header and navigator.globalPrivacyControl set | Zero client-side analytics requests; server-side Tier A per section 8.3 |
| Personal data scan | Tests fill forms with fictional data (for example test.user@example.com) and assert the value never appears in any event | No match |
| Trigger review | Product owner checks each trigger in a staging build with the debug view | Signed off in the release ticket |
11.2 In production
| Monitor | Measure | Threshold (Example) | Action |
|---|---|---|---|
| Invalid event rate | Quarantined / received, per schema | Above 0.5% per hour | Ticket to owning team; fix or roll back |
| Volume per event | Count per hour vs 28-day same-hour median | Outside 50% to 200% | Investigate release or outage |
| Platform parity | Events per platform vs share of traffic | Deviation above 20% | Check implementation drift |
| Consent compliance | Tier B events, or client-side Tier A events outside an exemption market, received without analytics consent or with GPC | Any | Data incident (data/data-incident-postmortem) |
| Funnel consistency | order_completed (EVT-008) count vs orders in the Orders data product | Difference above 1% per day | Investigate missing server events |
Production monitors follow the Data Quality Standard (data/data-quality-standard); register them as rules in the Checkout data contract (for example a completeness rule on daily event volume).
12. Change process and governance
12.1 Roles
| Role | Responsibility |
|---|---|
| Plan owner (product analytics lead) | Maintains this plan and the registry; approves names and schemas |
| Privacy reviewer | Approves tier, gating and personal data rules for each change |
| Event owner (product manager) | Defines the question, trigger and properties; accountable for the event's use |
| Platform engineers | Implement and test events per platform |
| Data steward (Checkout) | Maintains downstream models and the data contract |
12.2 Lifecycle
Every event moves through these states, and its current state is shown in the Status column of the event catalogue (section 4).
12.3 Change request content
A change request (pull request against the plan and registry) states: the measurement question, the event or property change, the schema diff and version bump, the tier and gating, the personal data assessment, platforms and releases, downstream models and metrics affected, and the removal date for temporary events. Target review time: [3] business days.
12.4 Deprecation
Mark an event Deprecated in the catalogue with a removal date, notify consumers of the data product, stop sending it in the next releases, and keep the schema in the registry for historical loads. Remove downstream columns only after the data retention period for the raw events has passed or the data has been migrated.
13. Retention, access and downstream use
| Data | Retention (Example) | Access | Notes |
|---|---|---|---|
| Raw Tier A events | 13 months | Product analytics team | Partition expiry enforced by the platform |
| Raw Tier B events | 90 days | Named analysts on the experiment | Deleted when the experiment analysis is approved, at the latest after 90 days |
| Quarantined events | 14 days | Plan owner and platform engineers | Deleted on expiry; personal data findings handled as incidents |
| Aggregates (daily counts) | 25 months | Organisation-wide via the semantic layer | No identifiers |
Downstream, events feed the Checkout data product (fct_checkout_sessions) and the metrics defined in Metric Definition (data/metric-definition). Experiment analysis follows the A/B Test Plan (product/ab-test-plan). Retention follows the Data Retention and Deletion Standard (data/data-retention-deletion-standard); classification follows the Data Classification Policy (data/data-classification-policy).
14. Glossary and references
14.1 Glossary
| Term | Meaning |
|---|---|
| Event | A record that something happened in the product, sent with a schema |
| Self-describing event | An event that names the exact schema and version it follows |
| Tracking plan | The governed list of events, properties, schemas and rules for a product |
| Measurement tier | Privacy cost class of an event (A aggregate, B product analytics, C marketing) |
| GPC | Global Privacy Control: a browser signal that the user does not want their data sold or shared, sent as the Sec-GPC header and exposed as navigator.globalPrivacyControl |
| SchemaVer | MODEL-REVISION-ADDITION versioning scheme for event schemas |
| Quarantine | Holding area for events that failed validation |
| Fingerprinting | Identifying a device from its characteristics; prohibited by this plan |
14.2 References
| Reference | Version or date checked | Use |
|---|---|---|
| JSON Schema, Draft 2020-12, json-schema.org/specification | Current release, checked 2026-10-24 | Schema dialect |
| Snowplow Iglu Central and Snowplow schema documentation, github.com/snowplow/iglu-central, docs.snowplow.io | Iglu Central release r167 (2025-06-12), Apache-2.0; docs checked 2026-10-24 | Self-describing schema pattern and SchemaVer (concepts) |
| Global Privacy Control (GPC), W3C Working Draft, w3.org/TR/2026/WD-gpc-20260924/ | Working Draft 24 September 2026; check the latest at w3.org/TR/gpc | Signal names and .well-known resource |
| Directive 2002/58/EC (ePrivacy Directive), Article 5(3) | Consolidated text, checked 2026-10-24 | Device storage and access consent rule |
| EDPB Guidelines 2/2023 on Technical Scope of Art. 5(3) of ePrivacy Directive, version 2.0, edpb.europa.eu | Adopted 7 October 2024 (published 16 October 2024) | Scope of Article 5(3) beyond cookies, including JavaScript, pixels and URL tracking |
| Regulation (EU) 2016/679 (GDPR), Articles 6, 7 and 9 | Checked 2026-10-24 | Lawful basis, consent conditions, special categories |
| California CCPA regulations, Cal. Code Regs. tit. 11, section 7025 | Amendments effective 2026-01-01; check the current text at cppa.ca.gov | Opt-out preference signals and the 7025(c)(6) display duty |
| Segment, Amplitude, Avo tracking plan formats | Product documentation, names only | Industry practice (no text used) |
Standard and licence note
Based on JSON Schema Draft 2020-12, the self-describing schema and SchemaVer concepts published by Snowplow for Iglu (Apache-2.0, github.com/snowplow/iglu-central), the W3C Global Privacy Control Working Draft, Article 5(3) of Directive 2002/58/EC, EDPB Guidelines 2/2023 (version 2.0) and Articles 6, 7 and 9 of Regulation (EU) 2016/679, all paraphrased in original words. This is a documentation format, not legal advice. Snowplow, Segment, Amplitude and Avo are trademarks of their owners; this template is not affiliated with or endorsed by them, and no vendor text is reproduced. The text is original, written for this collection; Corvid Commerce and all example data are fictional. Check the current official versions and the consolidated legal texts before use. Template licence: MIT.
Templat terkait
Dashboard Specification Template (BI Report, WCAG 2.2)
Audience and decisions, questions, KPI list linked to metric definitions, wireframe, filters and drill paths, row-level security, refresh, WCAG 2.2, performance budget, sunset
Rekayasa & Tata Kelola DataData Classification Policy Template (FIPS 199, ISO/IEC 27002 5.12)
Classification levels and criteria, FIPS 199 impact method, personal and special-category flags, labelling, handling matrix incl. AI use, discovery, declassification
Rekayasa & Tata Kelola DataData Contract Template (ODCS v3.2.0)
Producer-consumer data contract: schema, semantic roles, quality rules, SLA properties, servers and variables, roles, pricing, AI context, ODCS v3.2.0 YAML