Skip to content

Event Tracking Reference

Events are the core of Quest Data. Track player actions, game state, monetization, and performance. The SDK handles batching, offline caching, and retry logic automatically.

# Track a single event
QuestData.track("event_name", {
"property1": "value1",
"property2": 42,
"property3": true
})
# Events are queued immediately, sent in batches every 10s
# Or immediately when 10+ events queued
# Game started
QuestData.track("game_start", {
"version": "1.2.0",
"platform": OS.get_name(),
"language": TranslationServer.get_locale()
})
# Session ended (auto-tracked if app closes)
QuestData.track("game_end", {
"duration_seconds": 3600,
"total_revenue_session": 9.99
})
# Recommended: Use helper functions
QuestData.start_progression("level_5", "hard")
QuestData.complete_progression("level_5", 1000)
QuestData.fail_progression("level_5", "out_of_moves")
# Alternative: Raw events (no automatic duration)
QuestData.track("level_start", {
"level": 5,
"difficulty": "hard",
"attempt": 2
})
# Recommended: Use helper function
QuestData.track_purchase("starter_pack", 4.99, "USD", {
"transaction_id": "txn_abc123"
})
# Custom monetization events
QuestData.track("shop_opened", {
"section": "weapons",
"items_available": 12
})
# Recommended: Use helper function (auto stack trace + flight recorder)
QuestData.track_error("NullReference", "Player is null in _physics_process")
# Remote logging (different system — for debugging, not crash analytics)
QuestData.log_error("Memory pressure detected", {"free_mb": 45})

The SDK auto-tracks performance — no code required. Three lifecycle events feed the Performance dashboard:

EventWhenProperties
session_startSDK initplatform, device_model, cpu_cores, gpu_name, total_ram, app_version
session_pingEvery 60s during playfps, ram_bytes, scene (live snapshot at ping time)
session_endOn WM_CLOSE_REQUESTduration, min_fps, avg_fps, max_fps, max_ram, fps_samples, device_model

session_ping enables mid-session telemetry (long sessions, mobile background, crashes that prevent session_end). FPS and RAM are sampled live at ping time; the dashboard aggregates them for time-series charts and per-device breakdown.

Disable auto-pings by setting Project Settings → quest_data/heartbeat_interval to 0.

# Optional: extra context for hot spots
QuestData.track("lag_spike", {
"frame_drop": 45,
"duration_frames": 12,
"location": "boss_arena"
})
QuestData.track_ui(screen_name: String, element_name: String, action: String = "click")

Helper for tracking UI interactions. Wraps track("ui_interaction", { screen, element, action }) — consistent property names across screens, ready to feed the Engagement dashboard’s UI heatmap.

ParameterTypeDefaultDescription
screen_nameStringrequiredThe current screen / page (e.g. "main_menu", "shop")
element_nameStringrequiredElement identifier (e.g. "play_button", "sword_item")
actionString"click"Interaction type — "click", "view", "hover", "swipe", …
# Button presses
QuestData.track_ui("main_menu", "play_button") # default action = "click"
QuestData.track_ui("settings", "music_volume", "drag")
# Element views (e.g. shop item came into viewport)
QuestData.track_ui("shop", "starter_pack", "view")
# Tab switches
QuestData.track_ui("inventory", "weapons_tab", "click")

screen_name and element_name are required and must be non-empty — the SDK skips the call with a warning otherwise.

# Recommended: Use helper functions
QuestData.unlock_achievement("first_boss_defeat")
QuestData.submit_score("weekly_boss_speedrun", 1250)
# Ad watched (custom event — no helper function)
QuestData.track("ad_watched", {
"ad_type": "rewarded",
"reward_amount": 100,
"reward_type": "coins"
})

Track anything specific to your game:

# Custom event: boss defeated
QuestData.track("boss_defeated", {
"boss_id": "dragon_lord",
"boss_name": "Dragon Lord",
"level": 12,
"attempts": 3,
"damage_taken": 45,
"time_spent_seconds": 600
})
# Custom event: resource earned
QuestData.track("resource_earned", {
"resource_type": "gold",
"amount": 500,
"source": "quest_completion"
})
# Custom event: feature used
QuestData.track("feature_used", {
"feature": "daily_challenge",
"completed": true,
"difficulty": "normal"
})

All properties are optional. Common properties for all events:

{
"timestamp": 1712415000,
"player_id": "player123",
"session_id": "sess_xyz",
"version": "1.2.0",
"platform": "iOS"
}
PropertyLimitNotes
Properties per event50More = bigger payloads
Property value size1KBDon’t pass entire objects
Event size64KBTotal payload per batch
Queue size10,000 eventsOlder events dropped if exceeded

Events are automatically batched:

  • Trigger 1: 10+ events queued → send immediately
  • Trigger 2: 10 seconds elapsed → send batch
  • Offline: Events saved to user://quest_queue.save
  • Retry: Failed batches retry every 30s (max 5 times)
# Check queue status
var queue_size = QuestData.get_queue_size()
# Force flush
QuestData.flush()
  1. Keep properties small — use IDs not full objects
  2. Be consistent — use same event names always
  3. Don’t track PII — avoid names, emails, addresses
  4. Sample high-frequency events — don’t track every frame
  5. Test locally before release

Events not appearing?

  1. Check API key: ProjectSettings.get_setting("quest_data/api_key")
  2. Wait 15 seconds for batching
  3. Force flush: QuestData.flush()
  4. Check Configuration > Logs in dashboard

Events buffering?

  1. Check internet connection
  2. SDK retries automatically
  3. Events persist to disk on crash