diff --git a/docs/content/scripts/mixpanel.md b/docs/content/scripts/mixpanel.md
new file mode 100644
index 00000000..7a359f59
--- /dev/null
+++ b/docs/content/scripts/mixpanel.md
@@ -0,0 +1,112 @@
+---
+
+title: Mixpanel
+description: Use Mixpanel in your Nuxt app.
+links:
+- label: Source
+ icon: i-simple-icons-github
+ to: https://github.com/nuxt/scripts/blob/main/src/runtime/registry/mixpanel-analytics.ts
+ size: xs
+
+---
+
+[Mixpanel](https://mixpanel.com) is a product analytics platform that helps you understand how users interact with your application through event tracking, funnels, and retention analysis.
+
+Nuxt Scripts provides a registry script composable [`useScriptMixpanelAnalytics()`](/scripts/mixpanel){lang="ts"} to easily integrate Mixpanel in your Nuxt app.
+
+::script-stats
+::
+
+::script-docs
+::
+
+::script-types
+::
+
+## Composable Usage
+
+The simplest way to load Mixpanel is through `nuxt.config`:
+
+```ts
+export default defineNuxtConfig({
+ scripts: {
+ registry: {
+ mixpanelAnalytics: {
+ token: 'YOUR_PROJECT_TOKEN',
+ }
+ }
+ }
+})
+```
+
+### Tracking Events
+
+```vue
+
+```
+
+### Identifying Users
+
+```vue
+
+```
+
+### Registering Super Properties
+
+Super properties are sent with every subsequent event:
+
+```vue
+
+```
+
+### Environment Variables
+
+```ts [nuxt.config.ts]
+export default defineNuxtConfig({
+ scripts: {
+ registry: {
+ mixpanelAnalytics: true,
+ }
+ },
+ runtimeConfig: {
+ public: {
+ scripts: {
+ mixpanelAnalytics: {
+ token: '', // NUXT_PUBLIC_SCRIPTS_MIXPANEL_ANALYTICS_TOKEN
+ },
+ },
+ },
+ },
+})
+```
+
+```text [.env]
+NUXT_PUBLIC_SCRIPTS_MIXPANEL_ANALYTICS_TOKEN=YOUR_PROJECT_TOKEN
+```
diff --git a/src/module.ts b/src/module.ts
index 9a7755ea..ea42b1f7 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -166,6 +166,7 @@ const PARTYTOWN_FORWARDS: Record = {
umami: ['umami', 'umami.track'],
matomo: ['_paq.push'],
segment: ['analytics', 'analytics.track', 'analytics.page', 'analytics.identify'],
+ mixpanelAnalytics: ['mixpanel', 'mixpanel.track', 'mixpanel.identify', 'mixpanel.people.set', 'mixpanel.reset', 'mixpanel.register'],
metaPixel: ['fbq'],
xPixel: ['twq'],
tiktokPixel: ['ttq.track', 'ttq.page', 'ttq.identify'],
diff --git a/src/registry-types.json b/src/registry-types.json
index 702874e3..0d72bb6d 100644
--- a/src/registry-types.json
+++ b/src/registry-types.json
@@ -577,6 +577,18 @@
"code": "interface RybbitQueueState {\n queue: Array<[string, ...any[]]>\n flushed: boolean\n}"
}
],
+ "mixpanel-analytics": [
+ {
+ "name": "MixpanelAnalyticsOptions",
+ "kind": "const",
+ "code": "export const MixpanelAnalyticsOptions = object({\n /**\n * Your Mixpanel project token.\n * @see https://docs.mixpanel.com/docs/tracking-methods/sdks/javascript#1-initialize-the-library\n */\n token: string(),\n})"
+ },
+ {
+ "name": "MixpanelAnalyticsApi",
+ "kind": "interface",
+ "code": "export interface MixpanelAnalyticsApi {\n mixpanel: {\n track: (event: string, properties?: Record) => void\n identify: (distinctId: string) => void\n reset: () => void\n people: {\n set: (properties: Record) => void\n }\n register: (properties: Record) => void\n init: (token: string, config?: Record) => void\n }\n}"
+ }
+ ],
"segment": [
{
"name": "SegmentOptions",
diff --git a/src/registry.ts b/src/registry.ts
index ab6073b4..167a384c 100644
--- a/src/registry.ts
+++ b/src/registry.ts
@@ -122,6 +122,16 @@ export async function registry(resolve?: (path: string, opts?: ResolvePathOption
from: await resolve('./runtime/registry/segment'),
},
},
+ {
+ label: 'Mixpanel',
+ src: 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js',
+ category: 'analytics',
+ logo: ``,
+ import: {
+ name: 'useScriptMixpanelAnalytics',
+ from: await resolve('./runtime/registry/mixpanel-analytics'),
+ },
+ },
{
label: 'Meta Pixel',
proxy: 'metaPixel',
diff --git a/src/runtime/registry/mixpanel-analytics.ts b/src/runtime/registry/mixpanel-analytics.ts
new file mode 100644
index 00000000..4c52c89a
--- /dev/null
+++ b/src/runtime/registry/mixpanel-analytics.ts
@@ -0,0 +1,69 @@
+import type { RegistryScriptInput } from '#nuxt-scripts/types'
+import { useRegistryScript } from '../utils'
+import { MixpanelAnalyticsOptions } from './schemas'
+
+export { MixpanelAnalyticsOptions }
+
+export type MixpanelAnalyticsInput = RegistryScriptInput
+
+export interface MixpanelAnalyticsApi {
+ mixpanel: {
+ track: (event: string, properties?: Record) => void
+ identify: (distinctId: string) => void
+ reset: () => void
+ people: {
+ set: (properties: Record) => void
+ }
+ register: (properties: Record) => void
+ init: (token: string, config?: Record) => void
+ }
+}
+
+declare global {
+ interface Window {
+ mixpanel: MixpanelAnalyticsApi['mixpanel']
+ }
+}
+
+const methods = ['track', 'identify', 'reset', 'register'] as const
+const peopleMethods = ['set'] as const
+
+export function useScriptMixpanelAnalytics(_options?: MixpanelAnalyticsInput) {
+ return useRegistryScript('mixpanelAnalytics', (options) => {
+ return {
+ scriptInput: {
+ src: 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js',
+ },
+ schema: import.meta.dev ? MixpanelAnalyticsOptions : undefined,
+ scriptOptions: {
+ use() {
+ return {
+ mixpanel: window.mixpanel,
+ }
+ },
+ },
+ clientInit: import.meta.server
+ ? undefined
+ : () => {
+ window.mixpanel = window.mixpanel || [] as any
+ for (const method of methods) {
+ (window.mixpanel as any)[method] = (window.mixpanel as any)[method] || ((...args: any[]) => {
+ (window.mixpanel as any).push([method, ...args])
+ })
+ }
+ window.mixpanel.people = window.mixpanel.people || {} as any
+ for (const method of peopleMethods) {
+ (window.mixpanel.people as any)[method] = (window.mixpanel.people as any)[method] || ((...args: any[]) => {
+ (window.mixpanel as any).push([`people.${method}`, ...args])
+ })
+ }
+ window.mixpanel.init = window.mixpanel.init || ((...args: any[]) => {
+ (window.mixpanel as any).push(['init', ...args])
+ })
+ if (options?.token) {
+ window.mixpanel.init(options.token)
+ }
+ },
+ }
+ }, _options)
+}
diff --git a/src/runtime/registry/schemas.ts b/src/runtime/registry/schemas.ts
index 94c8b471..12687c48 100644
--- a/src/runtime/registry/schemas.ts
+++ b/src/runtime/registry/schemas.ts
@@ -716,6 +716,14 @@ export const RybbitAnalyticsOptions = object({
apiKey: optional(string()),
})
+export const MixpanelAnalyticsOptions = object({
+ /**
+ * Your Mixpanel project token.
+ * @see https://docs.mixpanel.com/docs/tracking-methods/sdks/javascript#1-initialize-the-library
+ */
+ token: string(),
+})
+
export const SegmentOptions = object({
/**
* Your Segment write key.