Stop Reinventing the Onboarding Wheel. Start Building.

Your users need smooth flows. You need clean code, faster. OnboardJS handles the messy state stuff so that you can focus on building.

WelcomeStep.tsx
stepsConfig.ts
function WelcomeStep() {
const { next } = useOnboarding()
return (
<div>
<button onClick={next}>Next</button>
</div>
)
}

Mixpanel Analytics Plugin

The official Mixpanel analytics plugin for OnboardJS. This plugin seamlessly integrates your OnboardJS flows with Mixpanel, capturing detailed user behavior events, enabling you to build comprehensive funnels, detect churn risks, and optimize your onboarding experience.


Why Mixpanel for Onboarding Analytics?

Did you know that without precise event tracking, you're essentially flying blind through your user onboarding? You won't know exactly where users drop off, what features they engage with first, or which flow variations convert best. This leads to missed opportunities and suboptimal user experiences.

Mixpanel is a powerful product analytics platform that specializes in event-based tracking, user behavior analysis, and conversion optimization—making it an ideal partner for OnboardJS's flexible, headless architecture.

The OnboardJS Mixpanel plugin handles all the complex event capturing and property enrichment, allowing you to focus on analyzing data and iterating on your onboarding strategy.

Key Benefits

  • Automated Event Tracking: Automatically sends detailed events like step_active, step_completed, flow_completed, and more.
  • Identify Drop-off Points: Pinpoint exactly where users are abandoning your onboarding flows using Mixpanel's funnel analysis.
  • Detect Churn Risk: Automated churn detection identifies users who are getting stuck or leaving your flow.
  • A/B Test Flows: Leverage Mixpanel Experiments to run tests and measure the impact of different onboarding variations.
  • Performance Insights: Track step render times to optimize the speed and responsiveness of your onboarding.
  • Privacy-Centric: Options for data sanitization and PII redaction.
  • Reduced Development Effort: No need to manually instrument every button click or step view.

Installation

First, install the plugin package and its peer dependencies:

bash
5 lines
1npm install @onboardjs/core @onboardjs/mixpanel-plugin mixpanel-browser
2# or
3yarn add @onboardjs/core @onboardjs/mixpanel-plugin mixpanel-browser
4# or
5pnpm add @onboardjs/core @onboardjs/mixpanel-plugin mixpanel-browser

Setup & Usage

The Mixpanel Analytics Plugin integrates directly with your OnboardingProvider in @onboardjs/react or directly with the OnboardingEngine in @onboardjs/core.

Before you start:

For Next.js, follow the official Mixpanel Next.js integrations guide to ensure proper initialization.

1. Configure the Plugin

The plugin's configuration options allow you to tailor it to your Mixpanel setup, desired level of detail, and specific tracking needs.

There are two ways to initialize Mixpanel for the OnboardJS Mixpanel Plugin:

  1. Mixpanel Client: You can pass your Mixpanel setup in two ways for the OnboardJS Mixpanel Plugin. - Directly initialize Mixpanel in your app:

    ```typescript import { createMixpanelPlugin } from '@onboardjs/mixpanel-plugin' import mixpanel from 'mixpanel-browser' // Your initialized Mixpanel instance

    // Minimal configuration const basicMixpanelPlugin = createMixpanelPlugin({ mixpanelInstance: mixpanel, // Pass the initialized Mixpanel client debug: process.env.NODE_ENV === 'development', // See logs in console }) - Pass your Mixpanel token typescript import { createMixpanelPlugin } from '@onboardjs/mixpanel-plugin'

    // Minimal configuration const basicMixpanelPlugin = createMixpanelPlugin({ token: process.env.PUBLIC_MIXPANEL_TOKEN, debug: process.env.NODE_ENV === 'development', // See logs in console }) ```

    This basic setup is enough to get started with automatic event tracking. However, you can customize it further to suit your needs.

tsx
70 lines
1// Advanced configuration example
2const advancedMixpanelPlugin = createMixpanelPlugin<YourAppContext>({
3  mixpanelInstance: mixpanel,
4  eventPrefix: 'saas_onboarding_', // All events will be prefixed (e.g., 'saas_onboarding_step_active')
5
6  // Customize specific event names
7  customEventNames: {
8    flowCompleted: 'saas_onboarding_signup_success',
9    stepCompleted: 'onboarding_step_finished',
10  },
11
12  // Enrich all events with global properties
13  globalProperties: {
14    app_version: '1.5.0',
15    onboarding_variant: 'v2',
16    platform: 'web',
17  },
18
19  // Add properties to specific step types
20  stepPropertyEnrichers: {
21    USER_PROFILE: (step, context) => ({
22      profile_form_version: '2024-03-A',
23      is_premium_tier_flow: context.flowData.selectedPlan === 'premium',
24    }),
25    INTEGRATION_CHOICE: (step, context) => ({
26      integrations_shown_count: step.payload.options.length,
27    }),
28  },
29
30  // Control what data is included in events
31  includeUserProperties: true, // Default: true
32  includeFlowData: true, // Default: true
33  includeStepMetadata: true, // Default: true
34  includeSessionData: true, // Includes session ID, page URL, user agent etc.
35  includePerformanceMetrics: true, // Includes step render time, memory usage, navigation time
36
37  // Privacy & Data Filtering
38  excludePersonalData: true, // Automatically redacts common PII like email, name, password
39  excludeFlowDataKeys: ['apiKey', 'sensitiveAuthToken'], // Exclude specific sensitive keys from flowData
40  excludeEvents: ['persistenceSuccess', 'persistenceFailure'], // Exclude certain events from tracking
41
42  // Churn Detection
43  enableChurnDetection: true,
44  churnTimeoutMs: 180000, // 3 minutes idle time before 'step_abandoned' is fired
45  churnRiskThreshold: 0.75, // Threshold for 'high_churn_risk' event (0-1)
46
47  // Progress Milestones
48  enableProgressMilestones: true,
49  milestonePercentages: [20, 50, 80], // Fire 'progress_milestone' at these percentages
50
51  // A/B Testing Integration
52  enableExperimentTracking: true,
53  experimentFlags: ['onboarding-flow-a', 'onboarding-new-ux-test'], // Monitor these feature flags for experiments
54
55  // Performance Thresholds for 'step_render_slow' event
56  performanceThresholds: {
57    slowRenderMs: 1000, // Fire 'step_render_slow' if a step takes >1s to render
58  },
59
60  // User property mapping
61  userPropertyMapper: (user) => ({
62    $email: user.email,
63    $name: user.name,
64    signup_date: user.createdAt,
65    plan: user.subscription?.plan,
66  }),
67
68  // Debugging
69  enableConsoleLogging: true, // Log events to console before sending
70})

2. Add to Your OnboardingProvider (React)

Once configured, pass the mixpanelPlugin instance to the plugins array of your OnboardingProvider.

tsx
27 lines
1// src/components/OnboardingProviderWrapper.tsx
2'use client' // Important for Next.js App Router
3
4import React, { useEffect } from 'react'
5import { OnboardingProvider, OnboardingContext } from '@onboardjs/react'
6import { createMixpanelPlugin } from '@onboardjs/mixpanel-plugin'
7
8export default function OnboardingProviderWrapper({
9  children,
10}: Readonly<{
11  children: React.ReactNode
12}>) {
13  // Create the Mixpanel plugin instance
14  const mixpanelPlugin = createMixpanelPlugin({
15    token: process.env.PUBLIC_MIXPANEL_TOKEN,
16  })
17
18  return (
19    <OnboardingProvider
20      steps={myOnboardingSteps}
21      plugins={[mixpanelPlugin]} // Add the plugin here!
22      // optional: initialContext={{ currentUser: { id: 'user_abc_123' }}}
23    >
24      {children}
25    </OnboardingProvider>
26  )
27}

3. Using with @onboardjs/core (Headless)

If you're using the core OnboardingEngine directly (e.g., in a Node.js backend, a different frontend framework, or for server-side initialization), you can install the plugin directly:

tsx
26 lines
1import { OnboardingEngine } from '@onboardjs/core'
2import { createMixpanelPlugin } from '@onboardjs/mixpanel-plugin'
3import mixpanel from 'mixpanel-browser' // Your initialized Mixpanel client
4
5// Initialize Mixpanel if it hasn't been already (e.g., in a script tag or global init)
6if (typeof window !== 'undefined' && !mixpanel.config) {
7  mixpanel.init('YOUR_MIXPANEL_TOKEN', { debug: true })
8}
9
10const engine = new OnboardingEngine({
11  steps: [], // Your onboarding steps
12  initialContext: {
13    currentUser: { id: 'headless-user-456' }, // Provide initial user context
14  },
15})
16
17// Install the plugin after engine creation
18// Ensure `mixpanel` is initialized before calling createMixpanelPlugin
19engine.use(
20  createMixpanelPlugin({
21    token: process.env.PUBLIC_MIXPANEL_TOKEN,
22  }),
23)
24
25// Don't forget to await engine.ready() before interacting with it
26// await engine.ready();

📊 Automatic Events Captured

The plugin automatically captures a rich set of events to give you a detailed view of your onboarding performance. You can use these to build funnels and insights in Mixpanel.

Event Name (Default)TriggerKey Properties Included
flow_startedThe OnboardJS engine is initialized and a flow begins.start_method ('fresh' or 'resumed'), total_steps, flow_start_time_ms, initial_flow_data_size
step_activeA new step becomes the currentStep in the engine.step_id, step_type, step_index, is_first_step, is_last_step, flow_progress_percentage, previous_step_id
step_completedThe user successfully completes a step (e.g., calls engine.next()).step_id, step_type, step_data (sanitized), flow_progress_percentage, render_time_ms, completion_method
step_abandonedUser is idle on a step for churnTimeoutMs (if enableChurnDetection: true).step_id, step_type, time_on_step_ms
high_churn_riskA user reaches a calculated churn risk score above churnRiskThreshold.step_id, risk_score, time_on_step_ms, back_navigation_count, error_count, idle_time_ms, validation_failures, primary_risk_factor
progress_milestoneUser reaches a configured milestonePercentages (e.g., 25%, 50%).milestone_percentage, actual_progress, steps_completed
navigation_backUser navigates to a previous step (e.g., calls engine.previous()).from_step_id, to_step_id, navigation_type
navigation_forwardUser navigates to a subsequent step via next() (excluding skips/jumps).from_step_id, to_step_id, navigation_type
navigation_jumpUser navigates non-sequentially (e.g., engine.goToStep(), or skipToStep if not nextStep).from_step_id, to_step_id, jump_distance
error_encounteredAn error occurs within the OnboardJS engine.error_message, error_stack, error_type
experiment_exposedUser is exposed to a variant of a experimentFlags feature flag.experiment_flag, variant, user_id
checklist_item_toggledA checklist item's completion status is changed.item_id, checked, step_id
checklist_progressThe progress of a checklist step changes.completed_items, total_items, completion_percentage, step_id
flow_pausedThe flow enters a paused state (requires explicit engine support for pausing).reason
flow_resumedThe flow resumes from a paused state.resume_point
flow_abandonedThe flow is officially marked as abandoned (e.g., via a specific engine call).abandonment_reason
flow_resetThe onboarding flow is reset.reset_reason
flow_completedThe entire onboarding flow is completed successfully.completion_time_ms, total_steps, completed_steps, skipped_steps, retried_steps, flow_completion_time_ms
step_skippedUser skips a step.step_id, skip_reason
step_retriedUser re-attempts a step (requires explicit engine support for retries).step_id, retry_count
step_validation_failedA step's validation logic fails.step_id, validation_errors, error_count
step_help_requestedUser requests help on a step (requires custom handling to emit this event).step_id, help_type
data_changedData within context.flowData changes. (Excluded by default due to high volume; enable with caution).changed_keys, change_count
step_render_slowA step takes longer than performanceThresholds.slowRenderMs to render.step_id, render_time_ms, threshold_ms, performance_ratio
persistence_successOnboarding state is successfully persisted by a DataPersistFn. (Excluded by default).persistence_time_ms
persistence_failureOnboarding state persistence fails.error_message, error_type
user_idleUser becomes idle during the onboarding process.idle_time_ms
user_returnedUser returns after being idle.away_time_ms
plugin_errorAn error occurs within this or another plugin.plugin_name, error_message, error_type, error_stack

Note on Property Inclusion: All events automatically include relevant context properties (like user_properties, flow_data, step_metadata, session_data, performance_metrics) based on your plugin configuration.

Configuration Presets

The plugin comes with pre-configured setups for common use cases:

SaaS Applications

typescript
7 lines
1import { saasConfig, createMixpanelPlugin } from '@onboardjs/mixpanel-plugin'
2
3const mixpanelPlugin = createMixpanelPlugin({
4  ...saasConfig,
5  mixpanelInstance: mixpanel,
6  token: 'your-token', // if not using mixpanelInstance
7})

E-commerce

typescript
10 lines
1import {
2  ecommerceConfig,
3  createMixpanelPlugin,
4} from '@onboardjs/mixpanel-plugin'
5
6const mixpanelPlugin = createMixpanelPlugin({
7  ...ecommerceConfig,
8  mixpanelInstance: mixpanel,
9  token: 'your-token', // if not using mixpanelInstance
10})

🛡️ Privacy & Data Handling

The plugin prioritizes privacy by offering robust configuration options:

  • excludePersonalData: true: Automatically redacts common PII (e.g., email, name, password, token, apiKey, secret) from all event properties.
  • excludeFlowDataKeys: ['key1', 'key2']: Explicitly specify any sensitive keys within your flowData that should never be sent to Mixpanel.
  • sanitizeData: (data) => { /* custom logic */ }: Provides a powerful escape hatch for implementing custom data sanitization before any event is sent to Mixpanel.

Always ensure your data collection practices comply with relevant privacy regulations (e.g., GDPR, CCPA).

⚠️ Troubleshooting

  • "Events Not Appearing in Mixpanel":
    • Mixpanel Initialization: Double-check that mixpanel.init() is called correctly and only once in your client-side application.
    • Token: Verify your Mixpanel project token is correct in your plugin configuration.
    • debug: true: Enable debug: true in the plugin config to see verbose logs in your browser console ([MixpanelPlugin] Event captured...).
    • Filtering: Check excludeEvents or includeOnlyEvents in your plugin configuration—you might be unintentionally filtering out events.
    • Network Tab: Open your browser's network tab and look for requests to Mixpanel endpoints (api.mixpanel.com). It might be that events are being blocked by your browser's or network's ad blocker.
  • "Dashboard Insights Not Showing Data":
    • Correct Event Names: If you used customEventNames, ensure the event names in the dashboard insights match your custom names.
    • Feature Flag/Event Placeholders: For experiments, remember to replace placeholder feature flag names with your actual feature flag keys.
    • Time Range: Adjust the date range filter on your Mixpanel dashboard to ensure it covers when you've been generating events.
  • "Plugin Not Loading":
    • Mixpanel Instance: Ensure you're passing either a valid mixpanelInstance or a token to initialize Mixpanel.
    • Browser Environment: The plugin is designed for browser environments. Server-side rendering might require additional configuration.

🤝 Contributing

This plugin is open-source and contributions are welcome! If you have ideas for improvements, new features, or encounter any issues, please check the plugin's GitHub repository.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.