An event is a record that one person did one particular thing at one particular moment, and a property is a fact attached to that record describing the case.
The model a product emits is deliberately small. An event carries a name, a timestamp, an identifier for the person and a set of properties. Everything a product analytics practice ever reports is arithmetic over rows of that shape, which is why a badly chosen name or a missing property is expensive in a way a badly chosen chart is not. A chart can be rebuilt this afternoon. An event that was never recorded in March cannot be recovered in June.
That permanence is what makes the naming a product manager's problem. An
engineer adding an event has a working name in mind within four seconds, and
the name they choose describes the code they are standing in, which is a
button, a component or a handler. Six months later an analyst opens the tool,
finds an event called submit2 and has no way to find out what it meant,
because the person who wrote it has moved to another team.
The sections below set out what an event holds and the three kinds of property it can carry. They then give a naming convention and show one real event set beside the same set named properly. Finally they take the choice between many specific events and a few general ones with properties, which is the decision that shapes a taxonomy more than any other.
What an event records and what a property adds
An event without properties answers one question, which is how many times the action happened.
An invoicing product recording a bare Invoice Sent event can report how many
invoices went out last month and nothing else. Four properties turn that
single row into a source for dozens of questions. Recording the channel, the
number of line items, the total amount and the currency lets a team ask how
many invoices went out by email. It also lets the team ask how the line item
count affects the days between sending and payment, and what value of invoices
accounts send during their first thirty days.
The general rule behind that is worth stating plainly. An event answers when and how often. Its properties answer for whom, of what kind and how much. A team that finds itself unable to answer a question is almost always missing a property rather than an event.
Three kinds of property
Properties attach to three different things, and a team that puts one in the wrong place loses the ability to ask about history.
- Event properties describe the particular action. The channel an invoice went out on, the number of line items, the amount and the currency.
- User properties describe the person who did it. Their role in the account, the month they first signed in, the language they use the product in.
- Account properties describe the organisation they belong to. The plan it pays for, the industry it works in, the number of days since it signed up.
The distinction that costs teams most is between a user or account property and an event property carrying the same fact. Most analytics tools hold the current value of a user property and overwrite it when it changes, which is the correct behaviour for answering a question about today and wrong for answering a question about March.
A worked case makes the loss concrete. An invoicing product holds plan as an
account property. An account on the starter plan in January upgrades to the
growth plan in June. In July an analyst asks how invoicing behaviour differs
between the two plans, and every event that account produced since January now
counts as growth plan behaviour, including six months of activity that
happened on starter. The upgrade itself is invisible, and the starter plan
looks emptier than it was.
The repair is to record the plan on the event as well, so each row carries the plan it was produced under. Storage is cheap and the alternative is a class of question the product can never answer again.
Naming an event so it still reads in a year
A naming convention exists so that somebody who has never seen an event can guess what it counts.
The convention most widely published is the object action form, which Segment
sets out in its own data collection guidance. The object comes first, the
action second, and the action goes in the past tense. Invoice Sent,
Payment Failed, Report Exported. Putting the object first groups every
event about invoices together in an alphabetical list, which is the small
practical reason the order matters.
Three rules carry almost all of the value.
- The object comes first and the action follows it, so related events sort together and a person can scan the list.
- The action is in the past tense, because an event records something that already happened and a present tense name reads as a command.
- No value ever appears in a name.
invoice_sent_by_emailandinvoice_sent_by_postshould be one event with achannelproperty.
The third rule is the one broken most often and the most expensive to undo. A taxonomy that encodes values in names grows one event for every value, so a team asking how many invoices went out in total has to write a query that unions four event names and will forget the fifth when it ships.
Casing matters less than consistency. Either every event is Title Case and
every property is snake case, or everything is snake case throughout. What
breaks a taxonomy is a tool holding Invoice Sent, invoice_sent and
InvoiceSent as three separate events, which is what happens when nobody
wrote the choice down.
One event set named badly and the same set named well
The table below is a real shape of problem. Four engineers added events to an invoicing product over two years with no convention between them.
| Names as first written | The action, named well | The question the good name answers |
|---|---|---|
click_send, sendInvoice2, invoice_sent_v2 | Invoice Sent | How many invoices an account sends in a month, across the whole history |
newpage | Invoice Viewed | Whether the customer opened the invoice before paying it |
btn_pay | Payment Recorded | The number of days between an invoice going out and the money arriving |
error | Payment Failed, with a reason property | Which failure reason costs the most revenue each month |
The left column is worse than it looks, because two of the four problems are
invisible in the tool. Three names for one action mean every count of invoices
sent is wrong unless the analyst knows all three, and nobody tells them.
A single error event covering payment failures, import failures and
validation failures means the one question worth asking, which is why payments
fail, cannot be asked at all without a property that was never recorded.
The right column is also not free. Renaming an event splits its history at the rename, so the old name and the new name each hold part of the record. That is the reason to settle a convention early, when a taxonomy has eleven events rather than three hundred.
Choosing between many specific events and few general ones
The same set of actions can be modelled as many narrow events or a few broad ones carrying properties, and the choice changes what is easy to ask.
An invoicing product sends invoices, payment reminders and receipts. One
design records Invoice Sent, Reminder Sent and Receipt Sent as three
events. The other records a single Document Sent event with a
document_type property holding one of three values.
The single event with a property is easier to total and easier to extend. A count of all documents sent is one query, a count of invoices is the same query with a filter, and adding a fourth document type next year changes a property value with no report to rewrite. Three separate events make the total a union that somebody will forget to update.
The test that decides it is whether the actions differ in the business. Two
actions belong in one event when what varies between them is an attribute of
the same act and both carry the same properties. They belong in separate
events when they mean different things, happen to different people or carry
different properties. Invoice Sent and Payment Failed are separate under
that test, because one is done by the seller and the other happens to the
buyer, and almost nothing about their properties matches.
One further constraint limits what any property can be. A property whose values are unbounded cannot be grouped usefully, so a raw search string, a full web address with its query parameters and a free text note all produce charts with one bar per row. A team that needs the raw value should record a bounded companion beside it, such as a count of results returned in bands, which is the property every report will actually use.
A well named set of events with well chosen properties is a decision a team made once, over an afternoon, under argument. A decision that lives only inside the code is one nobody outside the team can follow and nobody inside it can defend two years later. The set needs a document, with an owner and a reason against every row, and that document is the subject of the next page.