Skip to main content
WebReactMixpanel

Type-safe Mixpanel events in React

Stop shipping typos as new Mixpanel events. Define your tracking plan in Ordaze, generate a typed TypeScript wrapper around mixpanel-browser, and run the scanner in CI to catch any drift before it reaches production.

Mixpanel's JavaScript SDK hands you a single, stringly-typed method: mixpanel.track(eventName, properties). That is fine for a prototype. In a React app with real traffic it means every new event is a naming decision made under pressure inside a feature branch, and every analytics-powered dashboard depends on those strings staying stable forever.

The fix is a small indirection. Instead of calling Mixpanel directly from your components, call a thin typed wrapper whose shape is derived from your tracking plan. Ordaze generates that wrapper for you in TypeScript, and the scanner statically verifies that every tracking call in your React source matches the plan.

The Mixpanel SDK

This guide assumes you are installing the official Mixpanel SDK. The typed wrapper Ordaze generates sits on top of it and calls into it directly. You are not replacing your analytics provider, just adding a type-safe layer.

npm install mixpanel-browser

Setup in 5 steps

  1. 1

    Install Mixpanel and initialize it in a client component

    Add the official Mixpanel browser SDK and initialize it once, typically in a top-level provider component. Initialization has to happen on the client, so if you are on Next.js App Router this needs the "use client" directive.

    npm install mixpanel-browser
    npm install --save-dev @types/mixpanel-browser
  2. 2

    Define your events in Ordaze

    Create a new tracking plan or open an existing one. Add events with typed properties, required properties are enforced at the type level in the generated code.

  3. 3

    Generate the TypeScript wrapper

    From the Ordaze dashboard, export the TypeScript codegen for Mixpanel. You get a single file with a typed method per event, each calling mixpanel.track under the hood.

    // Generated: src/analytics/events.ts
    import mixpanel from 'mixpanel-browser';
    
    export const track = {
      signUpCompleted: (props: { plan: 'free' | 'pro' | 'enterprise'; referrer?: string }) => {
        mixpanel.track('Sign Up Completed', props);
      },
      // ... one method per event
    };
  4. 4

    Replace raw mixpanel.track calls with the typed wrapper

    Search your codebase for mixpanel.track( and replace with the typed method. IDE autocomplete now guides every new call. TypeScript errors catch missing required properties at build time.

    // Before
    mixpanel.track('Sign Up Completed', { plan: 'pro' });
    
    // After
    track.signUpCompleted({ plan: 'pro' });
  5. 5

    Add the Ordaze scanner to CI

    Install @ordaze/scanner and run it as a GitHub Action on every pull request. The scanner reads your React source, finds every analytics call, and fails the build when a call does not match the plan.

    # .github/workflows/scan.yml
    - uses: ordaze/scanner-action@v1
      with:
        project-id: ${{ secrets.ORDAZE_PROJECT_ID }}

Before and after

Before

Untyped, every call is a string literal a human typed

function SignUpButton({ plan }: { plan: string }) {
  return (
    <button
      onClick={() => {
        mixpanel.track('Sign Up Complete', { Plan: plan });
        //             ^ typo: should be 'Completed'
        //                                  ^ wrong case: vs 'plan'
      }}
    >
      Sign up
    </button>
  );
}
After

Typed, the shape comes from the tracking plan

import { track } from '@/analytics/events';

function SignUpButton({ plan }: { plan: 'free' | 'pro' | 'enterprise' }) {
  return (
    <button
      onClick={() => {
        track.signUpCompleted({ plan });
        // TypeScript error if plan is missing or a string like 'starter'
      }}
    >
      Sign up
    </button>
  );
}

React + Mixpanel gotchas

Do not initialize Mixpanel inside a useEffect

React's Strict Mode runs effects twice in development. Mixpanel will complain about double initialization and, more importantly, you will double-send events fired during the second mount. Initialize at module scope or inside a one-shot check on window.mixpanel.

Turn off autotrack to avoid double-counting

Mixpanel's autotrack feature fires its own events on clicks and form submits. If you also call track.buttonClicked() explicitly, you end up with two events per click, reported under different names. Disable autotrack in mixpanel.init and track explicitly.

Server components cannot call mixpanel-browser

If you are on Next.js App Router, mixpanel-browser fails in a Server Component because window is undefined. Either use a client component for the tracking call, or send the event server-side via the HTTP API from a Server Action.

React events fire before navigation completes

Tracking a button click inside onClick runs before any navigation the handler triggers. If the event needs the destination URL, capture it before calling track, or use a route change listener instead.

Why Ordaze for this combo

Not a Mixpanel replacement

The generated wrapper still calls mixpanel.track under the hood. You keep the Mixpanel SDK, the Mixpanel dashboard, and every Mixpanel feature. Ordaze is a layer on top, not a switch you flip.

One schema, thirteen languages

The same tracking plan feeds React, Swift, Kotlin, Python, and ten more targets. Your iOS team and your web team call the same conceptual event, with types generated natively for each.

Static drift detection

The scanner reads your TypeScript source without running it. It flags calls where the event name or properties drifted from the plan, and it runs in CI before you merge.

Frequently asked questions

No. The generated wrapper imports mixpanel-browser and calls mixpanel.track inside each method. You keep the SDK, the project, and every Mixpanel feature. Ordaze adds the typed layer above it.
You re-run codegen (or let it run in CI on plan changes). A new typed method appears in events.ts, with the exact properties you defined. Existing call sites are unaffected; you can adopt the new method at your own pace.
Yes. The generated wrapper is a regular TypeScript module. Call it from any client component. For server-side events, use Ordaze's codegen for the Mixpanel HTTP API from a Server Action or Route Handler.
You can migrate incrementally. Ordaze's codegen produces the same shape (typed methods, typed properties). Point new code at the Ordaze-generated file and phase out the old generator at your own pace.
Data Definitions is Mixpanel's internal schema layer. It validates events after they arrive, which means a typo ships to users and appears in your Mixpanel project before anyone notices. Ordaze validates the source code itself, in CI, before the event is ever fired.

Keep reading

Typed Mixpanel events in a weekend

Free plan includes 100 events, unlimited team members, and full TypeScript codegen. No credit card.

Get Started Free