There are problems with this design. Don't use it in prod
- We should have a naming grammar which uses adjectives end note
- 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)
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.
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.
app:launchedapp:launched.firstexperiment:started(assigned an A/B variant)intro:viewedintro:finishedaccount:createdsigned_in.successsigned_in.failuresigned_outlesson:completedlesson:uncompletedlesson:watcheduser.email:changedflashcard_answers:resetflashcard_answers:restoredapp.playback_rate:changed
- 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:resetinstead offlashcard_answers:reset) - What else?