As applications scale from single-purpose tools to multi-module platforms, their analytics event registries inevitably suffer from entropy. Without strict governance, developers name events ad hoc based on immediate feature tickets, resulting in bloated event catalogs where no single engineer understands the full taxonomy.
A clean event taxonomy must be predictable, self-documenting, and strongly typed.
The Object-Action Syntax Standard
The most durable event taxonomy standard follows an explicit [Entity] [Action] or [Domain]_[Entity]_[Action] grammatical structure:
[Module] _ [Entity] _ [Action]
│ │ │
│ │ └─ Past tense verb (created, updated, clicked, completed)
│ └──────────── Concrete noun (report, invoice, filter_preset)
└──────────────────────── Functional domain (billing, workspace, telemetry)
Examples of Consistent vs. Problematic Naming:
| Problematic Ad-Hoc Names | Standardized Object-Action Format | Rationale |
|---|---|---|
btn_click_save | workspace_document_saved | Describes business entity and outcome, not UI element. |
user_did_checkout | billing_subscription_completed | Specifies functional domain and precise object state. |
search_new | catalog_search_executed | Clarifies that an actual search query was dispatched. |
modal_opened_3 | telemetry_export_dialog_viewed | Eliminates arbitrary numeric versioning from the event name. |
Global vs. Contextual Event Properties
Every event payload should be composed of two distinct layers:
Global Context Properties (Injected by Middleware):
client_app_version: Exact build identifier (e.g.2.14.0-rc3).session_id: Unique identifier spanning the user’s active session.operating_system: Platform and OS version.account_tier: Customer subscription or permission tier.timestamp_utc: ISO 8601 millisecond-precision UTC timestamp.
Event-Specific Payload Properties (Supplied at Call Site):
entity_id: Anonymized identifier of the modified object.interaction_source: Entry point (e.g.top_nav_shortcut,context_menu,command_palette).execution_duration_ms: Client-measured duration of the interaction.
Enforcing Schemas via TypeScript Interfaces
To prevent schema drift before code ever reaches production, define telemetry events as strongly-typed union types:
export interface DocumentExportEvent {
eventName: 'workspace_document_exported';
properties: {
documentId: string;
exportFormat: 'pdf' | 'csv' | 'json';
pageCount: number;
includeAnnotations: boolean;
durationMs: number;
};
}
By enforcing these types through linting and pre-commit hooks, engineering teams guarantee that every event dispatched by client code adheres to the centralized specification.