Flow Events Tracking

Track the right flow events to gain actionable insights without noise.

Overview#

Event tracking in flows serves two purposes:

  1. Funnel analysis: Understand where users drop off in multi-step flows
  2. Behavior insights: Learn what users engage with and what they skip

The key is balance — track enough to understand behavior, but not so much that you drown in noise.

System Events (Automatic)#

The SDK automatically tracks flow lifecycle at the native layer, outside of your flow code. These events fire regardless of what your flow does:

EventWhenInsight
__started__Flow is presented (before any flow JS runs)How many users see the flow
__completed__complete() is calledHow many users finish successfully
__dismissed__dismiss() is calledHow many users exit early

With just these three events, you get a basic conversion rate: __completed__ / __started__

Don't duplicate system events

Don't track events that duplicate system events under different names (e.g., flow_started, paywall_viewed, flow_dismissed). The SDK already handles this. Event names starting with __ are reserved.

What to Track#

✓ Track Committed Decisions#

// ✓ GOOD: Committed decisions — user moves forward

// Step completion - shows funnel progression
Mobana.trackEvent('step_1_completed');
Mobana.trackEvent('step_2_completed');
Mobana.trackEvent('step_3_completed');

// Confirmed choices - user committed and proceeded
Mobana.trackEvent('plan_confirmed');            // Tapped Continue after picking a plan
Mobana.trackEvent('interests_confirmed');       // Submitted selected interests
Mobana.trackEvent('theme_set');                 // Confirmed theme choice

// Permission outcomes
Mobana.trackEvent('notification_granted');      // System granted permission
Mobana.trackEvent('notification_denied');       // System denied permission

// Deliberate exits
Mobana.trackEvent('onboarding_skipped');        // User chose to skip

✗ Avoid These#

// ✗ BAD: Noise-generating events

// Don't track cyclical/toggleable interactions — creates loops in journey diagrams
Mobana.trackEvent('plan_tapped');         // User taps between plans before deciding
Mobana.trackEvent('toggle_switched');     // User toggles monthly/annual back and forth
Mobana.trackEvent('tab_changed');         // User browses tabs — not a decision

// Don't duplicate system events under different names
Mobana.trackEvent('flow_started');        // __started__ already covers this
Mobana.trackEvent('paywall_viewed');      // __started__ already covers this
Mobana.trackEvent('flow_dismissed');      // __dismissed__ already covers this

// Don't track micro-interactions
Mobana.trackEvent('button_hovered');      // Not actionable
Mobana.trackEvent('scroll_started');      // Not actionable

// Don't use vague names
Mobana.trackEvent('click');               // Click on what?
Mobana.trackEvent('action');              // What action?

The Golden Rule#

Ask yourself:

"If this event count changes, would I change the flow?"

If not, you probably don't need the event.

  • step_2_completed increases: "Great, step 2 is working well. Maybe optimize step 3 now."
  • plan_confirmed drops: "Users are browsing plans but not committing — simplify the pricing step."
  • plan_tapped increases: "...so what? They're just browsing." (Don't track this)

Funnel Tracking Pattern#

For multi-step flows, track completion of each step to identify drop-off points:

onboarding.js
// ONBOARDING FLOW - Event Strategy

// These events create a clear funnel in analytics:
// __started__ (automatic) → step_1 → step_2 → step_3 → __completed__

document.getElementById('step-1-continue').addEventListener('click', () => {
  Mobana.trackEvent('step_1_completed');  // 1. Track step
  Mobana.haptic('light');
  showStep(2);
});

document.getElementById('step-2-continue').addEventListener('click', () => {
  Mobana.trackEvent('step_2_completed');  // 2. Track step
  Mobana.haptic('light');
  showStep(3);
});

document.getElementById('step-3-finish').addEventListener('click', () => {
  Mobana.trackEvent('step_3_completed');  // 3. Track step
  Mobana.haptic('success');
  Mobana.complete({ onboardingVersion: '2.0' });  // → triggers __completed__
});

// Track skip/dismiss too - valuable insight
document.getElementById('skip-btn').addEventListener('click', () => {
  Mobana.trackEvent('onboarding_skipped');
  Mobana.dismiss();  // → triggers __dismissed__
});

This creates a funnel in your Dashboard:

__started__step_1_completedstep_2_completedstep_3_completed__completed__

Tracking Committed Decisions#

Track the moment a user commits to a choice and moves forward — not every exploratory tap:

flow.js
// DECISION POINTS - Track when the user commits, not when they browse

// Plan selection — track on the Continue button, not on each plan tap
// (user may tap between plans multiple times before deciding)
document.getElementById('continue-btn').addEventListener('click', () => {
  const plan = document.querySelector('input[name="plan"]:checked').value;
  Mobana.trackEvent('plan_confirmed');
  Mobana.complete({ plan });
});

// Interests/preferences — track the submission, not each toggle
document.getElementById('confirm-interests').addEventListener('click', () => {
  const selected = getSelectedInterests();
  Mobana.trackEvent('interests_confirmed');
  showNextStep();
});

// Permission decisions — track the outcome
document.getElementById('enable-notifications').addEventListener('click', async () => {
  const granted = await Mobana.requestNotificationPermission();
  Mobana.trackEvent(granted ? 'notification_granted' : 'notification_denied');
  showNextStep();
});

// Deliberate skip
document.getElementById('skip-btn').addEventListener('click', () => {
  Mobana.trackEvent('onboarding_skipped');
  Mobana.dismiss();
});

Naming Convention#

Consistent naming makes analytics easier to understand:

// NAMING CONVENTION

// Use snake_case
Mobana.trackEvent('step_completed');      // ✓ Good
Mobana.trackEvent('stepCompleted');       // ✗ camelCase
Mobana.trackEvent('StepCompleted');       // ✗ PascalCase
Mobana.trackEvent('step-completed');      // ✗ kebab-case

// Be specific
Mobana.trackEvent('notification_granted');   // ✓ Clear
Mobana.trackEvent('click');                  // ✗ Click on what?

// Use consistent prefixes
Mobana.trackEvent('step_1_completed');
Mobana.trackEvent('step_2_completed');
Mobana.trackEvent('step_3_completed');

// Include context
Mobana.trackEvent('plan_confirmed');
Mobana.trackEvent('upgrade_declined');
Mobana.trackEvent('onboarding_skipped');

Post-Flow Event Tracking#

Track events after the flow closes using the result's trackEvent function:

app.tsx
// In your app
const result = await Mobana.startFlow('pre-purchase');

if (result.completed) {
  // User completed the flow, now watch for purchase...
  
  // Later, when purchase happens:
  await result.trackEvent?.('purchase_completed', { amount: 49.99 });
  
  // Or use trackConversion with sessionId for attribution
  Mobana.trackConversion('purchase', 49.99, result.sessionId);
}
AI agents: for complete Mobana SDK & API documentation, get full context here or visit llms.txt