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:
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:
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.
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
.
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:
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) | Trigger | Key Properties Included |
---|---|---|
flow_started | The OnboardJS engine is initialized and a flow begins. | start_method ('fresh' or 'resumed' ), total_steps , flow_start_time_ms , initial_flow_data_size |
step_active | A 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_completed | The 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_abandoned | User is idle on a step for churnTimeoutMs (if enableChurnDetection: true ). | step_id , step_type , time_on_step_ms |
high_churn_risk | A 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_milestone | User reaches a configured milestonePercentages (e.g., 25%, 50%). | milestone_percentage , actual_progress , steps_completed |
navigation_back | User navigates to a previous step (e.g., calls engine.previous() ). | from_step_id , to_step_id , navigation_type |
navigation_forward | User navigates to a subsequent step via next() (excluding skips/jumps). | from_step_id , to_step_id , navigation_type |
navigation_jump | User navigates non-sequentially (e.g., engine.goToStep() , or skipToStep if not nextStep ). | from_step_id , to_step_id , jump_distance |
error_encountered | An error occurs within the OnboardJS engine. | error_message , error_stack , error_type |
experiment_exposed | User is exposed to a variant of a experimentFlags feature flag. | experiment_flag , variant , user_id |
checklist_item_toggled | A checklist item's completion status is changed. | item_id , checked , step_id |
checklist_progress | The progress of a checklist step changes. | completed_items , total_items , completion_percentage , step_id |
flow_paused | The flow enters a paused state (requires explicit engine support for pausing). | reason |
flow_resumed | The flow resumes from a paused state. | resume_point |
flow_abandoned | The flow is officially marked as abandoned (e.g., via a specific engine call). | abandonment_reason |
flow_reset | The onboarding flow is reset. | reset_reason |
flow_completed | The entire onboarding flow is completed successfully. | completion_time_ms , total_steps , completed_steps , skipped_steps , retried_steps , flow_completion_time_ms |
step_skipped | User skips a step. | step_id , skip_reason |
step_retried | User re-attempts a step (requires explicit engine support for retries). | step_id , retry_count |
step_validation_failed | A step's validation logic fails. | step_id , validation_errors , error_count |
step_help_requested | User requests help on a step (requires custom handling to emit this event). | step_id , help_type |
data_changed | Data within context.flowData changes. (Excluded by default due to high volume; enable with caution). | changed_keys , change_count |
step_render_slow | A step takes longer than performanceThresholds.slowRenderMs to render. | step_id , render_time_ms , threshold_ms , performance_ratio |
persistence_success | Onboarding state is successfully persisted by a DataPersistFn . (Excluded by default). | persistence_time_ms |
persistence_failure | Onboarding state persistence fails. | error_message , error_type |
user_idle | User becomes idle during the onboarding process. | idle_time_ms |
user_returned | User returns after being idle. | away_time_ms |
plugin_error | An 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
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
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 yourflowData
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
: Enabledebug: true
in the plugin config to see verbose logs in your browser console ([MixpanelPlugin] Event captured...
).- Filtering: Check
excludeEvents
orincludeOnlyEvents
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.
- Mixpanel Initialization: Double-check that
- "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.
- Correct Event Names: If you used
- "Plugin Not Loading":
- Mixpanel Instance: Ensure you're passing either a valid
mixpanelInstance
or atoken
to initialize Mixpanel. - Browser Environment: The plugin is designed for browser environments. Server-side rendering might require additional configuration.
- Mixpanel Instance: Ensure you're passing either a valid
🤝 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.