GameAnalytics
C# Architecture
Onboarding Funnel
Telemetry
Unity Development
Mobile Games

Unity Game Onboarding Funnel Tracking with GameAnalytics: C# Implementation & Drop-Off Telemetry (Part 2)

4 min read
Eshan Naithani

Welcome to Part 2 of our 3-Part GameAnalytics Onboarding Funnel Masterclass:

In this second installment, we write a robust, production-ready C# manager (OnboardingFunnelTracker) that automatically tracks step completion, measures exact time spent on each step, logs failure retries, and handles mandatory vs optional tutorial steps.


1. Designing the OnboardingFunnelTracker Singleton

A clean onboarding manager must satisfy 4 production requirements:

  1. Prevent Duplicate Logs: Ensure a step is only logged as completed once per player lifetime.
  2. Track Time-to-Complete: Measure how many seconds players take to complete each tutorial section.
  3. Handle Retry Loops: Distinguish between a player who completes a step on their first try vs someone who fails 5 times.
  4. Persist Completion State: Use PlayerPrefs or server saving to avoid re-triggering tutorial telemetry on game restart.

2. Production C# Onboarding Funnel Manager

CSHARP
using System;
using System.Collections.Generic;
using UnityEngine;
using GameAnalyticsSDK;

public class OnboardingFunnelTracker : MonoBehaviour
{
    private static OnboardingFunnelTracker instance;
    public static OnboardingFunnelTracker Instance => instance;

    // Track step start times for exact duration calculations
    private Dictionary<string, float> stepStartTimes = new Dictionary<string, float>();

    private void Awake()
    {
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
        DontDestroyOnLoad(gameObject);
    }

    // =========================================================================
    // STEP START
    // =========================================================================
    public void TrackStepStart(string stepName)
    {
        string prefKey = $"Onboarding_Completed_{stepName}";
        if (PlayerPrefs.GetInt(prefKey, 0) == 1)
        {
            // Step already completed by this user in a previous session
            return;
        }

        if (!stepStartTimes.ContainsKey(stepName))
        {
            stepStartTimes.Add(stepName, Time.time);
        }
        else
        {
            stepStartTimes[stepName] = Time.time;
        }

        Debug.Log($"[Funnel Telemetry] Started Step: {stepName}");
        
        // Log Progression Start to GameAnalytics
        GameAnalytics.NewProgressionEvent(
            GAProgressionStatus.Start,
            "Tutorial",
            stepName
        );
    }

    // =========================================================================
    // STEP COMPLETE
    // =========================================================================
    public void TrackStepComplete(string stepName, int score = 0)
    {
        string prefKey = $"Onboarding_Completed_{stepName}";
        if (PlayerPrefs.GetInt(prefKey, 0) == 1)
        {
            return;
        }

        float durationSeconds = 0f;
        if (stepStartTimes.ContainsKey(stepName))
        {
            durationSeconds = Time.time - stepStartTimes[stepName];
            stepStartTimes.Remove(stepName);
        }

        // Save completed state locally
        PlayerPrefs.SetInt(prefKey, 1);
        PlayerPrefs.Save();

        Debug.Log($"[Funnel Telemetry] Completed Step: {stepName} in {durationSeconds:F1}s");

        // Log Progression Complete to GameAnalytics
        GameAnalytics.NewProgressionEvent(
            GAProgressionStatus.Complete,
            "Tutorial",
            stepName,
            score
        );

        // Also log a design event with time duration for custom funnel slicing
        GameAnalytics.NewDesignEvent(
            $"OnboardingTime:{stepName}",
            durationSeconds
        );
    }

    // =========================================================================
    // STEP FAIL / RETRY
    // =========================================================================
    public void TrackStepFail(string stepName, string failReason)
    {
        Debug.LogWarning($"[Funnel Telemetry] Failed Step: {stepName} | Reason: {failReason}");

        // Log Progression Fail to GameAnalytics
        GameAnalytics.NewProgressionEvent(
            GAProgressionStatus.Fail,
            "Tutorial",
            stepName
        );

        // Log specific fail reason design event
        GameAnalytics.NewDesignEvent($"OnboardingFail:{stepName}:{failReason}");
    }

    // =========================================================================
    // TUTORIAL SKIP
    // =========================================================================
    public void TrackTutorialSkipped(string lastStepName)
    {
        Debug.Log($"[Funnel Telemetry] Player Skipped Tutorial at Step: {lastStepName}");
        GameAnalytics.NewDesignEvent($"Onboarding:SkippedAt:{lastStepName}");
    }
}

3. Integrating the Tracker into Gameplay Scripts

Trigger tracking events cleanly inside your tutorial UI or trigger volume scripts.

CSHARP
// Example: Triggering Funnel Events in a Tutorial Dialogue Controller
public class TutorialDialogueStep : MonoBehaviour
{
    [SerializeField] private string stepName = "01_Welcome_Splash";

    private void OnEnable()
    {
        // Track when the player sees this tutorial dialog
        OnboardingFunnelTracker.Instance.TrackStepStart(stepName);
    }

    public void OnNextButtonClicked()
    {
        // Track when player clicks Next/Continue
        OnboardingFunnelTracker.Instance.TrackStepComplete(stepName);
        
        // Load next tutorial step...
    }
}

4. Part 2 Summary & Next Steps

In this second guide, we implemented the C# OnboardingFunnelTracker manager, recorded step durations, and logged failure/skip events to GameAnalytics.

šŸ‘‰ Continue to Part 3: Funnel Visualization, A/B Testing & D1 Retention Tuning →


šŸ’” Need a Custom Analytics & Onboarding Audit for Your Game?

Struggling with low D1 retention or high onboarding churn? I work directly with game studios to design custom telemetry pipelines, diagnose drop-off bottlenecks, and optimize tutorial UX:

  • Telemetry Architecture: Designing clean GameAnalytics, GA4, and Firebase event schemas.
  • Onboarding UX Optimization: Streamlining early game pacing to maximize player retention.
  • Monetization & LiveOps Setup: Interlinking analytics with IAP and ad mediation waterfalls.

šŸ‘‰ Book an Analytics & Onboarding Strategy Session or reach out directly to discuss your game's metrics.


šŸŽ® Shipped Mobile Games & Official Store Profiles

Explore live commercial titles built with Unity and published across official app stores:


Planning to launch a mobile game or optimize your engineering budget? Check out our 2026 Mobile Game Development Cost Guide or book an engineering consultation.

Share this article

Looking to build a production-ready game?

See how I built Bird Sort Mania in 20 days using AI, or check out my full Mobile Games Portfolio to see my shipped titles on Android and iOS.

Join 5,000+ Game Developers

Get weekly insights on Unity performance optimization, AI gameplay architectures, and robust system design. No spam, just deep technical breakdowns.

Unsubscribe at any time. Your data is never shared.

Recommended Reading

More articles in GameAnalytics