← All posts
·10 min read

Claude Code with Mixpanel: Events, People, and Funnels

Claude CodeMixpanelProduct AnalyticsTracking
Claude Code with Mixpanel: events, people, and funnels

Why Mixpanel without CLAUDE.md ships broken funnels

Mixpanel is event-based product analytics. The model is simple in theory: track named events, attach properties, identify users when they log in, and the funnels and retention charts compose out of the resulting event stream. The model is exacting in practice. distinct_id stability, identify semantics, super properties, and people profile updates all need to be wired correctly or the reports lie quietly.

Claude Code does not know your tracking conventions unless you tell it. Without a CLAUDE.md in place, Claude invents event names per-feature. It calls identify before alias, breaking the anonymous-to-identified merge. It uses people.set when people.set_once was correct, overwriting first-touch attribution on every login. It puts user attributes in event properties instead of people profiles, scattering the same data across thousands of events. It hardcodes the project token in client code without scoping the calls to the right environment.

This guide gives you the CLAUDE.md configuration that anchors Claude Code to how Mixpanel actually works: distinct_id stable across the anonymous/identified boundary, identify and alias used correctly, super properties for cross-event context, people profiles for user state, and the import API for backfills. If you are comparing product analytics, Claude Code with PostHog covers the open-source alternative.

The Mixpanel CLAUDE.md template

The CLAUDE.md at your project root is read at the start of every Claude Code session. For a Mixpanel project it needs to declare: the event taxonomy, the distinct_id strategy, the identify/alias flow, the super properties list, the people profile rules, and the import path for historical data.

# Mixpanel rules

## Stack
- mixpanel-browser (web) or mixpanel SDK matching the runtime
- Project token in env vars , server token separate from client token
- Events follow the taxonomy in /tracking/events.json
- People profiles follow the schema in /tracking/people.json

## Event naming (STRICT)
- Title Case with spaces , 'Order Completed' not 'orderCompleted' or 'order_completed'
- Verb-Object structure , 'Subscription Created' not 'Created Subscription'
- Past tense , 'Item Added to Cart' not 'Item Adding'
- NEVER duplicate event names with different semantics

## Property naming (STRICT)
- snake_case for property names , 'order_id' not 'orderId' or 'OrderId'
- Reserved properties start with $ , '$current_url', '$device_id'
- Currency: amount as integer minor units, currency_code as ISO 4217
- Timestamps: ISO 8601 strings, NEVER epoch numbers

## distinct_id rules (CRITICAL)
- Anonymous users get a UUID stored in localStorage on first visit
- On signup/signin call mixpanel.identify(user.id) , do NOT call alias here in v2.0+
- v2.0+ : identify handles the anonymous-to-known merge automatically
- v1.x  : call alias once per merge, then identify on subsequent visits
- NEVER call identify with different IDs across a session without a logout

## identify vs alias (version-dependent)
- mixpanel-browser >= 2.0 : identify only, alias is deprecated
- mixpanel-browser < 2.0  : alias on first signup, identify on every login
- Server SDK: identify with the user_id, distinct_id from cookie

## Super properties
- Set ONCE per session , persist across events automatically
- mixpanel.register({...}) for permanent supers (registered for the session)
- mixpanel.register_once({...}) for first-touch only (does NOT overwrite)
- NEVER set super properties that change frequently (timestamps, request_id)

## People profile rules
- mixpanel.people.set({...})       , update or create field
- mixpanel.people.set_once({...})  , first-touch only, never overwrite
- mixpanel.people.increment({...}) , numeric counters
- mixpanel.people.append({...})    , list operations
- ALWAYS use set_once for signup_date, first_referrer, original_utm

## Group analytics (B2B)
- mixpanel.set_group('company_id', value) , attach group
- mixpanel.get_group('company_id', value).set({...}) , update group profile
- Group ID must be stable , never use the company name (renames break tracking)

## Server-side tracking
- Mixpanel Node SDK with the project secret, never the project token in browser
- ALWAYS pass distinct_id explicitly , the SDK does not infer
- ALWAYS set $ip = '0' on server events if you don't want IP-based geolocation
- For backfills use the import API, not the track API

## Cohort sync
- Cohorts sync via webhooks or destination integrations
- Cohort membership is computed by Mixpanel, never replicated in app code
- Use messaging integrations for downstream activation, not custom webhooks

Drop this into CLAUDE.md, adjust the version-dependent rules to match your installed SDK, and let Claude generate against it. The distinct_id rules are the most error-prone area.

Event naming and the cost of inconsistency

Mixpanel events are case-sensitive and exact-match. Order Completed and order_completed are two different events. User Signed Up and Signup are two different events. Charts, funnels, and cohorts all reference the exact event name. Once a name is in use, renaming it requires either backfilling old events to the new name or maintaining a transformation layer.

Claude defaults to whatever case convention is dominant in the immediate code context. If the surrounding code is camelCase, Claude writes orderCompleted. If it is snake_case, Claude writes order_completed. Mixpanel's house style is Title Case with spaces, and the CLAUDE.md rule "Title Case with spaces" plus the structural rule "Verb-Object structure" is what aligns Claude with the platform default. Without the rule, you end up with three case styles in your Mixpanel project and dashboards that miss events.

The taxonomy file at /tracking/events.json is where the actual list lives. Claude reads it before adding any new event. The principle is the same as the RudderStack tracking plan, with Mixpanel-specific naming conventions on top.

distinct_id and the anonymous-to-identified boundary

The single most error-prone area in any Mixpanel integration is the merge of anonymous and identified users. The user visits the site anonymously, Mixpanel assigns a UUID and stores it as the distinct_id. The user signs up. From that moment onwards, events should be attributed to the user_id, with the prior anonymous events also linked to the same person.

In mixpanel-browser 2.0 and later, mixpanel.identify(user.id) handles this merge automatically. In 1.x, you needed to call mixpanel.alias(user.id) once on signup and then mixpanel.identify(user.id) on subsequent visits. Many SDK migrations were silent: Claude generates the v1.x pattern against the v2.0 SDK, the alias call is a no-op, the merge never happens, and the anonymous events orphan.

The CLAUDE.md rule "mixpanel-browser >= 2.0 : identify only, alias is deprecated" is the line that catches this. The version-aware split tells Claude which pattern to generate for which SDK. Without it, Claude reaches for the older pattern because the older pattern dominates the training data.

Get Claudify. Skills, hooks, and CLAUDE.md templates that make Claude Code wire Mixpanel correctly the first time.

Super properties and the cross-event context problem

Super properties are properties registered once and automatically attached to every subsequent event. mixpanel.register({ plan: 'pro' }) means every event from this session carries plan: 'pro' without the calling code remembering to pass it. The result is shorter track calls and consistent context across events.

The pitfall is registering things that change frequently. Registering the current timestamp as a super property means every event gets the same timestamp, which is meaningless. Registering the request_id means subsequent events carry the previous request's ID. Registering volatile state defeats the purpose of super properties.

The CLAUDE.md rule "NEVER set super properties that change frequently" is the line that prevents this. The companion rule "Set ONCE per session" is the positive guidance. Stable session attributes (plan, role, account_id, locale) belong in super properties. Event-specific attributes (order_id, item_count, page_url) belong in the event properties for that specific event.

Goes in super properties Goes in event properties Goes in people profile
plan, role, account_id order_id, item_count email, name, plan
locale, app_version page_url, button_label signup_date, last_active
ab_test_variant search_query, filter_set total_spend, ltv
feature_flag_states source, destination preferred_currency

People profiles and the set vs set_once distinction

People profiles are the per-user record in Mixpanel. They are separate from events. mixpanel.people.set({...}) updates or creates the field. mixpanel.people.set_once({...}) only updates if the field has never been set. The distinction matters for first-touch attribution.

signup_date should be set_once. The original referrer should be set_once. The original utm_source should be set_once. Setting them with set instead overwrites them on every login, which destroys the first-touch attribution. Mixpanel funnels and cohorts that segment by "users who arrived via X" stop working once the original referrer is overwritten with the most recent referrer.

The CLAUDE.md rule "ALWAYS use set_once for signup_date, first_referrer, original_utm" is the line that locks Claude into the correct semantics. The companion rule "people.increment for numeric counters" is what stops Claude from inventing a manual read-modify-write pattern for "total_sessions" or "total_purchases," which races under concurrent traffic.

Server-side tracking and the import API

The Mixpanel Node SDK is the path for server-side tracking. The server needs the project secret, not the project token. The secret is for the import API and the people API. The token alone cannot backfill or update people profiles via the secure paths.

The CLAUDE.md rule "ALWAYS pass distinct_id explicitly" matters because the server SDK does not have access to localStorage or cookies. The caller has to supply the distinct_id, usually pulled from a cookie or session store, and pass it to every track and people.set call. Claude defaults to omitting it and Mixpanel then drops the event because there is no way to attribute it.

For historical data, the import API is the right path. The track API rate-limits and enforces freshness windows; events older than five days do not show up in the dashboards. The import API accepts events up to five years old and handles the bulk path. Claude needs the rule "For backfills use the import API, not the track API" to default to the right endpoint when the prompt is "backfill these orders into Mixpanel."

Cohort sync and the activation question

Mixpanel cohorts are computed in the Mixpanel platform. Membership updates as users qualify or disqualify. The sync pattern depends on where the cohort needs to land. For email or push activation, the built-in messaging integrations (Braze, Iterable, OneSignal, Customer.io) consume the cohort directly via the destination integrations. For ad audiences, the Facebook, Google, and TikTok integrations push the cohort as a custom audience.

The CLAUDE.md rule "Cohort membership is computed by Mixpanel, never replicated in app code" stops Claude from rebuilding cohort logic in the app. The pattern is wrong even when it looks tractable, because the cohort definition can change in Mixpanel without the app knowing, and the app-side implementation drifts. The right pattern is webhooks or integrations from Mixpanel to the activation tool.

Verifying Claude's Mixpanel integration before it ships

A CLAUDE.md is necessary but not sufficient. The verification loop runs against the Mixpanel Live View. The check is:

  1. Generate the instrumentation with Claude
  2. Trigger the event in a development environment with the dev project token
  3. Inspect the Live View for arrival, event name, and property shape
  4. Inspect the user's People profile for trait updates
  5. Run a sample funnel with the new event included and confirm step-through

A hook that pings the Live View API after every change and surfaces the most recent event back to Claude tightens the loop further. For broader hook patterns, Claude Code skills covers how to package the verification loop. Claude Code best practices covers CLAUDE.md structure across stacks.

EU residency and the data-locality question

Mixpanel has an EU residency offering. The SDK initialisation accepts an api_host parameter that points the events at the EU endpoint. Without the parameter, events go to the US datacenter. For GDPR-sensitive deployments, the CLAUDE.md should flag this: "For EU residency set api_host to api-eu.mixpanel.com on init."

Claude does not know which region your project lives in unless you tell it. The default initialisation pulls the events to the US, which is fine for most cases and the wrong call for GDPR-regulated ones. Codifying the region in CLAUDE.md prevents the silent default.

Wrapping up

Mixpanel rewards consistency. Event names that follow a convention, distinct_id that tracks anonymous-to-identified merges correctly, super properties used for stable context, people profiles for user state with set_once for first-touch fields, and the import API for backfills.

Claude Code without a CLAUDE.md gets each of these wrong in a different way. Event names drift across features. The identify/alias flow breaks the merge. Super properties register volatile state. People profile updates overwrite first-touch attribution. The dashboards then lie quietly, because Mixpanel does not error when the wiring is wrong, it just produces reports that miss data.

With the template above, Claude Code generates Mixpanel integrations that the platform was designed to receive, and the funnels, retention charts, and cohorts produce the answers the data actually supports.

Get Claudify. Skills, hooks, and CLAUDE.md templates that make Claude Code wire Mixpanel correctly the first time.

More like this

Ready to upgrade your Claude Code setup?

Get Claudify
Featured on Dofollow.Tools AI Toolz Dir Claudify - Featured on Startup Fame