Best Practices
These are the do’s and don’ts that save you from headaches down the road. Follow these patterns and your analytics data will be clean, your game will stay fast, and your players’ privacy will be protected.
Event Naming
Section titled “Event Naming”Consistent event names make your data queryable. Inconsistent names create noise.
# snake_case, verb_noun patternQuestData.track("level_complete", {"level": 5})QuestData.track("item_purchased", {"item": "sword"})QuestData.track("boss_defeated", {"boss": "dragon"})QuestData.track("tutorial_skipped", {"step": "combat"})# Inconsistent naming — don't do thisQuestData.track("LevelComplete", {}) # PascalCaseQuestData.track("level-complete", {}) # kebab-caseQuestData.track("level complete", {}) # spacesQuestData.track("lvl_comp", {}) # abbreviatedQuestData.track("completed level 5", {}) # natural languageNaming convention
Section titled “Naming convention”| Pattern | Example | Use case |
|---|---|---|
noun_verb | level_complete | Most events |
noun_noun | shop_opened | UI navigation |
noun_adjective | player_dead | State changes |
What to Track (and What Not To)
Section titled “What to Track (and What Not To)”- State changes — level_start, level_complete, level_fail
- Milestones — every 100th click, first purchase, prestige
- Business events — purchases, subscription changes, ad views
- Errors — crashes, corrupted data, unexpected states
- Session lifecycle — game_start, game_end (SDK does this automatically)
Don’t track
Section titled “Don’t track”- Every frame — FPS data should be sampled (every 10-30 seconds), not per-frame
- Every input — Don’t track every tap, click, or keypress
- PII — Never send real names, email addresses, phone numbers, or IP addresses
- Passwords or tokens — Never include auth data in event properties
- Large objects — Don’t serialize your entire game state into properties
Rule of thumb
Section titled “Rule of thumb”Ask yourself: “Will I look at this in the dashboard?” If the answer is no, don’t track it.
Performance
Section titled “Performance”The SDK is designed to be lightweight, but you can still cause problems with bad patterns.
How the SDK works
Section titled “How the SDK works”track()is instant — it just adds to an in-memory queue- Events are batched and sent every 10 seconds (or when 10+ events queue up)
- If the server is unreachable, events are saved to disk and retried later
- On game exit, unsent events are automatically persisted
Performance tips
Section titled “Performance tips”| Do | Don’t |
|---|---|
Call track() freely — it’s non-blocking | Don’t call track() in _process() every frame |
| Use milestones (every 100th action) | Don’t track continuous values (mouse position) |
| Keep properties small (IDs, numbers) | Don’t serialize large dictionaries |
| Let the SDK handle batching | Don’t call flush() after every track() |
Queue limits
Section titled “Queue limits”| Limit | Value |
|---|---|
| Max queue size | 10,000 events |
| Max event size | 64 KB |
| Max properties per event | 50 |
| Max property value size | 1 KB |
If the queue exceeds 10,000 events, the oldest events are dropped. This only happens if the server is unreachable for a very long time.
Environments
Section titled “Environments”Separate your development data from production data using environment-specific API keys.
-
Create two API keys in the dashboard under Configuration > API Keys:
- Development key — for local testing
- Production key — for released builds
-
The SDK auto-selects based on build type:
OS.is_debug_build()→ usesquest_data/dev_api_url- Release build → uses
quest_data/prod_api_url
Why this matters
Section titled “Why this matters”- Test events don’t pollute your production analytics
- You can reset your dev database without affecting real data
- Retention and funnel data stay clean
GDPR & Privacy
Section titled “GDPR & Privacy”Quest Data is designed for privacy-first analytics. But you still need to follow the rules.
What the SDK sends
Section titled “What the SDK sends”- Player ID — auto-generated UUID (not linked to real identity)
- Session ID — random, changes every game launch
- Events — only what you explicitly
track() - Device info — OS name, not hardware serials or IMEI
What you should do
Section titled “What you should do”| Requirement | How |
|---|---|
| Consent | Show a consent dialog before enabling tracking |
| Data access | Let players request their data via player ID |
| Data deletion | Delete player data on request (dashboard or API) |
| No PII | Never include real names, emails, addresses in events |
| Disclosure | Mention analytics in your privacy policy |
No-PII checklist
Section titled “No-PII checklist”Before shipping, grep your codebase for track( calls and verify none of these appear in properties:
- Email addresses
- Real names
- Phone numbers
- Physical addresses
- IP addresses (the SDK never sends these)
- Device serial numbers
Security
Section titled “Security”API Key safety
Section titled “API Key safety”Your API key identifies your game to the server. Treat it with basic care:
| Do | Don’t |
|---|---|
| Store in Godot ProjectSettings | Hardcode in GDScript files |
| Use different keys for dev/prod | Use the same key everywhere |
| Rotate keys if compromised | Share keys in public repos |
The API key is not a secret in the traditional sense — it’s embedded in your game binary which players can decompile. It’s more like a project identifier. The server validates it but doesn’t expose sensitive data through it.
What the API key can do
Section titled “What the API key can do”- Send events (
POST /v1/track) - Read configs (
GET /v1/config) - Submit scores, unlock achievements, save games
What it cannot do
Section titled “What it cannot do”- Access other games’ data
- Read other players’ data
- Delete data
- Access the admin dashboard
Common Mistakes
Section titled “Common Mistakes”| Mistake | Problem | Fix |
|---|---|---|
Tracking in _process() | Thousands of events per second | Track milestones or sample periodically |
| Different event names for same thing | Fragmented data | Use a naming convention |
| Tracking without consent | GDPR violation | Add consent dialog |
| Using one API key everywhere | Test data in production | Create separate dev/prod keys |
| Logging stack traces as events | Wrong tool | Use track_error() for crashes, log_error() for logs |
| Huge properties | Wasted bandwidth, potential rejection | Keep properties small, use IDs |
Next Steps
Section titled “Next Steps”- Event Tracking Reference — All event types and properties
- Analytics Guide — Make sense of your data
- Remote Debugging Guide — Find and fix bugs
- Godot Tutorial — Complete integration walkthrough