Event & property naming
A short, opinionated style guide for event and property names.
There's no schema enforcement on event or property names — Millimetric will store whatever you send. But analytics taxonomies rot fast unless you have a convention. Here's ours.
Event names
snake_case, past tense, scoped to the actor.
✅ signup
✅ trial_started
✅ checkout_completed
✅ invite_sent
✅ agent_task_completed
❌ Sign Up
❌ signing-up
❌ signupCompleted
❌ Signup Successful$-prefix is reserved
System events emitted by the SDK or the server start with $. Don't define your own $-events; they're indistinguishable from system ones in the dashboard.
| $pageview | Browser SDK on load and SPA navigation. | | $identify | Server, on POST /v1/identify. |
Verb in the past tense
signup is fine, but signed_up is better. Past tense reads naturally in funnel queries: "users who signed_up then subscribed".
That said, the existing convention in this codebase uses bare nouns/short verbs (signup, purchase, clicked_pricing) — both work. Pick one and stick to it.
Don't pack multiple events into a name
Property cardinality is cheap. Event-name cardinality is what kills your dashboards.
Roughly 30–50 events is plenty
If you have 200 distinct event names, you almost certainly should have fewer events with more properties.
Property names
snake_case. Type the value. Include units where ambiguous.
Booleans named as questions
is_paid, has_premium, was_invited, did_complete_onboarding. Reads nicely in WHERE clauses.
Units on numbers, always
duration_ms, amount_cents, latency_ms, size_bytes, weight_kg. Pick a unit per metric and never mix.
Money in cents
Or any fixed-precision integer. Never floats for revenue. amount_cents: 4900, plus currency: "usd". Always together.
$-prefix on properties means "ambient context"
The browser SDK adds $viewport_w, $viewport_h, $language, $timezone. Following that convention for your own ambient context ($session_user_role, $build_version) keeps event-specific properties visually distinct from cross-cutting ones.
Conventions tools rely on
If you set these with the listed names, dashboards and MCP tools will Just Work.
utm_source, utm_medium, utm_campaign, utm_content, utm_term
Classifier (also reads them off url)
fbclid, gclid, ttclid, msclkid, li_fat_id
Classifier
amount_cents + currency
Revenue dashboards (roadmap)
experiment_id + variant
A/B test analysis (roadmap)
plan (string)
Cohort filtering on user-tier
path (on the event itself, not in properties)
Top-paths breakdown
A small starter taxonomy
Steal this for a SaaS product:
$pageview
every navigation
path, url, referrer (auto-captured)
signup
account created
plan, referral_code, invited
trial_started
trial begins
plan, trial_days
subscription_started
first paid charge
plan, amount_cents, currency, billing_period
subscription_changed
upgrade/downgrade
from_plan, to_plan, amount_cents, currency
feature_used
a notable in-app action
feature, result
invite_sent
user invites a teammate
count
support_ticket_opened
help requested
category, priority
error_shown
user-facing error
error_code, http_status
account_deleted
farewell
reason
For e-commerce, swap signup/trial_*/subscription_* for viewed_product, added_to_cart, removed_from_cart, started_checkout, completed_checkout, refunded. See the E-commerce recipe.
Renaming is a chore — pick now
There's no rename API. Renames happen by:
Start emitting the new name.
Wait for the retention window to pass (default 90 days).
Old events expire, new events have the new name.
Or query both names with a CASE WHEN until the old one rolls off. Easiest by far is to pick a convention before you start and write it down somewhere your team will read it.
Last updated
Was this helpful?