Claude Code for Mixpanel: Product Analytics and Funnels — Claude Skills 360 Blog
Blog / AI / Claude Code for Mixpanel: Product Analytics and Funnels
AI

Claude Code for Mixpanel: Product Analytics and Funnels

Published: July 24, 2027
Read time: 5 min read
By: Claude Skills 360

Mixpanel delivers product analytics with funnels, retention, and user profiles — mixpanel.init(token, { persistence: "localStorage", track_pageview: false }) initializes. mixpanel.identify(userId) merges anonymous events with the user’s profile. mixpanel.people.set({ $email, $name, plan, createdAt }) updates the user profile in Mixpanel People. mixpanel.track("Button Clicked", { buttonName, page, variant }) fires an event. mixpanel.time_event("Checkout") starts a timer — the next mixpanel.track("Checkout") call auto-appends $duration. Super properties: mixpanel.register({ plan, environment }) attaches to every subsequent event automatically. mixpanel.track_links("#nav a", "Nav Link Clicked") auto-tracks all anchor clicks. Group analytics (B2B): mixpanel.set_group("company", companyId) and mixpanel.get_group("company", companyId).set({ name, plan }). Server-side Node.js: const Mixpanel = require("mixpanel"), const mp = Mixpanel.init(token), mp.track("event", { distinct_id: userId, ...properties }), mp.people.set(userId, traits). mixpanel.alias(newId, oldId) links anonymous → identified. Claude Code generates Mixpanel event tracking, user profiles, and server-side analytics pipelines.

CLAUDE.md for Mixpanel

## Mixpanel Stack
- Browser version: mixpanel-browser >= 2.55
- Server version: mixpanel >= 0.18 (Node.js)
- Browser init: mixpanel.init(process.env.NEXT_PUBLIC_MIXPANEL_TOKEN!, { persistence: "localStorage", track_pageview: false })
- Identify: mixpanel.identify(userId) — call after login
- Profile: mixpanel.people.set({ $email, $name, plan }) — $ prefix = Mixpanel reserved properties
- Track: mixpanel.track("Event Name", { prop1: value, prop2: value2 })
- Duration: mixpanel.time_event("Video Watched"); later: mixpanel.track("Video Watched") — adds $duration
- Super props: mixpanel.register({ plan, version }) — appended to every event silently
- Reset: mixpanel.reset() — call on sign-out to clear identity

Typed Mixpanel Client

// lib/mixpanel/client.ts — typed Mixpanel browser analytics
import mixpanel from "mixpanel-browser"

let initialized = false

export function initMixpanel() {
  if (initialized || typeof window === "undefined") return
  mixpanel.init(process.env.NEXT_PUBLIC_MIXPANEL_TOKEN!, {
    persistence: "localStorage",
    track_pageview: false,        // We fire page events manually for SPA accuracy
    ignore_dnt: false,
    batch_requests: true,
    batch_flush_interval_ms: 2000,
    debug: process.env.NODE_ENV === "development",
  })
  initialized = true
}

// ── Typed event catalog ────────────────────────────────────────────────────

type EventMap = {
  "Page Viewed":          { pageName: string; path: string; referrer?: string }
  "Button Clicked":       { buttonName: string; page: string; variant?: string }
  "Form Submitted":       { formName: string; success: boolean }
  "Feature Used":         { feature: string; context?: string }
  "Subscription Started": { plan: string; billing: "monthly" | "annual"; amount: number }
  "Subscription Cancelled": { plan: string; reason?: string; daysActive: number }
  "Search Performed":     { query: string; resultCount: number; category?: string }
  "Video Played":         { videoId: string; videoTitle: string }
  "Error Occurred":       { errorCode: string; errorMessage: string; page: string }
}

type EventName = keyof EventMap

export function track<E extends EventName>(event: E, properties: EventMap[E]): void {
  if (!initialized) return
  mixpanel.track(event, properties as Record<string, unknown>)
}

export function identifyUser(
  userId: string,
  profile: {
    email?:     string
    name?:      string
    plan?:      string
    createdAt?: string
    company?:   string
  } = {},
): void {
  if (!initialized) return
  mixpanel.identify(userId)
  if (Object.keys(profile).length > 0) {
    mixpanel.people.set({
      $email:     profile.email,
      $name:      profile.name,
      plan:       profile.plan,
      createdAt:  profile.createdAt,
      company:    profile.company,
    })
  }
}

export function setGroup(groupName: string, groupId: string, traits: Record<string, unknown> = {}): void {
  if (!initialized) return
  mixpanel.set_group(groupName, groupId)
  if (Object.keys(traits).length > 0) {
    mixpanel.get_group(groupName, groupId).set(traits)
  }
}

export function setSuperProperties(props: Record<string, string | number | boolean>): void {
  if (!initialized) return
  mixpanel.register(props)
}

/** Start timing an event — call before the action, track after */
export function timeEvent(eventName: EventName): void {
  if (!initialized) return
  mixpanel.time_event(eventName)
}

/** Increment a People counter (e.g. total orders) */
export function incrementPeopleProperty(property: string, value = 1): void {
  if (!initialized) return
  mixpanel.people.increment({ [property]: value })
}

export function resetIdentity(): void {
  if (!initialized) return
  mixpanel.reset()
}

React Analytics Hook

// hooks/useAnalytics.ts — convenient React analytics interface
"use client"
import { useCallback } from "react"
import { track, timeEvent, type EventMap } from "@/lib/mixpanel/client"

type EventName = keyof EventMap

export function useAnalytics() {
  const trackEvent = useCallback(
    <E extends EventName>(event: E, properties: EventMap[E]) => {
      track(event, properties)
    },
    [],
  )

  const startTimer = useCallback((event: EventName) => {
    timeEvent(event)
  }, [])

  return { trackEvent, startTimer }
}

// Usage:
// const { trackEvent } = useAnalytics()
// <button onClick={() => trackEvent("Button Clicked", { buttonName: "Upgrade", page: "/pricing" })}>
//   Upgrade
// </button>

Next.js Analytics Provider

// components/MixpanelProvider.tsx — init + page views + user identity
"use client"
import { useEffect } from "react"
import { usePathname } from "next/navigation"
import { initMixpanel, identifyUser, track, setSuperProperties } from "@/lib/mixpanel/client"

type Props = {
  userId?:   string
  userEmail?: string
  userName?:  string
  userPlan?:  string
  children:  React.ReactNode
}

export default function MixpanelProvider({
  userId,
  userEmail,
  userName,
  userPlan,
  children,
}: Props) {
  const pathname = usePathname()

  // Initialize once
  useEffect(() => {
    initMixpanel()
    if (userId) {
      identifyUser(userId, { email: userEmail, name: userName, plan: userPlan })
    }
    setSuperProperties({
      environment: process.env.NODE_ENV ?? "development",
      appVersion:  process.env.NEXT_PUBLIC_APP_VERSION ?? "0.0.0",
    })
  }, [userId, userEmail, userName, userPlan])

  // Page views
  useEffect(() => {
    track("Page Viewed", {
      pageName: document.title,
      path:     pathname,
      referrer: document.referrer,
    })
  }, [pathname])

  return <>{children}</>
}

Server-Side Node.js Tracking

// lib/mixpanel/server.ts — server-side Mixpanel for backend events
import Mixpanel from "mixpanel"

const mp = Mixpanel.init(process.env.MIXPANEL_TOKEN!, {
  host: "api.mixpanel.com",
  protocol: "https",
  verbose: process.env.NODE_ENV === "development",
})

export async function serverTrack(
  userId: string,
  event: string,
  properties: Record<string, unknown> = {},
  ip?: string,
): Promise<void> {
  return new Promise((resolve, reject) => {
    mp.track(event, { distinct_id: userId, ip, ...properties }, (err) => {
      if (err) reject(err)
      else resolve()
    })
  })
}

export async function serverPeopleSet(
  userId: string,
  traits: Record<string, unknown>,
): Promise<void> {
  return new Promise((resolve, reject) => {
    mp.people.set(userId, traits, (err) => {
      if (err) reject(err)
      else resolve()
    })
  })
}

// app/api/checkout/route.ts usage:
// await serverTrack(session.userId, "Checkout Completed", { revenue: amount, plan })
// await serverPeopleSet(session.userId, { plan, lastPaymentAt: new Date().toISOString() })

For the Amplitude alternative when needing Amplitude’s Charts, user-level behavioral cohorts, Amplitude Experiment A/B testing with statistical significance calculations, or the Amplitude CDP for reverse ETL — Amplitude has a more sophisticated statistical analysis layer while Mixpanel is often preferred for its simpler event-based querying and JQL (JavaScript Query Language) for custom reports, see the Amplitude guide. For the PostHog alternative when needing an open-source, self-hostable product analytics tool that combines Mixpanel-like funnels with session recording, feature flags, and experiments in one platform — PostHog is the full-stack open-source alternative to Mixpanel with no per-event pricing on the self-hosted tier, see the PostHog guide. The Claude Skills 360 bundle includes Mixpanel skill sets covering event tracking, user profiles, and server-side analytics. Start with the free tier to try product analytics generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free