Naming Conventions
Standards for naming events, properties, and identifiers.
Consistent naming is the foundation of queryable, readable, and maintainable analytics. Without a naming strategy, the same action ends up tracked under multiple names, data fragments across dashboards, and nobody trusts the numbers.
The cost of fixing naming after the fact is enormous. You either migrate historical data (expensive, error-prone) or live with a permanent seam in your analytics. Get this right from the start.
Event names
The Accoil format: Object_Action
Accoil uses Title_Case with underscores for event names. The object comes first, followed by a past-tense verb, separated by underscores.
Report_Created
User_Invited
Search_Performed
Integration_ConnectedThis format:
- Groups related events when sorted alphabetically (all
Report_*events cluster together) - Reads naturally and is immediately understandable
- Works cleanly in all databases and APIs without quoting issues
Core naming rules
Every event name must follow these rules:
| Rule | Explanation |
|---|---|
| Object first | Name the thing that was acted upon. This groups related events in sorted lists. |
| Past-tense verb | The event describes something that already happened. Events are facts, not intentions. |
| Outcomes, not mechanisms | Track what the user accomplished, not how they accomplished it. |
| Title_Case with underscores | Capitalize each word, separate with underscores. |
Multi-word objects
When the object or action is more than one word, keep the same pattern:
Advanced_Search_Performed
Bulk_Export_Generated
Setup_Wizard_Completed
User_Role_ChangedMulti-word objects are fine and often necessary. Clarity beats brevity. Do not abbreviate objects to avoid multi-word names.
Singular vs plural
Use singular for individual actions. Use plural only for genuine bulk operations:
Report_Exported -- one report was exported
Reports_Bulk_Deleted -- batch operation on many reports
Todo_Created -- one todo was created
Todos_Cleared -- all todos were removed at onceDo / Don't examples
| Do | Don't | Why |
|---|---|---|
Report_Created | Create_Report_Button_Clicked | Track the outcome, not the mechanism |
Search_Performed | user_searched_something | Use the standard format, not ad-hoc naming |
Plan_Upgraded | Performing_Upgrade | Past tense, not present or future |
Integration_Connected | app.integration.connected | Use Accoil's Title_Case format |
Report_Created | Created_Report | Object first, verb second |
Export_Generated | EXPORT_GENERATED | Title_Case, not ALL_CAPS |
Action vocabulary
Use past tense. The event already happened.
| Action | Meaning | Notes |
|---|---|---|
Created | New thing made | |
Updated | Existing thing modified | |
Deleted | Thing removed | |
Viewed | Thing displayed to user | Use sparingly -- see below |
Started | Process began | |
Completed | Process finished | |
Failed | Process errored | |
Abandoned | Process left incomplete | Useful for workflows and wizards |
Sent | Message or notification dispatched | |
Connected | Integration or service linked | |
Disconnected | Integration or service unlinked | |
Configured | Settings or setup established | |
Invited | User invited someone | |
Joined | User accepted invite | |
Upgraded | Plan or tier increased | |
Downgraded | Plan or tier decreased | |
Generated | Output produced (reports, exports) | |
Applied | Filter, template, or rule put into effect | |
Performed | Action executed (search, sync) |
A note on Viewed and Clicked: These describe UI mechanics, not user intent. Prefer tracking the meaningful outcome. If you must track navigation, keep it sparse -- key pages only, not every screen. See Cost Optimization for why page views are almost never worth tracking.
Accoil track calls: event name only
No properties on track
Accoil's track call accepts only the event name. There are no event properties. This is by design -- it forces cleaner event taxonomy and pushes contextual data to user and account traits where it belongs.
Because track calls carry no properties, event naming carries more weight in Accoil than in other platforms. The event name alone must communicate what happened. Use identify and group traits to provide the context that other platforms carry as event properties.
When to create a new event vs use traits
Since Accoil events have no properties, the question of "new event vs property" becomes "new event vs trait":
Use separate events for fundamentally different actions:
Report_Created
Report_Shared
Report_Exported
Report_ArchivedUse traits (via identify or group) for contextual metadata:
// Set via group() call -- not on the event
group("acc_456", { primary_report_type: "standard" })
// Then track the action
track("Report_Created")The test: Can you write a single sentence that describes all variants? "A report was created" covers standard, custom, and template reports -- so use one event and let traits provide context. But "a report was created" and "a report was shared" are fundamentally different actions -- so use separate events.
Property and trait naming
Format: snake_case
Always use snake_case for property and trait names, regardless of event naming convention. This applies to all traits sent via identify and group calls.
{
report_type: "standard",
created_by: "usr_456",
is_template: false,
employee_count: 150
}Consistent suffixes
Use consistent suffixes so properties are self-describing:
| Pattern | Type | Examples | Purpose |
|---|---|---|---|
*_id | String (prefixed) | report_id, task_id | Entity references |
*_type | Enum string | report_type: "standard" | Categorization |
*_count | Integer | recipient_count: 3 | Quantities |
is_* | Boolean | is_template: true | State flags |
has_* | Boolean | has_description: true | Presence flags |
*_at | ISO 8601 timestamp | created_at, expires_at | Points in time |
*_source | Enum string | signup_source: "google_oauth" | Origin and attribution |
*_format | Enum string | export_format: "pdf" | Output format |
When someone sees recipient_count they immediately know it is an integer. When they see is_template they know it is a boolean. Consistent suffixes eliminate guesswork in every query.
The same trait must always mean the same thing
If report_id appears on user traits and account traits, it must reference the same entity in the same format. Never reuse a trait name with a different meaning. This sounds obvious, but it drifts over time as different developers add traits independently.
ID format conventions
Use prefixed IDs so they are self-documenting in logs and queries:
| Entity | Prefix | Example |
|---|---|---|
| User | usr_ | usr_abc123 |
| Account | acc_ | acc_def456 |
| Report | rpt_ | rpt_ghi789 |
| Task | tsk_ | tsk_jkl012 |
| Team | tem_ | tem_mno345 |
| Session | ses_ | ses_pqr678 |
| Workspace | ws_ | ws_abc123 |
| Project | proj_ | proj_def456 |
When you see usr_abc123 in a raw event, you know instantly it is a user ID without checking the property name. This matters when debugging, reviewing logs, and joining data across systems.
Event naming checklist
Before adding a new event, verify:
- Follows the
Object_Actionformat with Title_Case underscores - Uses past tense verb (describes what happened, not what will happen)
- Object comes first, verb comes last
- Describes the outcome, not the UI mechanism
- No redundant prefixes (e.g., "Event_", "Track_", "App_")
- No implementation details (e.g., "Button1", "Div_Search")
- No PII in the event name
- Consistent with existing events for the same object
- Added to the centralized event definition file
- Would not be better served by an existing event