Building Effective Flows

Best practices for designing flows that engage users and generate valuable insights.

Introduction#

Flows are full-screen HTML experiences displayed inside a WebView. They're perfect for onboarding, permission requests, feature announcements, surveys, and upgrade prompts.

Well-designed flows guide users through important moments while generating actionable analytics. This guide covers the principles and patterns that make flows effective.

Flow Structure#

Every flow is a single HTML file with embedded CSS and JavaScript:

flow.html
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    /* Your CSS here */
  </style>
</head>
<body>
  <!-- Your HTML content -->
  
  <script>
    // Your JavaScript here
    // Mobana bridge is available as window.Mobana
  </script>
</body>
</html>

The Mobana bridge is injected before your code runs, so you can use it immediately in your scripts.

Design Principles#

1. Keep It Focused#

Each flow should have one clear goal. Don't try to do too much.

  • Onboarding flow: Explain value, collect preferences
  • Permission flow: Explain why, request one permission
  • Mega flow: Onboarding + permissions + upsell + survey

2. Lead with Value#

Before asking for anything (permission, signup, purchase), explain what the user gets.

  • "Get daily tips to help you reach your goals" → Enable notifications
  • "Enable notifications" → (no context)

3. Always Provide an Exit#

Users should always be able to dismiss or skip. Trapped users become frustrated users.

  • • Include a "Skip" or "Maybe later" option
  • • Or a visible close/dismiss button
  • • Track skips as events for insights

4. Show Progress#

For multi-step flows, show users where they are and how many steps remain.

  • • Step indicators (dots, numbers)
  • • Progress bars
  • • "Step 2 of 4" text

5. Provide Feedback#

Use haptics and visual feedback to acknowledge user actions.

// On button tap
Mobana.haptic('light');

// On success
Mobana.haptic('success');

// On error
Mobana.haptic('error');

Common Flow Patterns#

Multi-Step Onboarding#

A classic onboarding flow with step indicator:

onboarding.html
<!-- Step indicator -->
<div class="step-indicator">
  <div class="step active" data-step="1"></div>
  <div class="step" data-step="2"></div>
  <div class="step" data-step="3"></div>
</div>

<!-- Step content -->
<div class="step-content" id="step-1">
  <h1>Welcome to MyApp!</h1>
  <p>Let's get you set up in just a few steps.</p>
  <button id="step-1-continue">Continue</button>
</div>

<script>
let currentStep = 1;

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

function showStep(step) {
  // Hide all steps, show target step
  document.querySelectorAll('.step-content').forEach(el => el.style.display = 'none');
  document.getElementById(`step-${step}`).style.display = 'block';
  
  // Update indicator
  document.querySelectorAll('.step').forEach(el => {
    el.classList.toggle('active', parseInt(el.dataset.step) <= step);
  });
  
  currentStep = step;
}
</script>

Permission Request#

The "pre-permission" pattern — explain value before triggering the system dialog:

notification-permission.html
<!-- Permission request pattern -->
<div class="permission-screen">
  <div class="icon">🔔</div>
  <h2>Stay in the loop</h2>
  <p>Get notified about important updates and special offers.</p>
  
  <!-- Explain the value before asking -->
  <ul class="benefits">
    <li>Daily tips to help you succeed</li>
    <li>Exclusive offers just for you</li>
    <li>Important account updates</li>
  </ul>
  
  <button id="enable-btn" class="primary">Enable Notifications</button>
  <button id="skip-btn" class="secondary">Maybe Later</button>
</div>

<script>
document.getElementById('enable-btn').addEventListener('click', async () => {
  Mobana.trackEvent('notification_prompt_accepted');
  
  const granted = await Mobana.requestNotificationPermission();
  
  if (granted) {
    Mobana.trackEvent('notification_permission_granted');
    Mobana.haptic('success');
  } else {
    Mobana.trackEvent('notification_permission_denied');
  }
  
  // Continue regardless of result
  showNextScreen();
});

document.getElementById('skip-btn').addEventListener('click', () => {
  Mobana.trackEvent('notification_prompt_skipped');
  showNextScreen();
});
</script>

This pattern significantly increases permission grant rates because users understand the value before seeing the system dialog.

Personalization#

Use params and attribution to customize the flow:

flow.js
<script>
// Get params passed from the app
const params = Mobana.getParams();
const attribution = Mobana.getAttribution();

// Personalize greeting
const greeting = document.getElementById('greeting');
if (params.userName) {
  greeting.textContent = `Welcome, ${params.userName}!`;
} else {
  greeting.textContent = 'Welcome!';
}

// Show campaign-specific content
if (attribution?.utm_campaign === 'premium_promo') {
  document.getElementById('premium-offer').style.display = 'block';
}

// Adapt for platform
if (Mobana.getPlatform() === 'ios') {
  document.getElementById('ios-specific').style.display = 'block';
}

// Respect color scheme
const colorScheme = Mobana.getColorScheme();
document.body.classList.add(`theme-${colorScheme}`);
</script>

Testing Flows#

  • Preview in Dashboard: Use the flow editor's preview to test on web first.
  • Test on real devices: WebView behavior can differ from desktop browsers.
  • Test both platforms: Check iOS and Android for safe area differences.
  • Test dark mode: Toggle device color scheme and verify your flow adapts.
  • Test permissions: Test with permissions already granted, denied, and blocked.

Performance Tips#

  • Prefetch flows: Call prefetchFlow() during app startup for instant display.
  • Optimize images: Use compressed images and appropriate sizes.
  • Inline critical CSS: Include styles in the HTML to avoid render blocking.
  • Minimize JavaScript: Keep scripts lean; the bridge provides most functionality.

Next Steps#