Skip to content

Instantly share code, notes, and snippets.

@zmillman
Last active July 15, 2021 22:17
Show Gist options
  • Save zmillman/1e9dfebbe1220dc35e7b to your computer and use it in GitHub Desktop.
Save zmillman/1e9dfebbe1220dc35e7b to your computer and use it in GitHub Desktop.
Event naming guidelines/styleguide

There are problems with this design. Don't use it in prod

  • We should have a naming grammar which uses adjectives end note

Event table columns:

  • id (primary key) - unique event id
  • name (string) - event name
  • user_id (int) - identifies the actor responsible for triggering the event
  • distinct_id (string) - uuid from device or session token
  • target_type (string)
  • target_id (int)
  • app_id (string) - name of the application running the code
  • app_version (string) - deployed application code version creating the event
  • ip_address (string) - IP of host creating the event
  • platform (string) - one of "web", "ios", "android"
  • meta (JSON hash) - misc. attributes necessary for logging and auditing the event (e.g. error messages for login failure)
  • created_at (datetime)

name:

Format: <noun phrase>:<verb phrase> or <verb phrase>

Each phrase consists of words in underscore case joined by periods. This keeps names consistent and preserves word distinctions for case-insensitive SQL
good: signed_in.success, signed_out
bad: signed in success, SignedOut

Nouns are always before the verb. (string prefix indexes will be more performant grouping actions on similar objects, instead of actions)
good: app:launched, lesson:completed
bad: launched:app, completed:lesson

Noun phrases begin with the object, followed by an optional keypath to a specific attribute. This groups events on similar entities for SQL's string prefix indexes
good: user.email:changed
bad: user:email_changed, email:changed

Every event has exactly one word which is a verb. Each record should represent exactly one event
good: app:launched, account:created
bad: app, account:created.signed_in

Verb phrases consist of exactly one word which is a verb, followed by an optional modifier.
good: account:created, signed_in.success
bad: account:created.signed_in, signed_in_success

Modifiers indicate notable categories of the event, like success or the first occurrence. This groups similar events together for better performance with SQL string prefix indexes
good: account:created.success, app:launched.first
bad: account:failure.created, app:launched.once

Verbs must be in past tense. Events represent an event which has just happened (i.e. in the past)
good: app:launched
bad: app:launch

Events which revert a previous event should be named with a new verb.
good: answers:reset, answers:restored
bad: answers:reset answer:reset.undo

For Mixpanel, the name is the noun phrase and verb converted to title case to follow their naming conventions. (e.g. lesson:watched => "Lesson Watched"). The modifier should be sent as a value in the properties hash.

Zach's quick and dirty linguistic theory

Events represent sentences in the past tense of a subject-object-verb language where the subject is indicated by user_id/distinct_id and the object and verb as segments in name.

The object in name is indefinite (e.g. video:watched means "watched a video"), unless there's a target to make the object definite (e.g. "watched the video with id of 74").

Modifiers are adverbs (e.g. .success means "successfully") which modify whichever verb they follow.

Timing of the event is established by created_at, location of the event with ip_address, and originating application by app_id/app_version/platform.

This should cover who, what, when, where, and how. It's up to our analysis to figure out the why.

Example event names

  • app:launched
  • app:launched.first
  • experiment:started (assigned an A/B variant)
  • intro:viewed
  • intro:finished
  • account:created
  • signed_in.success
  • signed_in.failure
  • signed_out
  • lesson:completed
  • lesson:uncompleted
  • lesson:watched
  • user.email:changed
  • flashcard_answers:reset
  • flashcard_answers:restored
  • app.playback_rate:changed

Open questions:

  • Are there other dimensions (e.g. "count") or attributes we should be tracking in their own columns?
  • Is there a more readable phrase separator than colons?
  • Should nouns allow namespacing? (e.g. flashcard/answers:reset instead of flashcard_answers:reset)
  • What else?
@zackm
Copy link

zackm commented Mar 11, 2015

  • I can't think of any other column's that I'd add
  • I'm not sure about the noun segments point. I could see the argument both ways but I'd probably prefer to not allow namespacing
  • I prefer undoing as "lesson.uncompleted"

@zmillman
Copy link
Author

Updated guidelines:

  • colons as phrase separators
  • noun phrases have optional keypaths
  • better verb phrase documentation

@ambirdsall
Copy link

My one issue is that the list of columns isn't accurate. We don't have distinct_id, app_id or app_version columns, and our properties is actually called extras. Seems like we should change either this or the table; or make it clear that the schema is aspirational.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment