Skip to content
Tolinku
Tolinku
Sign In Start Free
Use Cases · · 5 min read

Onboarding Analytics: Measuring Activation Success

By Tolinku Staff
|
Tolinku e commerce deep linking dashboard screenshot for use cases blog posts

You can't improve onboarding without measuring it. Most teams track whether users "completed onboarding" as a single binary event, which tells you almost nothing about where users struggle or what makes successful users different from those who churn. Effective onboarding analytics break the process into stages, define activation clearly, and track the path from install to engaged user.

For improving completion rates, see Improving Onboarding Completion Rates. For click-through optimization, see Click-Through Rate Optimization for Deep Links.

Defining Activation

Activation vs. Onboarding Completion

These are not the same thing:

Concept Definition Example
Onboarding completion User finished the setup flow Saw all screens, created account
Activation User experienced core value Created first project, made first purchase

A user can complete onboarding without being activated (they created an account but never used the product). An activated user is far more likely to retain.

Finding Your Activation Event

The activation event is the action most correlated with long-term retention. To find it:

async function findActivationEvent() {
  const candidates = [
    'first_project_created',
    'first_item_saved',
    'first_share',
    'first_purchase',
    'profile_completed',
    'first_connection',
    'first_content_viewed',
  ];

  for (const event of candidates) {
    const usersWhoDidIt = await getUsersWithEvent(event, { within: '7_days' });
    const usersWhoDid_not = await getUsersWithoutEvent(event, { within: '7_days' });

    const retentionWith = await getDay30Retention(usersWhoDidIt);
    const retentionWithout = await getDay30Retention(usersWhoDid_not);

    console.log(event, {
      retention_with: retentionWith,
      retention_without: retentionWithout,
      lift: ((retentionWith - retentionWithout) / retentionWithout * 100).toFixed(1) + '%',
    });
  }
}

The event with the highest retention lift is your activation event. For most apps, it's some form of "user created or experienced the product's core value."

Activation Timing

Track not just whether activation happens, but when:

Time to Activation Day 30 Retention
Same session (< 10 min) 45-55%
Day 1 35-45%
Day 2-3 25-35%
Day 4-7 15-25%
After Day 7 5-10%

Users who activate in their first session retain at 3-5x the rate of those who take a week.

The Onboarding Funnel

Stage Definitions

const ONBOARDING_FUNNEL = [
  {
    stage: 'install',
    event: 'app_installed',
    description: 'App downloaded from store',
  },
  {
    stage: 'first_open',
    event: 'app_opened_first_time',
    description: 'App opened for the first time',
  },
  {
    stage: 'signup_started',
    event: 'signup_form_viewed',
    description: 'User saw the signup form',
  },
  {
    stage: 'signup_completed',
    event: 'account_created',
    description: 'Account successfully created',
  },
  {
    stage: 'setup_completed',
    event: 'onboarding_completed',
    description: 'Finished all onboarding steps',
  },
  {
    stage: 'activated',
    event: 'activation_event',
    description: 'Performed the core value action',
  },
  {
    stage: 'retained',
    event: 'return_visit_day_7',
    description: 'Came back on day 7',
  },
];

Funnel Calculation

async function calculateOnboardingFunnel(dateRange, segment) {
  const funnel = [];

  for (let i = 0; i < ONBOARDING_FUNNEL.length; i++) {
    const stage = ONBOARDING_FUNNEL[i];
    const users = await countUniqueUsers(stage.event, { dateRange, segment });

    const previousUsers = i > 0 ? funnel[i - 1].users : users;
    const firstStageUsers = funnel.length > 0 ? funnel[0].users : users;

    funnel.push({
      stage: stage.stage,
      users,
      stepConversion: previousUsers > 0 ? (users / previousUsers * 100).toFixed(1) + '%' : '100%',
      overallConversion: (users / firstStageUsers * 100).toFixed(1) + '%',
      dropOff: previousUsers - users,
    });
  }

  return funnel;
}

Example Funnel Output

Stage Users Step Conversion Overall Drop-Off
Install 10,000 100% 100% 0
First open 8,500 85% 85% 1,500
Signup started 6,200 73% 62% 2,300
Signup completed 4,100 66% 41% 2,100
Setup completed 3,000 73% 30% 1,100
Activated 1,800 60% 18% 1,200
Retained (D7) 900 50% 9% 900

This tells you that the biggest absolute drop-offs are between install and first open (1,500), and between first open and signup started (2,300). The biggest percentage drop is between signup started and completed (66%), indicating signup form friction. For strategies to address these drop-offs, see Reducing Onboarding Drop-Off.

Segmented Analysis

By Acquisition Source

async function funnelBySource(dateRange) {
  const sources = ['organic', 'referral', 'paid_social', 'paid_search', 'email'];

  for (const source of sources) {
    const funnel = await calculateOnboardingFunnel(dateRange, { source });
    console.log(`\n${source}:`);
    for (const stage of funnel) {
      console.log(`  ${stage.stage}: ${stage.users} (${stage.overallConversion})`);
    }
  }
}

Expected pattern:

  • Referral users: Highest completion and activation rates (social proof + trust)
  • Organic search: High intent but moderate completion (no context)
  • Paid social: Moderate intent, lower completion (impulse installs)
  • Paid search: Higher intent than social, moderate completion

By Platform

iOS and Android users often have different onboarding behavior:

async function funnelByPlatform(dateRange) {
  const iosFunnel = await calculateOnboardingFunnel(dateRange, { platform: 'ios' });
  const androidFunnel = await calculateOnboardingFunnel(dateRange, { platform: 'android' });

  console.log('Stage | iOS | Android');
  for (let i = 0; i < iosFunnel.length; i++) {
    console.log(
      iosFunnel[i].stage,
      iosFunnel[i].overallConversion,
      androidFunnel[i].overallConversion
    );
  }
}

Users who arrive via deep links carry context. Measure whether personalized onboarding (using that context) outperforms generic onboarding:

async function funnelByDeepLinkContext(dateRange) {
  const withContext = await calculateOnboardingFunnel(dateRange, { hasDeepLinkContext: true });
  const withoutContext = await calculateOnboardingFunnel(dateRange, { hasDeepLinkContext: false });

  console.log('With deep link context vs. without:');
  for (let i = 0; i < withContext.length; i++) {
    console.log(
      withContext[i].stage,
      'With:', withContext[i].overallConversion,
      'Without:', withoutContext[i].overallConversion
    );
  }
}

Time-Based Metrics

Time to Complete Each Step

async function getStepDurations(dateRange) {
  const steps = ONBOARDING_FUNNEL.map(s => s.event);

  for (let i = 1; i < steps.length; i++) {
    const durations = await getTimeBetweenEvents(steps[i - 1], steps[i], dateRange);

    console.log(`${steps[i - 1]} -> ${steps[i]}:`, {
      median: durations.p50,
      p75: durations.p75,
      p90: durations.p90,
    });
  }
}

Long durations between steps indicate friction. If the median time between "signup form viewed" and "account created" is 3 minutes, the form has too many fields or unclear error messages.

Session Analysis

How many sessions does it take to complete onboarding?

Sessions to Complete % of Users Implication
1 session 60% Healthy (completed in first visit)
2 sessions 20% Acceptable (came back to finish)
3+ sessions 10% Friction (onboarding is too long)
Never 10% Lost (need re-engagement)

Cohort Analysis

Weekly Cohorts

Track onboarding metrics by weekly cohorts to measure improvement over time:

async function onboardingCohorts() {
  const weeks = getLastNWeeks(8);

  for (const week of weeks) {
    const cohortUsers = await getUsersInstalledDuring(week);
    const completed = await countActivated(cohortUsers, { within: '7_days' });
    const retained = await countRetained(cohortUsers, { day: 30 });

    console.log(week.label, {
      cohortSize: cohortUsers.length,
      activationRate: (completed / cohortUsers.length * 100).toFixed(1) + '%',
      day30Retention: (retained / cohortUsers.length * 100).toFixed(1) + '%',
    });
  }
}

This reveals whether your onboarding changes are actually improving metrics over time.

Event Taxonomy

Standard Events

Use consistent event names across your analytics:

// Onboarding events
analytics.track('onboarding_started', { source, variant });
analytics.track('onboarding_step_viewed', { step, stepIndex, totalSteps, variant });
analytics.track('onboarding_step_completed', { step, timeOnStep, variant });
analytics.track('onboarding_step_skipped', { step, variant });
analytics.track('onboarding_abandoned', { lastStep, totalTime, variant });
analytics.track('onboarding_completed', { totalTime, stepsCompleted, variant });

// Activation events
analytics.track('activation_event', { action, timeFromSignup, source });

// Re-engagement events
analytics.track('onboarding_resumed', { lastStep, daysSinceAbandonment, channel });
analytics.track('onboarding_reminder_sent', { nextStep, channel });
analytics.track('onboarding_reminder_opened', { nextStep, channel });

Properties to Include

Every onboarding event should include:

  • userId: For user-level analysis
  • variant: If running A/B tests
  • source: Acquisition channel (organic, referral, paid, etc.)
  • platform: iOS, Android, web
  • appVersion: To catch version-specific issues
  • timestamp: For time-based analysis

Dashboards

Daily Monitoring

Track these daily to catch problems early:

Metric Alert If
Signup conversion rate Drops > 5% from baseline
Activation rate (7-day) Drops > 3% from baseline
Median time to activate Increases > 20%
Onboarding error rate Exceeds 2%
Permission grant rate Drops > 10%

Weekly Review

Metric What to Look For
Funnel by source Are any sources degrading?
Cohort activation trends Is the latest cohort better or worse?
Step-level drop-off Has a specific step gotten worse?
A/B test results Ready to call a winner? (see A/B Testing Onboarding Flows)
Re-engagement recovery rate Are reminders working?

For analytics features, see Tolinku analytics. For onboarding use cases, see the onboarding documentation. For analytics setup, see the analytics docs.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.