Analytics Event Naming Conventions: The Definitive Guide
The complete reference for analytics event naming: patterns, casing, tense, granularity, cross-platform examples, and a decision framework for choosing the right convention.
Ask five engineers how they'd name an analytics event for a user adding an item to a cart. You'll get five different answers: AddToCart, add_to_cart, cart_item_added, CartAdd, ecommerce.cart.add. They're all reasonable. They're all incompatible.
When there's no agreed convention, naming decisions get made in the moment - by whoever is writing the ticket, the engineer implementing it, or the analyst querying the data weeks later. The result is an event registry that nobody fully trusts.
This guide covers the patterns that actually hold up across platforms, team sizes, and time. Not rules for the sake of rules - conventions that make your tracking plan a reliable source of truth instead of an archaeology project.
- Why naming conventions matter more than you think
- The core decision: what naming pattern to use
- Naming pattern comparison
- The same event across platforms
- Choosing a naming pattern: decision framework
- Casing: snake_case vs. Title Case vs. camelCase
- Tense: past tense wins
- Granularity: how specific should event names be?
- Properties: the other half of the naming problem
- Common mistakes and how to avoid them
- Locking conventions in with a tracking plan
- A naming convention checklist
- Frequently asked questions
- Getting your team aligned
Why naming conventions matter more than you think
Analytics event names aren't just labels. They become the raw material for every dashboard, funnel analysis, A/B test, and ML feature your team builds. Once an event name ships to production, changing it means breaking historical data or running two event names in parallel - neither of which is pleasant.
Bad naming compounds silently. A single ButtonClicked event on a product with 50 button types forces every analyst to write the same filter logic repeatedly. Inconsistent casing between platforms (iOS sends PurchaseComplete, Android sends purchase_complete) fragments cohort data. Ambiguous past vs. present tense ("clicked" vs. "click") creates subtle disagreements about when events fire.
Good naming is cheap to get right the first time. It's expensive to fix later.
The core decision: what naming pattern to use
Most teams land on one of three patterns. Here's what each looks like in practice:
Object-action (recommended)
Structure: [Object] [Action] - the thing, then what happened to it.
Cart Item AddedSubscription CancelledReport ExportedOnboarding Step CompletedAPI Key Created
This pattern reads naturally in English, sorts objects together in alphabetical event lists, and makes the subject of each event unambiguous. It's the pattern used by Segment, Amplitude's documentation examples, and most mature analytics teams.
Action-object
Structure: [Action] [Object] - verb first.
Added Cart ItemCancelled SubscriptionExported Report
Some teams prefer this because it mimics natural English commands. The downside: event lists sorted alphabetically group all "Added" events together, then all "Cancelled" events - making it harder to find everything related to a specific object like Cart or Subscription.
Namespace-prefixed
Structure: [namespace].[object].[action] or [namespace]_[object]_[action].
checkout.cart.item_addedbilling.subscription.cancelledplatform.api_key.created
Useful for large products with distinct domains or multiple teams contributing events. The namespace prevents collisions and makes events self-documenting. The tradeoff is verbosity - names get long, and the period separator can cause issues in some query tools.
Pick one pattern and document it. Which pattern matters less than consistency. A team using action-object everywhere is in far better shape than a team where half the events are object-action and the other half are namespaced.
Naming pattern comparison
Each naming pattern has distinct strengths depending on your team size, tooling, and how you browse event data. Here is how the three patterns compare across the dimensions that matter most.
Object-Action
Example: Cart Item Added
- Readability in dashboards: High. Title Case with spaces reads naturally and requires no mental parsing. Analysts can scan event lists quickly.
- Alphabetical sort behavior: Groups events by object. All Cart events, all Subscription events, and all Report events appear together. This is usually what you want when browsing an event list.
- Cross-team scalability: Good for small to mid-size teams. Can break down at scale if two teams define overlapping objects without coordination.
- Tooling compatibility: Excellent. Works natively with Segment, Amplitude, Mixpanel, and most BI tools. No escaping or quoting needed.
- Recommended for: Most teams. Startups, single-product companies, and teams under 50 engineers. The best default if you have no strong reason to choose otherwise.
Action-Object
Example: Added Cart Item
- Readability in dashboards: Moderate. Reads like natural English commands, but the verb-first structure can feel repetitive when scanning long lists.
- Alphabetical sort behavior: Groups events by action. All "Added" events cluster together, all "Cancelled" events cluster together. This makes it harder to find all events related to a single feature or object.
- Cross-team scalability: Similar to Object-Action. No inherent advantage or disadvantage for multi-team setups.
- Tooling compatibility: Equivalent to Object-Action. No special handling required.
- Recommended for: Teams that already use this pattern consistently and have no reason to migrate. Not recommended for new tracking plans.
Namespace-Prefixed
Example: checkout.cart.item_added
- Readability in dashboards: Lower. Dot-separated or underscore-heavy names require more effort to read at a glance. Less natural for non-technical stakeholders.
- Alphabetical sort behavior: Groups events by domain namespace first, then by object. This is ideal when multiple teams own distinct areas of the product.
- Cross-team scalability: Strongest option. Namespaces act as ownership boundaries. The billing team's events never collide with the checkout team's events, even if both have an "item" object.
- Tooling compatibility: Mixed. Periods can cause issues in SQL column references and some analytics tools that treat dots as path separators. Test with your stack before committing.
- Recommended for: Large organizations with 50+ engineers, multiple product areas, or platform teams that need strict event ownership boundaries.
The same event across platforms
Cross-platform consistency is the most common place naming conventions break down. The same event should use the same name regardless of which platform fires it. Here is how "Cart Item Added" looks when implemented across four languages.
TypeScript
analytics.track("Cart Item Added", { item_id: "sku_123", quantity: 1, price: 29.99 });
Swift
Analytics.track("Cart Item Added", properties: ["item_id": "sku_123", "quantity": 1, "price": 29.99])
Kotlin
Analytics.track("Cart Item Added", mapOf("item_id" to "sku_123", "quantity" to 1, "price" to 29.99))
Python
analytics.track("Cart Item Added", {"item_id": "sku_123", "quantity": 1, "price": 29.99})
Notice that the event name string is identical in every language. The only differences are syntax. This is exactly how it should work, but in practice teams drift because each platform's engineer types the name from memory or a ticket description.
Code generation eliminates this problem entirely. When event names and properties are defined once in a tracking plan and generated into typed SDK methods for each platform, there is no room for a typo or casing mismatch. The generated function enforces the correct name at compile time.
Choosing a naming pattern: decision framework
The right pattern depends on three factors: whether you have existing events, how many teams contribute to your tracking plan, and which analytics tools you use. Walk through these questions in order.
Are you starting from scratch or migrating existing events?
Starting fresh: Use Object-Action with Title Case. It is the most readable pattern, sorts well in every analytics tool, and has the widest adoption across the industry.
Migrating: If your existing pattern is consistent, keep it. Switching patterns means either breaking historical data or maintaining a mapping layer. If your existing events are inconsistent, adopt Object-Action for all new events and backfill old ones opportunistically when you touch the code that fires them.
How many teams contribute events?
One team: Object-Action is sufficient. A single team can coordinate naming through code review and a shared tracking plan without needing formal ownership boundaries.
Multiple teams: Consider Namespace-Prefixed to prevent collisions. When the billing team and the checkout team both have a concept of "item," namespaces keep their events cleanly separated without requiring cross-team coordination on every new event.
What analytics tools do you use?
Segment, Amplitude, Mixpanel: Title Case Object-Action works best. These tools display event names directly in their UI, so human readability matters. Their documentation and templates also use this format.
Custom data pipelines: snake_case may be more compatible. If events flow directly into a data warehouse where analysts write SQL, snake_case avoids quoting issues and aligns with column naming conventions.
Casing: snake_case vs. Title Case vs. camelCase
This is the most common source of cross-platform fragmentation. iOS developers tend toward PascalCase. Backend engineers tend toward snake_case. JavaScript developers are split between camelCase and everything else.
The analytics industry has largely converged on two options:
- Title Case with spaces -
Cart Item Added. Most human-readable in dashboards, works well with Amplitude, Mixpanel, and most BI tools that display event names directly to analysts. - snake_case -
cart_item_added. Preferred by engineers, easier to write as a constant in code, no ambiguity about word boundaries.
Whatever you choose, enforce it for every platform. The worst outcome is iOS using CartItemAdded and Android using cart_item_added - they won't be recognized as the same event unless your pipeline normalizes them, and even then you've introduced a hidden transformation layer that future teammates don't know exists.
If you're building a new tracking plan from scratch, Title Case with spaces is the better default. It's the most readable in the tools where analysts actually spend time.
Tense: past tense wins
Use past tense for events. An event records something that happened - it fires after the action is complete. So: Subscription Cancelled not Cancel Subscription, Form Submitted not Submit Form.
Present tense and imperative forms ("Click", "Submit", "Cancel") can imply intent rather than completion, which is ambiguous. Did the event fire when the user clicked, or when the server confirmed the action? Past tense removes that ambiguity.
The exception: screen and page views. These are usually named in the present: Home Screen Viewed, Pricing Page Viewed. "Viewed" is past tense but the subject is the page itself - this is consistent with how Segment and Amplitude document screen events.
Granularity: how specific should event names be?
This is where most teams make a mistake in one of two directions.
Too generic: Button Clicked, Link Tapped, Action Taken. These tell you nothing without filtering on a property. Your analysts will write WHERE button_name = 'Add to Cart' in every query, which means the event name itself is doing no useful work.
Too specific: Red Add to Cart Button Clicked on Mobile Homepage Hero Section. This encodes implementation details into the event name. When the button color changes or it moves to a different section, the event name becomes a lie.
The right level of specificity is the action, not its visual implementation. Cart Item Added is correct. The context (where, from which surface) belongs in properties: source: "homepage_hero", platform: "mobile". The name captures what happened; properties capture the context.
Properties: the other half of the naming problem
Events have names; events also have properties. The same conventions apply - and the same inconsistencies cause the same problems.
Standard conventions for properties:
- Use snake_case for property keys:
user_id,plan_type,item_count. This is the near-universal standard in data pipelines, SQL, and analytics tools. - Use consistent value formats. If
plan_typecan be"free","pro", or"enterprise"- document the allowed values. Don't let iOS send"Free"while Android sends"free". - Use boolean properties rather than string flags.
is_trial: truenottrial_status: "active". - Use ISO 8601 for timestamps in properties.
started_at: "2026-03-24T10:30:00Z"notstart_time: "March 24". - Use IDs not display names for references.
workspace_id: "ws_abc123"is stable;workspace_name: "Acme Corp"changes.
Common mistakes and how to avoid them
Abbreviations
Avoid them. usr_reg_cmplt saves nothing; it costs every future analyst who encounters it. Write out the words: User Registration Completed.
Encoding the platform in the name
Don't do iOS Cart Item Added or Web Subscription Cancelled. Platform belongs in a property: platform: "ios". Events that encode the platform can't be used for cross-platform funnels without union queries.
Duplicates with different names
Purchase Completed and Order Placed are the same event with two names. This happens when two teams instrument the same action independently. A central tracking plan prevents it; a spreadsheet doesn't.
Vague actions
User Interacted, Feature Used, Action Occurred. These events exist because someone wanted to track "engagement" without deciding what that means. They generate high event volume and zero signal. Name the specific interaction.
Locking conventions in with a tracking plan
Conventions documented in a wiki page or Notion doc have a half-life of a few months. New engineers don't read them. Contractors don't know they exist. The tracking plan drifts.
The more durable approach is to make the convention machine-readable: a centralized tracking plan registry where every event is defined with a name, tense, casing, and required properties - and where new events are reviewed before they ship. Code generation takes this further by removing the manual step entirely. If the event name in the registry is Cart Item Added, the generated SDK method is trackCartItemAdded() - not whatever the next engineer felt like typing.
That's the difference between a convention and an enforced standard. Conventions require discipline. Enforced standards require a tool.
A naming convention checklist
Before you ship an event, run it through this:
- Does the name follow the agreed pattern (object-action, action-object, or namespaced)?
- Is the casing consistent with every other event in the registry?
- Is the verb in past tense?
- Is the name free of platform, device, or visual implementation details?
- Does a similar event already exist with a different name?
- Are all property keys in snake_case?
- Are enum property values documented and lowercase?
- Are all required properties present?
Eight questions. They take under a minute. They prevent years of technical debt.
Frequently asked questions
Should analytics event names use snake_case or Title Case?
Title Case with spaces is the better default for most teams because it is the most readable format in analytics dashboards where non-technical stakeholders browse event data. Use snake_case only if your events flow directly into SQL-based pipelines where quoting spaces would add friction.
Should analytics events use past tense or present tense?
Use past tense. An analytics event records something that already happened, so Cart Item Added is correct and Add Cart Item is not. Past tense removes ambiguity about whether the event fires on intent or on completion.
How do I name analytics events consistently across iOS, Android, and web?
Define every event name in a single source of truth, such as a tracking plan registry, and enforce it across platforms. The event name string must be identical regardless of language or framework. Code generation is the most reliable way to guarantee this because the generated SDK functions carry the exact name from the registry into each codebase.
What is the object-action naming pattern for analytics events?
Object-action means structuring event names as the noun first, then the verb: Cart Item Added, Subscription Cancelled, Report Exported. This pattern groups related events together in alphabetical lists and reads naturally in dashboards. It is the format recommended by Segment and used by most mature analytics teams.
How do I prevent duplicate event names in my tracking plan?
Use a centralized tracking plan registry where every event must be defined before it ships. Without a single source of truth, two teams will inevitably name the same action differently. Code review alone is not enough because reviewers rarely have the full event inventory memorized.
Should I include the platform name in the event name?
No. Platform belongs in a property (platform: "ios"), never in the event name. Encoding the platform into the name means you cannot run cross-platform funnels without writing union queries. Keep event names platform-agnostic and let properties carry the context.
Getting your team aligned
The hardest part of naming conventions isn't deciding on a standard. It's getting twelve engineers across three time zones to follow it consistently in a fast-moving codebase.
The practical path: start with your next sprint, not a retroactive cleanup. Define the convention, add it to the definition of done for any ticket that touches analytics, and use code review to catch deviations. Once the new events are clean, backfill the old ones opportunistically when you touch them anyway.
If you're ready to move beyond conventions-on-paper, Ordaze gives you a structured tracking plan registry where every event is versioned, every property is typed, and generated code enforces the naming standard at compile time. The codebase scanner can show exactly which events are implemented correctly and which are drifting.
Try Ordaze free - no credit card required.
Keep reading
Ready to bring structure to your analytics events?
Try Ordaze free