How to migrate from Mixpanel to OpenPanel
Migrating analytics tools sounds painful, but OpenPanel's API closely mirrors Mixpanel's patterns. Most implementations translate with minimal code changes. You'll map your existing events, optionally import historical data, and run both tools in parallel before cutting over.
OpenPanel gives you better privacy controls with cookieless tracking by default, transparent pricing without surprise overages, and the option to self-host. The migration typically takes 1-2 hours for code changes, plus a week or two of parallel tracking to verify data consistency.
Prerequisites
- An existing Mixpanel implementation
- An OpenPanel account (sign up free)
- Access to your Mixpanel project settings for data export
- Access to your application codebase
Export Mixpanel data
Before migrating, you'll want to export your historical data from Mixpanel. This step is optional if you're okay starting fresh, but most teams prefer to preserve their historical events for comparison.
Mixpanel provides an export API that returns events in JSON format. You'll need your API credentials from Project Settings in Mixpanel.
curl https://mixpanel.com/api/2.0/export \
-u YOUR_API_SECRET: \
-d 'from_date=2024-01-01' \
-d 'to_date=2024-12-15' \
-d 'event=["event1","event2"]' \
> mixpanel_export.jsonAlternatively, you can export through Mixpanel's dashboard by navigating to Data Management, then Export. Select your date range and events, then download the file. Keep this export handy for the import step later.
Install OpenPanel SDK
Install the OpenPanel SDK alongside Mixpanel. You'll remove Mixpanel later after verifying the migration.
For web applications, install the web SDK. This handles browser-specific features like automatic page view tracking and outgoing link tracking.
npm install @openpanel/webFor server-side applications or Node.js, use the core SDK instead. This version requires a client secret and is meant for trusted environments.
npm install @openpanel/sdkIf you're using Next.js, there's a dedicated package that handles both client and server tracking with proper component integration. Check the SDK documentation for framework-specific setup.
Map your events
OpenPanel's API follows similar patterns to Mixpanel, with a few naming convention differences. Mixpanel uses Title Case for events and properties, while OpenPanel uses snake_case.
Here's how basic event tracking translates. In Mixpanel, you might track a button click like this:
mixpanel.track('Button Clicked', {
'Button Name': 'Sign Up',
'Button Location': 'Hero'
});The equivalent in OpenPanel uses snake_case naming:
op.track('button_clicked', {
button_name: 'Sign Up',
button_location: 'Hero'
});User identification works similarly, but OpenPanel uses a structured object instead of separate method calls. Mixpanel's pattern splits identify and people.set:
mixpanel.identify('user_123');
mixpanel.people.set({
'$email': 'user@example.com',
'$name': 'John Doe',
'Plan': 'Premium'
});OpenPanel combines this into a single identify call with built-in fields for common properties:
op.identify({
profileId: 'user_123',
email: 'user@example.com',
firstName: 'John',
lastName: 'Doe',
properties: {
plan: 'Premium'
}
});For super properties (global properties that attach to every event), Mixpanel uses register or registerSuperProperties. OpenPanel calls this setGlobalProperties, but the concept is identical:
op.setGlobalProperties({
app_version: '1.0.0',
environment: 'production'
});Incrementing user properties works the same way, just with different method names:
op.increment({
profileId: user.id,
property: 'login_count',
value: 1
});Import historical data
OpenPanel can import your Mixpanel export using the SDK's server-side client. You'll need to transform the Mixpanel format slightly since Mixpanel uses Unix timestamps and different property names.
import { OpenPanel } from '@openpanel/sdk';
const op = new OpenPanel({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
});
const mixpanelEvents = await loadMixpanelExport();
for (const event of mixpanelEvents) {
op.track(event.event, event.properties, {
profileId: event.distinct_id,
timestamp: new Date(event.time * 1000),
});
}For user profiles, map Mixpanel's dollar-prefixed properties to OpenPanel's built-in fields:
const mixpanelUsers = await loadMixpanelUsers();
for (const user of mixpanelUsers) {
op.identify({
profileId: user.distinct_id,
email: user.$email,
firstName: user.$first_name,
lastName: user.$last_name,
properties: {
plan: user.Plan,
signupDate: user['Signup Date'],
},
});
}For large migrations, contact support. OpenPanel has tooling to help with bulk imports.
Run in parallel
Before removing Mixpanel, run both tools simultaneously for 1-2 weeks. This lets you verify that event counts match and user identification is working correctly.
Create a simple wrapper function that sends events to both platforms:
function trackEvent(eventName, properties) {
if (typeof mixpanel !== 'undefined') {
mixpanel.track(eventName, properties);
}
if (op) {
op.track(eventName, properties);
}
}
trackEvent('button_clicked', { button_name: 'Sign Up' });After a week, compare Mixpanel's Live View with OpenPanel's real-time dashboard. Check that event counts are close (they won't be exact due to timing differences), user profiles are being created correctly, and any funnels you've set up show similar conversion rates.
Remove Mixpanel
Once you've verified data consistency, remove the Mixpanel SDK from your project. For npm packages, uninstall the dependency:
npm uninstall mixpanel-browserThen search your codebase for any remaining mixpanel.* calls and replace them with the OpenPanel equivalents. If you were using the wrapper function from the parallel tracking step, you can now remove it and call OpenPanel directly.
op.track('button_clicked', { button_name: 'Sign Up' });Don't forget to remove any Mixpanel script tags if you were loading their SDK via CDN.
Verify your setup
After removing Mixpanel, monitor OpenPanel for a few days to ensure everything is tracking correctly. Check the real-time view to confirm events are flowing, verify that user profiles show the expected properties, and test any funnels or reports you've configured.
If events aren't appearing, double-check that you're using the correct client ID and that the SDK is initialized before any tracking calls. The browser console will show network requests to api.openpanel.dev if tracking is working.
Next steps
The SDK documentation covers advanced features like custom event properties, server-side tracking, and framework-specific integrations. If you're coming from Mixpanel because of pricing concerns, you might also want to explore self-hosting for complete control over your data and costs.
For framework-specific setup instructions, check out our guides:
- Next.js analytics guide for Next.js applications
- React analytics guide for React applications
- Express analytics guide for Express.js applications
- Python analytics guide for Python applications


