Event naming

A naming convention for custom events that survives contact with a real team, and why it matters more here than in most tools.

Markdown
Updated Sep 2, 2026
On this page
  1. Object, then action
  2. Never put a variable value in the name
  3. Put the variable in a property instead
  4. Good and bad
  5. Where the name comes from matters too

A good event name describes what happened, not what happened to whom or when. Get this wrong early and every dashboard built on top of it inherits the mess.

Object, then action

Name events object_action: signup_completed, invite_sent, plan_upgraded, checkout_started. Lowercase, snake_case, no spaces. This reads the same in the Events catalog, in a funnel step, and in a filter: you never have to remember whether you called it SignupCompleted in one place and signup-complete in another.

The tracker's own automatic events follow this rule for a reason: pageview, outbound, download, page_leave, web_vital are a small, fixed vocabulary. It never invents outbound_hero_cta or outbound_pricing_partner: the specifics live in properties, not the name. Do the same for your own events.

Never put a variable value in the name

Every event name becomes a dimension in a daily counter (rollups, metric event_count). That counter is bounded per site per day: once too many distinct dimension values show up for one metric, the long tail folds into a single _other bucket so the table doesn't grow without limit. An event name is exactly the kind of thing that folds.

If you name events plan_upgraded_pro, plan_upgraded_business, plan_upgraded_enterprise instead of one plan_upgraded event with a plan property, you've manually created the long tail the folding mechanism exists to protect against. Once it folds, you can no longer tell how many of each happened, only that _other happened some number of times. The same applies to anything unbounded: a user id, an email, an order id, a timestamp baked into the name.

Put the variable in a property instead

Every event carries up to 8 properties, each with a 64-character key and a 256-character value, enforced identically on the client and again on the server so a tampered payload can't smuggle more through. Keys are restricted to letters, numbers, _, ., : and -: anything else is silently dropped, not rejected, so a typo'd key just disappears rather than erroring your call.

So plan_upgraded with { plan: "business", billing_period: "annual" } is one bounded event name with two properties you can break a funnel or a chart down by, which is exactly what the three-name version couldn't offer without extra work.

Good and bad

Instead ofProblemDo this
plan_upgraded_pro, plan_upgraded_businessValue baked into the name; folds into _other once cardinality growsplan_upgraded with { plan: "pro" }
click_button_hero_cta_v2Re-encodes the element into the event name, and drifts every time the button copy changesUse data-mrkr-event="cta_click" with data-mrkr-prop-* and keep the detail in properties
user_42981_purchasedUnbounded value in the name; one row per user, foreverpurchase_completed with the user identified by session, not the event name
SignupComplete, signup-complete, signup_completeThree names for one thing, split across every reportPick one: signup_completed, and use it everywhere

Where the name comes from matters too

If you're using the declarative data-mrkr-event attribute instead of calling track() directly, the name is whatever you put in the attribute, capped at 64 characters, the same limit track() enforces. See the JavaScript API reference for the exact signature and what mrkr records automatically for what's already tracked without any naming decision on your part.

For the full property-sanitization rules see custom events. Your own events are never billed (only pageviews are), so name them for clarity rather than for cost: see what counts toward your quota.