Godot Integration Tutorial
This tutorial walks you through integrating Quest Data into a simple Idle/Clicker game. By the end, your game will track events, progression, purchases, remote config, and leaderboards. Each step builds on the previous one.
Step 1: Track Core Events
Section titled “Step 1: Track Core Events”Start by tracking the most important player actions. In your main game script:
extends Node
func _ready(): # Track game start with useful context QuestData.track("game_start", { "version": ProjectSettings.get_setting("application/config/version", "1.0"), "platform": OS.get_name(), "language": TranslationServer.get_locale() })
func _on_click_button_pressed(): # Don't track every click — track milestones instead total_clicks += 1 if total_clicks % 100 == 0: QuestData.track("milestone_reached", { "type": "clicks", "count": total_clicks })Step 2: Player Properties
Section titled “Step 2: Player Properties”Tell Quest Data who your players are so you can segment them later:
func _ready(): # Set properties once on game start QuestData.set_user_properties({ "platform": OS.get_name(), "language": TranslationServer.get_locale(), "first_launch": not FileAccess.file_exists("user://save.dat") })
func _on_level_up(new_level: int): # Update as the player progresses QuestData.set_user_property("highest_level", new_level)These properties appear in the Player Explorer and can be used for Segments.
Step 3: Progression Tracking
Section titled “Step 3: Progression Tracking”Track levels, stages, or any sequential content. The SDK automatically calculates how long each attempt takes:
func start_level(level_id: String, difficulty: String = "normal"): QuestData.start_progression(level_id, difficulty)
func complete_level(level_id: String, score: int): QuestData.complete_progression(level_id, score) # Duration is calculated automatically!
func fail_level(level_id: String, reason: String): QuestData.fail_progression(level_id, reason)In your game:
# Player enters level 5 on hard modestart_level("level_5", "hard")
# Player beats it with a score of 1200complete_level("level_5", 1200)
# Or diesfail_level("level_5", "out_of_health")What you see in the dashboard: Completion rates per level, average duration, most common failure reasons. This tells you where your difficulty curve is wrong.
See Progression Tracking Reference for full API details.
Step 4: Purchase Tracking
Section titled “Step 4: Purchase Tracking”Track in-app purchases to see revenue in the dashboard:
func _on_purchase_completed(product_id: String, price: float): QuestData.track_purchase(product_id, price, "USD", { "store": "google_play", "player_level": current_level })Common products for idle games:
# Coin packsQuestData.track_purchase("coins_1000", 0.99)QuestData.track_purchase("coins_10000", 4.99)
# Speed boostQuestData.track_purchase("speed_boost_1h", 1.99, "USD", { "boost_type": "speed", "duration_hours": 1})
# Remove adsQuestData.track_purchase("remove_ads", 2.99)What you see in the dashboard: Revenue timeline, top-selling products, ARPPU, paying vs. free players.
See Purchase Tracking Reference and the Monetization Guide.
Step 5: Remote Config
Section titled “Step 5: Remote Config”Change game settings without pushing an update. First, create some config keys in the dashboard under Configuration > Remote Config:
| Key | Value | Description |
|---|---|---|
coin_multiplier | 1.0 | Coins earned per click |
daily_bonus | 100 | Free coins per day |
show_ads | true | Whether to show ads |
Then read them in your game:
func _ready(): # Fetch latest config from server QuestData.fetch_remote_config()
func get_coins_per_click() -> float: # Returns server value, or 1.0 if not fetched yet return QuestData.get_config("coin_multiplier", 1.0)
func should_show_ads() -> bool: return QuestData.get_config("show_ads", true)
func get_daily_bonus() -> int: return QuestData.get_config("daily_bonus", 100)Power move: Create a Segment for VIP players (tag: vip) and give them coin_multiplier = 2.0. They get double coins without any code change.
See Remote Config Reference and the Live Ops Guide.
Step 6: Leaderboards
Section titled “Step 6: Leaderboards”Add a global leaderboard so players can compete:
func _on_game_over(final_score: int): # Submit score — SDK buffers and sends efficiently QuestData.submit_score("global_highscore", final_score, { "level_reached": current_level }, player_display_name)
func show_leaderboard(): # Fetch top 10 QuestData.get_leaderboard("global_highscore", 10, func(entries: Array): for entry in entries: add_leaderboard_row(entry["rank"], entry["player_name"], entry["score"]) )The SDK handles score buffering (only sends the highest score per 5-second window) and the server uses UPSERT logic (only updates if the new score is higher).
See Leaderboards Reference and the Player Management Guide.
Step 7: Error Tracking (Bonus)
Section titled “Step 7: Error Tracking (Bonus)”Catch errors so you can debug production crashes remotely:
func load_save_file() -> Dictionary: var file = FileAccess.open("user://save.dat", FileAccess.READ) if file == null: QuestData.track_error("SaveLoadFailed", "Could not open save file") return {}
var data = file.get_var() if not data is Dictionary: QuestData.track_error("SaveCorrupted", "Expected Dictionary, got " + type_string(typeof(data))) return {} return dataThe SDK automatically captures stack traces and 60 seconds of pre-crash telemetry (FPS, memory, recent events).
See Error Tracking Reference and the Remote Debugging Guide.
What You’ve Built
Section titled “What You’ve Built”Your game now:
- Tracks core events and milestones
- Identifies players with properties
- Measures progression (completion rates, duration, failure reasons)
- Records revenue and purchase data
- Reads live config from the server (no app update needed)
- Has a global leaderboard
- Catches errors with stack traces
All of this data flows into your dashboard in real-time. Open it, play your game for a minute, and watch the events appear.
Next Steps
Section titled “Next Steps”- Analytics Guide — Learn to read your data and make decisions
- Remote Debugging Guide — Set up remote logging and Discord alerts
- Best Practices — Event naming, GDPR, performance tips
- SDK Reference — Complete API documentation