Events and Properties
Date: 2026-08-16
The atom of modern analytics: a named thing that happened, with key-value context attached. Everything downstream — funnels, cohorts, attribution — is a query over a table of these, so what you don’t attach at fire time is gone.
What it is
An event is a record that something happened, carrying a name, a timestamp, an identifier for who it happened to, and properties — key-value pairs describing the circumstances.
{
"event": "add_to_cart",
"timestamp": "2026-08-16T10:12:04Z",
"user_id": "u_8421",
"anonymous_id": "a_77",
"properties": {
"product_id": "4471",
"price_pence": 2400,
"quantity": 2,
"currency": "GBP"
}
}That’s the whole model. A stream of these, ordered by time, is the raw material for every analysis.
Three kinds of property
The distinction decides where a value gets set, and getting it wrong is why properties go missing.
| Kind | Attached to | Set by | Example |
|---|---|---|---|
| Event properties | One event | The call site | product_id, price_pence |
| Super properties | Every event from this client | The SDK, once | device, app_version, consent_state |
| User properties | The person, not the event | An identify call | plan_tier, first_order_date, lifetime_orders |
Anything a developer has to remember to include is a property that will be missing on a third of events. If it applies to every event, make it a super property set once at initialisation — see Event Taxonomy Design.
User properties are the awkward ones: they describe a person at a moment, and most tools store only the current value. So “what plan tier were they on when this happened” is unanswerable unless you also stamp it onto the event.
Immutability
Events are facts about the past and are not editable. That has consequences people meet late:
- You cannot backfill a property you didn’t collect. If
delivery_optionwasn’t oncheckout_startedin March, no amount of work recovers March - Corrections are new events, not edits. A refund is a
refundevent, not an amendedpurchase - Schema changes apply forwards only. Adding a property today creates a seam: queries spanning it must handle both shapes
The practical rule that follows: when in doubt, attach it. Storage is cheap and the property you didn’t collect is unrecoverable. The counterweight is Cardinality — unbounded values get truncated — and PII in Analytics, where attaching the wrong thing is a disclosure incident.
Naming and typing
Covered properly in Event Taxonomy Design, but the two that bite immediately:
- One meaning per property name, permanently.
valuemeaning order total on one event and item price on another is a trap you can’t undo - Fix the unit in the name.
price_penceis ugly and correct;pricewill eventually be off by 100×
Where the model strains
- Duration. An event is a point in time. “Time spent on page” needs two events and a subtraction, or a heartbeat, and every tool does it differently
- State. Events describe changes; they don’t describe how things are. Reconstructing current state means replaying the stream, which is why a profile store exists alongside — Customer Data Platforms
- Ordering. Events arrive out of order across devices and networks. Client timestamps drift; server timestamps lose the client’s reality. Most tools keep both, and knowing which your query uses matters
- Volume. Every event is a row forever. Autocapture generates orders of magnitude more than deliberate instrumentation — Autocapture
Why this replaced pageviews
The older model counted page loads and inferred behaviour from URLs. It broke on single-page apps, and it couldn’t describe anything that wasn’t a navigation — see Page Views vs Events.
The event model’s advantage is that the thing you care about is recorded directly rather than inferred. Its cost is that you have to decide in advance what you care about, and you only get what you asked for.