Gaming Event Spec

This page defines all standard gaming events for Datafly Signal — covering web, mobile, and desktop games. The events span the full player lifecycle: discovery and acquisition, sessions, progression, in-game economy, social play, and retention. Implement these events to enable accurate server-side delivery to advertising and analytics platforms.

💡

Gaming events use snake_case identifiers following the noun_past convention (game_started, level_completed, achievement_unlocked). These are Signal’s canonical event names, taken from the live gaming blueprints. Where GA4 has a native gaming equivalent (e.g. level_start, earn_virtual_currency), Signal’s blueprints map to it automatically — see the Vendor Mapping table. Cross-vertical events (search, sign_up, login, generate_lead, view_promotion, select_promotion, ad_impression) use their canonical names.

All events are sent via datafly.track(). Properties are passed as a flat object in the second argument. Use stable identifiers for game_id, level_id, item_id, and achievement_id — these are used as join keys in your data warehouse, so avoid changing them once live. Never put raw PII (email, phone, name) in track() properties.


Acquisition Events

Events tracking how players discover, evaluate, and sign up for the game.

view_promotion

Fired when a promotional banner, featured-game tile, or store creative is visible to the player.

datafly.track('view_promotion', {
  promotion_id: 'LAUNCH_S3',
  promotion_name: 'Season 3 Launch',
  creative_name: 'season3-hero-v2.mp4',
  creative_slot: 'store-featured'
})
PropertyTypeRequiredDescription
promotion_idstringOptionalIdentifier for the promotion
promotion_namestringOptionalHuman-readable name of the promotion
creative_namestringOptionalName or URL of the creative asset shown
creative_slotstringOptionalSlot or placement where the promotion appeared

select_promotion

Fired when a player clicks a promotional banner, featured tile, or store creative.

datafly.track('select_promotion', {
  promotion_id: 'LAUNCH_S3',
  promotion_name: 'Season 3 Launch',
  creative_name: 'season3-hero-v2.mp4',
  creative_slot: 'store-featured'
})
PropertyTypeRequiredDescription
promotion_idstringOptionalIdentifier for the promotion
promotion_namestringOptionalHuman-readable name of the promotion
creative_namestringOptionalName or URL of the creative asset shown
creative_slotstringOptionalSlot or placement where the promotion appeared

Fired when a player submits a search query (for games, items, players, or guides).

datafly.track('search', {
  search_term: 'battle royale co-op'
})
PropertyTypeRequiredDescription
search_termstringRequiredThe search term entered by the player

generate_lead

Fired when a prospective player submits interest before a full account exists — e.g. a beta waitlist, pre-registration, or newsletter opt-in. Never pass raw email or phone here; the contact PII is hashed server-side via Signal’s identity blueprint.

datafly.track('generate_lead', {
  lead_type: 'pre_registration',
  game_id: 'dungeon_quest',
  value: 0,
  currency: 'GBP'
})
PropertyTypeRequiredDescription
lead_typestringOptionalKind of lead (e.g. pre_registration, beta_waitlist, newsletter)
game_idstringOptionalIdentifier for the game the lead relates to
valuenumberOptionalEstimated monetary value of the lead
currencystringOptionalISO 4217 currency code

sign_up

Fired when a player completes account registration.

datafly.track('sign_up', {
  method: 'email'
})
PropertyTypeRequiredDescription
methodstringOptionalRegistration method (e.g. email, google, apple, steam, guest)

login

Fired when a player signs in to their account.

datafly.track('login', {
  method: 'steam'
})
PropertyTypeRequiredDescription
methodstringOptionalLogin method (e.g. email, google, apple, steam)

Session Events

Events tracking game sessions from launch to close.

game_started

Fired when a player has launched the game and begun a session.

datafly.track('game_started', {
  game_id: 'dungeon_quest',
  game_version: '2.4.1',
  platform: 'mobile',
  mode: 'single_player'
})
PropertyTypeRequiredDescription
game_idstringOptionalIdentifier for the game or game mode
game_versionstringOptionalApplication or build version (e.g. 2.4.1)
platformstringOptionalPlatform: web, mobile, desktop, console
modestringOptionalPlay mode: single_player, multiplayer, co_op

game_ended

Fired when a player’s session has ended.

datafly.track('game_ended', {
  game_id: 'dungeon_quest',
  session_duration_seconds: 1842,
  reason: 'quit'
})
PropertyTypeRequiredDescription
game_idstringOptionalIdentifier for the game
session_duration_secondsnumberOptionalTotal session length in seconds
reasonstringOptionalHow the session ended: completed, quit, disconnect

Progression Events

Events tracking player advancement through levels, tutorials, and achievements.

tutorial_started

Fired when a player has entered a tutorial sequence.

datafly.track('tutorial_started', {
  tutorial_id: 'tut_basic_controls'
})
PropertyTypeRequiredDescription
tutorial_idstringOptionalIdentifier for the tutorial

tutorial_completed

Fired when a player has finished a tutorial sequence.

datafly.track('tutorial_completed', {
  tutorial_id: 'tut_basic_controls',
  duration_seconds: 95,
  skipped_steps: 0
})
PropertyTypeRequiredDescription
tutorial_idstringOptionalIdentifier for the tutorial
duration_secondsnumberOptionalTime taken to complete the tutorial
skipped_stepsnumberOptionalNumber of steps the player skipped

tutorial_skipped

Fired when a player has opted to skip a tutorial.

datafly.track('tutorial_skipped', {
  tutorial_id: 'tut_advanced_crafting',
  at_step: 3
})
PropertyTypeRequiredDescription
tutorial_idstringOptionalIdentifier for the tutorial
at_stepnumberOptionalStep number at which the player skipped (1-indexed)

level_started

Fired when a player has begun a level or stage.

datafly.track('level_started', {
  level_id: 'world_2_level_4',
  level_name: 'The Dark Cavern',
  attempt: 1
})
PropertyTypeRequiredDescription
level_idstringRequiredStable identifier for the level
level_namestringOptionalDisplay name (e.g. The Dark Cavern)
attemptnumberOptionalWhich attempt at this level this is (1 for first play, 2 for first retry, etc.)

level_completed

Fired when a player successfully finishes a level. For failures, send the dedicated level_failed event below.

datafly.track('level_completed', {
  level_id: 'world_2_level_4',
  level_name: 'The Dark Cavern',
  score: 48200,
  stars: 3,
  duration_seconds: 147,
  attempt: 2
})
PropertyTypeRequiredDescription
level_idstringRequiredStable identifier for the level
level_namestringOptionalDisplay name
scorenumberOptionalScore achieved
starsnumberOptionalStar rating earned (0–3)
duration_secondsnumberOptionalTime taken to finish the level
attemptnumberOptionalWhich attempt number this was

level_failed

Fired when a player has failed a level.

datafly.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'
})
PropertyTypeRequiredDescription
level_idstringRequiredStable identifier for the level
level_namestringOptionalDisplay name
scorenumberOptionalScore at point of failure
duration_secondsnumberOptionalTime played before failing
attemptnumberOptionalWhich attempt this failure was on
failure_reasonstringOptionalReason for failure (e.g. time_expired, no_lives, boss_defeated_player)

achievement_unlocked

Fired when a player has unlocked an achievement or badge.

datafly.track('achievement_unlocked', {
  achievement_id: 'ach_speed_runner',
  achievement_name: 'Speed Runner',
  achievement_type: 'speed',
  points: 50
})
PropertyTypeRequiredDescription
achievement_idstringRequiredStable achievement identifier
achievement_namestringOptionalDisplay name (e.g. Speed Runner)
achievement_typestringOptionalCategory (e.g. speed, completion, social, collection)
pointsnumberOptionalPoints awarded for the achievement

Economy Events

Events tracking real-money purchases, virtual-currency flows, and in-game item usage.

Distinguish real-money purchases (item_purchased) from virtual-currency transactions (currency_spent / currency_earned). This separation is essential for revenue reporting and App Store / Play Store reconciliation. Only item_purchased carries real revenue for ad-platform value optimisation.

item_purchased

Fired when a real-money (IAP or store) purchase of an item, bundle, or currency pack completes successfully. This is the most important monetisation event — ensure it fires reliably and carries a unique transaction_id for deduplication.

datafly.track('item_purchased', {
  transaction_id: 'IAP-10042',
  value: 9.99,
  currency: 'GBP',
  items: [
    {
      item_id: 'pack_gems_1200',
      item_name: '1,200 Gems Pack',
      item_category: 'currency_pack',
      price: 9.99,
      quantity: 1,
      currency: 'GBP'
    }
  ]
})
PropertyTypeRequiredDescription
transaction_idstringRequiredUnique purchase identifier — used for deduplication
valuenumberOptionalTotal real-money revenue
currencystringOptionalISO 4217 currency code
itemsarrayOptionalItems purchased (see Items Array Schema)
⚠️

Always send transaction_id on purchase events for deduplication. Platforms like Meta CAPI and GA4 use the transaction ID to prevent double-counting alongside client-side events.


currency_earned

Fired when a player receives virtual currency.

datafly.track('currency_earned', {
  virtual_currency_name: 'coins',
  value: 500,
  source: 'level_complete'
})
PropertyTypeRequiredDescription
virtual_currency_namestringRequiredName of the virtual currency (e.g. gems, coins, star_tokens)
valuenumberOptionalAmount earned
sourcestringOptionalHow the currency was earned: level_complete, daily_reward, achievement, purchase

currency_spent

Fired when a player spends virtual currency.

datafly.track('currency_spent', {
  virtual_currency_name: 'gems',
  value: 200,
  item_id: 'powerup_shield_x3',
  item_name: 'Shield Pack x3'
})
PropertyTypeRequiredDescription
virtual_currency_namestringRequiredName of the virtual currency
valuenumberOptionalAmount spent
item_idstringOptionalItem acquired with the currency
item_namestringOptionalDisplay name of the item acquired

item_equipped

Fired when a player equips an item to their character or loadout.

datafly.track('item_equipped', {
  item_id: 'skin_dragon_red',
  item_name: 'Red Dragon Skin',
  slot: 'character_skin'
})
PropertyTypeRequiredDescription
item_idstringRequiredIdentifier of the equipped item
item_namestringOptionalDisplay name
slotstringOptionalEquipment slot the item was placed in (e.g. helmet, primary_weapon, character_skin)

Social Events

Events tracking multiplayer activity, friend interactions, and community features.

friend_invited

Fired when a player sends a friend or referral invitation, or shares a clip, score, or achievement to a social channel.

datafly.track('friend_invited', {
  invitation_method: 'link_share',
  content_type: 'invite'
})
PropertyTypeRequiredDescription
invitation_methodstringOptionalHow the invitation was sent: in_game, link_share, sms, email, twitter, discord
content_typestringOptionalType of content shared, if any (e.g. invite, clip, score, achievement)

match_started

Fired when a multiplayer match has begun.

datafly.track('match_started', {
  match_id: 'match_9f3a2c1e',
  match_type: 'ranked',
  player_count: 10,
  game_mode: 'battle_royale'
})
PropertyTypeRequiredDescription
match_idstringOptionalUnique identifier for the match
match_typestringOptionalMatch type: ranked, casual, custom
player_countnumberOptionalTotal number of players in the match
game_modestringOptionalIn-game mode or map (e.g. capture_the_flag, battle_royale)

match_completed

Fired when a multiplayer match has ended.

datafly.track('match_completed', {
  match_id: 'match_9f3a2c1e',
  outcome: 'win',
  score: 2840,
  duration_seconds: 624,
  rank_change: 18
})
PropertyTypeRequiredDescription
match_idstringOptionalMatch identifier
outcomestringOptionalPlayer’s result: win, loss, draw
scorenumberOptionalFinal score for this player
duration_secondsnumberOptionalTotal match duration in seconds
rank_changenumberOptionalChange in ranking points as a result of the match (can be negative)

leaderboard_viewed

Fired when a player opens a leaderboard or posts a score to a scoreboard.

datafly.track('leaderboard_viewed', {
  leaderboard_id: 'ldr_season_3_ranked',
  scope: 'friends',
  score: 48200
})
PropertyTypeRequiredDescription
leaderboard_idstringOptionalIdentifier for the leaderboard
scopestringOptionalLeaderboard scope: global, friends, regional
scorenumberOptionalThe player’s score being posted or viewed, if applicable

Retention & Monetisation Events

Events tracking returning players, ad engagement, and re-engagement.

ad_impression

Fired when an in-game ad (rewarded, interstitial, or banner) is shown to the player.

datafly.track('ad_impression', {
  ad_platform: 'admob',
  ad_format: 'rewarded',
  ad_unit_name: 'extra_life_reward',
  value: 0.012,
  currency: 'USD'
})
PropertyTypeRequiredDescription
ad_platformstringOptionalMediation or ad network (e.g. admob, applovin, unity_ads)
ad_formatstringOptionalAd format: rewarded, interstitial, banner
ad_unit_namestringOptionalName of the ad placement
valuenumberOptionalEstimated ad revenue for the impression
currencystringOptionalISO 4217 currency code

Items Array Schema

💡

Store and economy events accept an items array. Each object in the array can include the following properties. The items[] array uses GA4-style field names. Signal’s server-side blueprints automatically transform these to vendor-specific formats (e.g., Meta’s contents[] with id/title fields).

PropertyTypeDescription
item_idstringYour internal item or SKU identifier
item_namestringItem display name
item_categorystringItem category (e.g. skin, currency_pack, loot_box, powerup)
item_brandstringBrand or franchise name
item_variantstringSelected variant (e.g. Legendary, Gold)
pricenumberUnit price
quantitynumberNumber of units
indexnumberPosition in list (0-indexed, relevant in list/search contexts)
currencystringISO 4217 currency code
discountnumberMonetary discount applied to this item

Vendor Mapping

The table below shows how Datafly Signal maps gaming events to the native event names expected by each vendor’s server-side API. Signal uses its own established snake_case event names as the canonical format (left column), and blueprints handle the transformation to vendor-specific payloads. Where GA4 has a native gaming event, that native name appears in the GA4 column; Signal’s event name does not change.

Signal EventGA4Meta CAPITikTok Events API
view_promotionview_promotion(custom)(custom)
select_promotionselect_promotion(custom)(custom)
searchsearchSearchSearch
generate_leadgenerate_leadLeadSubmitForm
sign_upsign_upCompleteRegistrationCompleteRegistration
loginlogin(custom)(custom)
game_started(custom)(custom)(custom)
game_ended(custom)(custom)(custom)
tutorial_startedtutorial_begin(custom)(custom)
tutorial_completedtutorial_complete(custom)(custom)
tutorial_skipped(custom)(custom)(custom)
level_startedlevel_start(custom)(custom)
level_completedlevel_end(custom)(custom)
level_failed(custom)(custom)(custom)
achievement_unlockedunlock_achievementAchievementUnlockedUnlockAchievement
item_purchasedpurchasePurchaseCompletePayment
currency_earnedearn_virtual_currency(custom)(custom)
currency_spentspend_virtual_currencySpendCreditsSpendCredits
item_equipped(custom)(custom)(custom)
friend_invitedshare(custom)(custom)
match_started(custom)(custom)(custom)
match_completed(custom)(custom)(custom)
leaderboard_viewedpost_score(custom)(custom)
ad_impressionad_impression(custom)(custom)