# Analytics Tutorial Learn how to track player behavior, measure engagement, and make data-driven decisions with AeThex Analytics. --- ## What You'll Build A complete analytics system that tracks: - Player events (level complete, item collected, etc.) - User properties (level, skill, preferences) - Custom funnels (onboarding, purchases, retention) - Crash reports and errors - Performance metrics **Time:** 25 minutes **Difficulty:** Beginner **Prerequisites:** Basic GDScript knowledge --- ## Why Use Analytics? Analytics helps you: - **Understand players** - See what they do in your game - **Improve retention** - Find where players drop off - **Optimize monetization** - Track purchase funnels - **Fix bugs faster** - Get crash reports automatically - **Make data-driven decisions** - Know what features to build --- ## Step 1: Connect to Analytics First, connect to AeThex Cloud and initialize analytics: ```gdscript # main.gd extends Node func _ready(): # Connect to cloud var result = await AeThexCloud.connect_to_cloud() if result.success: print("Connected to AeThex Cloud") initialize_analytics() else: print("Failed to connect: ", result.error) func initialize_analytics(): # Analytics initialization is automatic # Track app start AeThexAnalytics.track_event("app_started", { "platform": OS.get_name(), "version": ProjectSettings.get_setting("application/config/version") }) ``` --- ## Step 2: Track Basic Events Track important game events: ```gdscript #player.gd extends CharacterBody2D var level = 1 var score = 0 func level_complete(): # Track level completion AeThexAnalytics.track_event("level_complete", { "level": level, "score": score, "time_spent": get_level_time(), "deaths": death_count }) level += 1 func collect_item(item_name: String): # Track item collection AeThexAnalytics.track_event("item_collected", { "item_name": item_name, "level": level, "timestamp": Time.get_unix_time_from_system() }) func player_died(): # Track deaths AeThexAnalytics.track_event("player_died", { "level": level, "cause": death_cause, "position": global_position }) ``` --- ## Step 3: Set User Properties Store persistent information about users: ```gdscript # analytics_manager.gd (autoload) extends Node func _ready(): # Set up user properties when game starts setup_user_properties() func setup_user_properties(): # Basic user info AeThexAnalytics.set_user_property("platform", OS.get_name()) AeThexAnalytics.set_user_property("game_version", ProjectSettings.get_setting("application/config/version")) # Load from save file var save_data = load_save() if save_data: AeThexAnalytics.set_user_property("player_level", save_data.level) AeThexAnalytics.set_user_property("total_playtime", save_data.playtime) AeThexAnalytics.set_user_property("achievements_unlocked", save_data.achievements.size()) func on_player_level_up(new_level: int): # Update user property when it changes AeThexAnalytics.set_user_property("player_level", new_level) func on_achievement_unlocked(achievement_id: String): # Increment property AeThexAnalytics.increment_user_property("achievements_unlocked", 1) # Track event AeThexAnalytics.track_event("achievement_unlocked", { "achievement_id": achievement_id }) ``` --- ## Step 4: Track Screen Views Monitor which screens players visit: ```gdscript # base_screen.gd (inherit from this for all screens) extends Control var screen_name: String = "Unknown" var screen_enter_time: float = 0 func _ready(): screen_enter_time = Time.get_ticks_msec() / 1000.0 track_screen_view() func _exit_tree(): track_screen_duration() func track_screen_view(): AeThexAnalytics.track_event("screen_view", { "screen_name": screen_name, "timestamp": Time.get_unix_time_from_system() }) func track_screen_duration(): var duration = (Time.get_ticks_msec() / 1000.0) - screen_enter_time AeThexAnalytics.track_event("screen_duration", { "screen_name": screen_name, "duration_seconds": duration }) ``` **Example usage:** ```gdscript # main_menu.gd extends "res://scripts/base_screen.gd" func _ready(): screen_name = "main_menu" super._ready() ``` --- ## Step 5: Track Economy Events Monitor in-game economy: ```gdscript # economy_tracker.gd extends Node func currency_earned(currency_name: String, amount: int, source: String): AeThexAnalytics.track_event("currency_earned", { "currency": currency_name, "amount": amount, "source": source, # "quest", "shop", "reward", etc. "total_balance": get_currency_balance(currency_name) }) func currency_spent(currency_name: String, amount: int, item: String): AeThexAnalytics.track_event("currency_spent", { "currency": currency_name, "amount": amount, "item": item, "remaining_balance": get_currency_balance(currency_name) }) func item_purchased(item_id: String, price: int, currency: String): AeThexAnalytics.track_event("item_purchased", { "item_id": item_id, "price": price, "currency": currency, "source": "shop" # or "chest", "reward", etc. }) func real_money_purchase(product_id: String, price: float, currency: String): AeThexAnalytics.track_event("iap_purchase", { "product_id": product_id, "price": price, "currency": currency, "revenue": price # Important for revenue tracking }) ``` --- ## Step 6: Create Funnels Track conversion funnels to understand player flow: ```gdscript # funnel_tracker.gd extends Node # Onboarding funnel func track_onboarding_funnel(step: String): var funnel_steps = [ "tutorial_start", "tutorial_complete", "first_level_start", "first_level_complete", "account_created" ] AeThexAnalytics.track_event("onboarding_funnel", { "step": step, "step_number": funnel_steps.find(step) + 1, "total_steps": funnel_steps.size() }) # Purchase funnel func track_purchase_funnel(step: String, product_id: String = ""): AeThexAnalytics.track_event("purchase_funnel", { "step": step, # "view_shop", "select_item", "confirm", "complete" "product_id": product_id }) # Level progression funnel func track_level_funnel(step: String, level: int): AeThexAnalytics.track_event("level_funnel", { "step": step, # "start", "complete", "fail", "abandon" "level": level }) ``` **Example usage:** ```gdscript # tutorial.gd func _ready(): FunnelTracker.track_onboarding_funnel("tutorial_start") func on_tutorial_complete(): FunnelTracker.track_onboarding_funnel("tutorial_complete") # shop.gd func _on_item_clicked(product_id): FunnelTracker.track_purchase_funnel("select_item", product_id) func _on_purchase_confirmed(product_id): FunnelTracker.track_purchase_funnel("confirm", product_id) ``` --- ## Step 7: Track Engagement Metrics Measure player engagement: ```gdscript # engagement_tracker.gd (autoload) extends Node var session_start_time: float = 0 var total_sessions: int = 0 var events_this_session: int = 0 func _ready(): start_session() func start_session(): session_start_time = Time.get_ticks_msec() / 1000.0 total_sessions = load_total_sessions() + 1 save_total_sessions(total_sessions) AeThexAnalytics.track_event("session_start", { "session_number": total_sessions, "days_since_install": get_days_since_install() }) # Set user property AeThexAnalytics.set_user_property("total_sessions", total_sessions) func end_session(): var session_duration = (Time.get_ticks_msec() / 1000.0) - session_start_time AeThexAnalytics.track_event("session_end", { "duration_seconds": session_duration, "events_tracked": events_this_session }) func _notification(what): if what == NOTIFICATION_WM_CLOSE_REQUEST: end_session() func track_engagement_event(): events_this_session += 1 func get_days_since_install() -> int: var install_date = load_install_date() if install_date == 0: install_date = Time.get_unix_time_from_system() save_install_date(install_date) return 0 var current_time = Time.get_unix_time_from_system() var days = (current_time - install_date) / 86400.0 # seconds in a day return int(days) ``` --- ## Step 8: Track Errors and Crashes Automatically report errors: ```gdscript # error_tracker.gd (autoload) extends Node func _ready(): # Catch unhandled errors Engine.get_singleton("ScriptServer").add_global_constant("ErrorTracker", self) func track_error(error_message: String, stack_trace: String = ""): AeThexAnalytics.track_event("error_occurred", { "error_message": error_message, "stack_trace": stack_trace, "platform": OS.get_name(), "version": ProjectSettings.get_setting("application/config/version") }) func track_crash(crash_reason: String): AeThexAnalytics.track_event("game_crash", { "reason": crash_reason, "platform": OS.get_name(), "memory_used": Performance.get_monitor(Performance.MEMORY_STATIC), "fps": Engine.get_frames_per_second() }) # Catch GDScript errors func _on_error(error_message: String): track_error(error_message, get_stack()) # Helper to get stack trace func get_stack() -> String: var stack = get_stack_trace() var result = "" for frame in stack: result += "%s:%d in %s()\n" % [frame.source, frame.line, frame.function] return result func get_stack_trace() -> Array: return [] # Implemented in debug builds ``` --- ## Step 9: Performance Tracking Track game performance metrics: ```gdscript # performance_tracker.gd (autoload) extends Node const SAMPLE_INTERVAL = 5.0 # seconds var sample_timer: Timer func _ready(): sample_timer = Timer.new() sample_timer.timeout.connect(_sample_performance) sample_timer.wait_time = SAMPLE_INTERVAL add_child(sample_timer) sample_timer.start() func _sample_performance(): var fps = Engine.get_frames_per_second() var memory_mb = Performance.get_monitor(Performance.MEMORY_STATIC) / 1024.0 / 1024.0 var draw_calls = Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME) # Track performance event AeThexAnalytics.track_event("performance_sample", { "fps": fps, "memory_mb": memory_mb, "draw_calls": draw_calls, "scene": get_tree().current_scene.name if get_tree().current_scene else "unknown" }) # Alert on low performance if fps < 30: track_low_performance(fps, memory_mb) func track_low_performance(fps: int, memory_mb: float): AeThexAnalytics.track_event("low_performance", { "fps": fps, "memory_mb": memory_mb, "platform": OS.get_name(), "scene": get_tree().current_scene.name if get_tree().current_scene else "unknown" }) ``` --- ## Step 10: A/B Testing Implement A/B tests to compare features: ```gdscript # ab_testing.gd (autoload) extends Node var user_variant: String = "" func _ready(): assign_variant() func assign_variant(): # Check if user already has a variant assigned user_variant = load_user_variant() if user_variant.is_empty(): # Randomly assign variant (50/50 split) user_variant = "A" if randf() < 0.5 else "B" save_user_variant(user_variant) # Set as user property AeThexAnalytics.set_user_property("ab_test_variant", user_variant) # Track assignment AeThexAnalytics.track_event("ab_test_assigned", { "variant": user_variant }) func get_variant() -> String: return user_variant func is_variant_a() -> bool: return user_variant == "A" func is_variant_b() -> bool: return user_variant == "B" func track_conversion(goal: String): AeThexAnalytics.track_event("ab_test_conversion", { "variant": user_variant, "goal": goal }) ``` **Example usage:** ```gdscript # Configure feature based on variant func _ready(): if ABTesting.is_variant_a(): # Show red button $Button.modulate = Color.RED else: # Show blue button $Button.modulate = Color.BLUE func _on_button_pressed(): # Track which variant converted ABTesting.track_conversion("button_clicked") ``` --- ## Analytics Dashboard View your analytics data: 1. **Go to:** [https://studio.aethex.io/analytics](https://studio.aethex.io/analytics) 2. **Select your project** 3. **View dashboards:** - Overview: DAU, MAU, retention - Events: All tracked events - Funnels: Conversion funnels - User Properties: Audience segments - Errors: Crash reports - Performance: FPS, memory, load times --- ## Best Practices ### 1. **Name Events Consistently** ```gdscript # ✓ DO - Use snake_case AeThexAnalytics.track_event("level_complete", {}) AeThexAnalytics.track_event("item_collected", {}) # ❌ DON'T - Inconsistent naming AeThexAnalytics.track_event("LevelComplete", {}) AeThexAnalytics.track_event("item-collected", {}) ``` ### 2. **Include Context in Events** ```gdscript # ✓ DO - Rich context AeThexAnalytics.track_event("button_clicked", { "button_name": "play", "screen": "main_menu", "session_time": get_session_time() }) # ❌ DON'T - No context AeThexAnalytics.track_event("button_clicked", {}) ``` ### 3. **Track the User Journey** ```gdscript # Track entire player flow AeThexAnalytics.track_event("game_started", {}) AeThexAnalytics.track_event("tutorial_started", {}) AeThexAnalytics.track_event("tutorial_completed", {}) AeThexAnalytics.track_event("first_level_started", {}) AeThexAnalytics.track_event("first_level_completed", {}) ``` ### 4. **Avoid PII (Personally Identifiable Information)** ```gdscript # ❌ DON'T - Include PII AeThexAnalytics.track_event("user_info", { "email": "user@example.com", # Never track emails "name": "John Doe", # Never track real names "ip_address": "192.168.1.1" # Never track IPs }) # ✓ DO - Use anonymous identifiers AeThexAnalytics.track_event("user_info", { "user_id": "anon_123456", "player_level": 5 }) ``` ### 5. **Batch Events if Needed** ```gdscript # For high-frequency events, batch them var event_batch = [] func track_player_movement(): event_batch.append({ "event": "player_moved", "position": player.position }) if event_batch.size() >= 10: flush_events() func flush_events(): for event in event_batch: AeThexAnalytics.track_event(event.event, event) event_batch.clear() ``` --- ## Common Metrics to Track ### Engagement Metrics: - Daily Active Users (DAU) - Monthly Active Users (MAU) - Session length - Sessions per user - Day 1/7/30 retention ### Monetization Metrics: - Average Revenue Per User (ARPU) - Paying User Rate - Lifetime Value (LTV) - Conversion rate ### Game Metrics: - Level completion rate - Tutorial completion rate - Time to first action - Churn points - Player progression --- ## Example: Complete Analytics Setup ```gdscript # analytics_complete.gd (autoload) extends Node signal analytics_ready var is_initialized = false func _ready(): initialize() func initialize(): # Wait for cloud connection await get_tree().create_timer(1.0).timeout if not AeThexCloud.is_connected(): await AeThexCloud.connect_to_cloud() # Set up user properties setup_user_properties() # Start session tracking start_session() # Connect to game signals connect_game_signals() is_initialized = true analytics_ready.emit() func setup_user_properties(): AeThexAnalytics.set_user_property("platform", OS.get_name()) AeThexAnalytics.set_user_property("game_version", get_game_version()) AeThexAnalytics.set_user_property("install_date", get_install_date()) func start_session(): AeThexAnalytics.track_event("session_start", { "platform": OS.get_name(), "version": get_game_version() }) func connect_game_signals(): # Connect to various game events var game = get_tree().root.get_node("Game") if game: game.level_completed.connect(on_level_completed) game.player_died.connect(on_player_died) game.item_collected.connect(on_item_collected) func on_level_completed(level: int, score: int): AeThexAnalytics.track_event("level_complete", { "level": level, "score": score }) func on_player_died(level: int, cause: String): AeThexAnalytics.track_event("player_died", { "level": level, "cause": cause }) func on_item_collected(item: String): AeThexAnalytics.track_event("item_collected", { "item": item }) func get_game_version() -> String: return ProjectSettings.get_setting("application/config/version", "1.0.0") func get_install_date() -> int: # Load from save or set to current time var save_file = FileAccess.open("user://install_date.save", FileAccess.READ) if save_file: var date = save_file.get_64() save_file.close() return date else: var date = Time.get_unix_time_from_system() save_file = FileAccess.open("user://install_date.save", FileAccess.WRITE) save_file.store_64(date) save_file.close() return date ``` --- ## Testing Analytics Test your analytics implementation: ```gdscript # test_analytics.gd extends Node func _ready(): test_analytics() func test_analytics(): print("Testing analytics...") # Test basic event AeThexAnalytics.track_event("test_event", { "test": true }) # Test user property AeThexAnalytics.set_user_property("test_property", "test_value") # Check console for confirmation print("Analytics test complete. Check dashboard for events.") ``` --- ## Next Steps - **[Publishing Guide](../PUBLISHING_GUIDE.md)** - Deploy your game with analytics - **[API Reference](../API_REFERENCE.md#aethexanalytics-singleton)** - Complete analytics API - **Dashboard:** View your data at [studio.aethex.io/analytics](https://studio.aethex.io/analytics) --- ## Summary You've learned how to: ✅ Track custom events ✅ Set user properties ✅ Create conversion funnels ✅ Monitor performance ✅ Track errors and crashes ✅ Implement A/B testing ✅ Measure engagement metrics Analytics gives you the insights to make your game better and understand your players! **Ready to publish?** Check out the [Publishing Guide](../PUBLISHING_GUIDE.md)! 🚀