Gaming Event Spec
This page defines the recommended event taxonomy for gaming products — covering web, mobile, and desktop games. The events span the player lifecycle from session start through progression, in-game economy, and social play.
All event names use snake_case. Use stable identifiers for game_id, level_id, item_id, and achievement_id — these will be used as join keys in your data warehouse. Avoid changing them once live.
Session
Events tracking game sessions from launch to close.
game_started
A player has launched the game and begun a session.
| Property | Type | Required | Description |
|---|---|---|---|
game_id | string | No | Identifier for the game or game mode |
game_version | string | No | Application or build version (e.g. '2.4.1') |
platform | string | No | Platform: 'web', 'mobile', 'desktop' |
mode | string | No | Play mode: 'single_player', 'multiplayer', 'co_op' |
_df.track('game_started', {
game_id: 'dungeon_quest',
game_version: '2.4.1',
platform: 'mobile',
mode: 'single_player'
})game_ended
A player’s session has ended.
| Property | Type | Required | Description |
|---|---|---|---|
game_id | string | No | Identifier for the game |
session_duration_seconds | number | No | Total session length in seconds |
reason | string | No | How the session ended: 'completed', 'quit', 'disconnect' |
_df.track('game_ended', {
game_id: 'dungeon_quest',
session_duration_seconds: 1842,
reason: 'quit'
})Progression
Events tracking player advancement through levels, achievements, and tutorials.
level_started
A player has begun a level or stage.
| Property | Type | Required | Description |
|---|---|---|---|
level_id | string | Yes | Stable identifier for the level |
level_name | string | No | Display name (e.g. 'The Dark Cavern') |
attempt | number | No | Which attempt at this level this is (1 for first play, 2 for first retry, etc.) |
_df.track('level_started', {
level_id: 'world_2_level_4',
level_name: 'The Dark Cavern',
attempt: 1
})level_completed
A player has successfully completed a level.
| Property | Type | Required | Description |
|---|---|---|---|
level_id | string | Yes | Stable identifier for the level |
level_name | string | No | Display name |
score | number | No | Score achieved |
stars | number | No | Star rating earned (0–3) |
duration_seconds | number | No | Time taken to complete the level |
attempt | number | No | Which attempt number this completion was on |
_df.track('level_completed', {
level_id: 'world_2_level_4',
level_name: 'The Dark Cavern',
score: 48200,
stars: 3,
duration_seconds: 147,
attempt: 2
})level_failed
A player has failed a level.
| Property | Type | Required | Description |
|---|---|---|---|
level_id | string | Yes | Stable identifier for the level |
level_name | string | No | Display name |
score | number | No | Score at point of failure |
duration_seconds | number | No | Time played before failing |
attempt | number | No | Which attempt this failure was on |
failure_reason | string | No | Reason for failure (e.g. 'time_expired', 'no_lives', 'boss_defeated_player') |
_df.track('level_failed', {
level_id: 'world_2_level_4',
level_name: 'The Dark Cavern',
score: 12400,
duration_seconds: 63,
attempt: 1,
failure_reason: 'no_lives'
})achievement_unlocked
A player has unlocked an achievement or badge.
| Property | Type | Required | Description |
|---|---|---|---|
achievement_id | string | Yes | Stable achievement identifier |
achievement_name | string | No | Display name (e.g. 'Speed Runner') |
achievement_type | string | No | Category (e.g. 'speed', 'completion', 'social', 'collection') |
points | number | No | Points awarded for the achievement |
_df.track('achievement_unlocked', {
achievement_id: 'ach_speed_runner',
achievement_name: 'Speed Runner',
achievement_type: 'speed',
points: 50
})tutorial_started
A player has entered a tutorial sequence.
| Property | Type | Required | Description |
|---|---|---|---|
tutorial_id | string | No | Identifier for the tutorial |
_df.track('tutorial_started', {
tutorial_id: 'tut_basic_controls'
})tutorial_completed
A player has finished a tutorial sequence.
| Property | Type | Required | Description |
|---|---|---|---|
tutorial_id | string | No | Identifier for the tutorial |
duration_seconds | number | No | Time taken to complete the tutorial |
skipped_steps | number | No | Number of steps the player skipped |
_df.track('tutorial_completed', {
tutorial_id: 'tut_basic_controls',
duration_seconds: 95,
skipped_steps: 0
})tutorial_skipped
A player has opted to skip a tutorial.
| Property | Type | Required | Description |
|---|---|---|---|
tutorial_id | string | No | Identifier for the tutorial |
at_step | number | No | Step number at which the player skipped (1-indexed) |
_df.track('tutorial_skipped', {
tutorial_id: 'tut_advanced_crafting',
at_step: 3
})Economy
Events tracking in-game purchases, item usage, and virtual currency flows.
Distinguish between real-money purchases (purchase_type: 'iap') and virtual currency transactions (purchase_type: 'virtual'). This separation is important for revenue reporting and App Store / Play Store reconciliation.
item_purchased
A player has purchased an item, either with real money or virtual currency.
| Property | Type | Required | Description |
|---|---|---|---|
item_id | string | Yes | Stable identifier for the item |
item_name | string | No | Display name (e.g. 'Dragon Skin') |
item_type | string | No | Item category: 'weapon', 'skin', 'powerup', 'loot_box', 'currency_pack', or a custom value |
price | number | No | Price paid |
currency | string | No | ISO 4217 code for real-money purchases (e.g. 'GBP') or virtual currency name (e.g. 'gems') |
quantity | number | No | Quantity purchased |
purchase_type | string | No | 'iap' for real-money in-app purchase, 'virtual' for virtual currency spend |
_df.track('item_purchased', {
item_id: 'skin_dragon_red',
item_name: 'Red Dragon Skin',
item_type: 'skin',
price: 4.99,
currency: 'GBP',
quantity: 1,
purchase_type: 'iap'
})item_equipped
A player has equipped an item to their character or loadout.
| Property | Type | Required | Description |
|---|---|---|---|
item_id | string | Yes | Identifier of the equipped item |
item_name | string | No | Display name |
slot | string | No | Equipment slot the item was placed in (e.g. 'helmet', 'primary_weapon', 'character_skin') |
_df.track('item_equipped', {
item_id: 'skin_dragon_red',
item_name: 'Red Dragon Skin',
slot: 'character_skin'
})currency_earned
A player has received virtual currency.
| Property | Type | Required | Description |
|---|---|---|---|
currency_name | string | Yes | Name of the virtual currency (e.g. 'gems', 'coins', 'star_tokens') |
amount | number | No | Amount earned |
source | string | No | How the currency was earned: 'level_complete', 'daily_reward', 'achievement', 'purchase' |
_df.track('currency_earned', {
currency_name: 'coins',
amount: 500,
source: 'level_complete'
})currency_spent
A player has spent virtual currency.
| Property | Type | Required | Description |
|---|---|---|---|
currency_name | string | Yes | Name of the virtual currency |
amount | number | No | Amount spent |
item_id | string | No | Item purchased with the currency |
item_name | string | No | Display name of the item purchased |
_df.track('currency_spent', {
currency_name: 'gems',
amount: 200,
item_id: 'powerup_shield_x3',
item_name: 'Shield Pack x3'
})Social
Events tracking multiplayer activity, friend interactions, and community features.
friend_invited
A player has sent a friend invitation.
| Property | Type | Required | Description |
|---|---|---|---|
invitation_method | string | No | How the invitation was sent: 'in_game', 'link_share', 'sms', 'email' |
_df.track('friend_invited', {
invitation_method: 'link_share'
})match_started
A multiplayer match has begun.
| Property | Type | Required | Description |
|---|---|---|---|
match_id | string | No | Unique identifier for the match |
match_type | string | No | Match type: 'ranked', 'casual', 'custom' |
player_count | number | No | Total number of players in the match |
game_mode | string | No | In-game mode or map (e.g. 'capture_the_flag', 'battle_royale') |
_df.track('match_started', {
match_id: 'match_9f3a2c1e',
match_type: 'ranked',
player_count: 10,
game_mode: 'battle_royale'
})match_completed
A multiplayer match has ended.
| Property | Type | Required | Description |
|---|---|---|---|
match_id | string | No | Match identifier |
outcome | string | No | Player’s result: 'win', 'loss', 'draw' |
score | number | No | Final score for this player |
duration_seconds | number | No | Total match duration in seconds |
rank_change | number | No | Change in ranking points as a result of the match (can be negative) |
_df.track('match_completed', {
match_id: 'match_9f3a2c1e',
outcome: 'win',
score: 2840,
duration_seconds: 624,
rank_change: 18
})leaderboard_viewed
A player has opened a leaderboard.
| Property | Type | Required | Description |
|---|---|---|---|
leaderboard_id | string | No | Identifier for the leaderboard |
scope | string | No | Leaderboard scope: 'global', 'friends', 'regional' |
_df.track('leaderboard_viewed', {
leaderboard_id: 'ldr_season_3_ranked',
scope: 'friends'
})