Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2127d33
feat(registry): add PostHog analytics script
harlan-zw Dec 20, 2025
d43a233
fix(posthog): use window for state instead of module-level vars
harlan-zw Dec 20, 2025
f2431cf
fix(posthog): use() waits for init promise
harlan-zw Dec 20, 2025
a16be2e
docs(posthog): fix feature flags example to use onLoaded
harlan-zw Dec 20, 2025
7043fd3
feat(playground): add PostHog demo page
harlan-zw Dec 20, 2025
54440ee
fix: remove console.log
harlan-zw Dec 20, 2025
872a4ef
chore: resolve main merge conflicts and improve PostHog integration
harlan-zw Jan 14, 2026
2223346
fix(posthog): improve robustness and fix documentation
harlan-zw Jan 14, 2026
d404443
test(posthog): add comprehensive E2E tests for analytics and feature …
harlan-zw Jan 14, 2026
ed84ca8
test(posthog): switch to real PostHog API for E2E testing
harlan-zw Jan 14, 2026
bf44530
debug: add comprehensive console logging to PostHog E2E test
harlan-zw Jan 14, 2026
83a0125
fix: add explicit load() call and trigger for PostHog test
harlan-zw Jan 14, 2026
08c638c
wip: debugging PostHog E2E test status issue
harlan-zw Jan 14, 2026
3429883
feat(posthog): working PostHog integration with E2E tests (status=err…
harlan-zw Jan 14, 2026
1269008
feat: add NPM-only script support to @nuxt/scripts core
harlan-zw Jan 14, 2026
e7e458a
feat: complete NPM script mode implementation for PostHog
harlan-zw Jan 14, 2026
ce8bff4
fix: add SSR guard to PostHog use() function
harlan-zw Jan 14, 2026
c019cb7
fix: address AI feedback issues
harlan-zw Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions docs/content/scripts/analytics/posthog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
---
title: PostHog
description: Use PostHog in your Nuxt app.
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/scripts/blob/main/src/runtime/registry/posthog.ts
size: xs
---

[PostHog](https://posthog.com) is an open-source product analytics platform that provides analytics, session replay, feature flags, A/B testing, and more.

Nuxt Scripts provides a registry script composable `useScriptPostHog` to easily integrate PostHog in your Nuxt app.

## Installation

You must install the `posthog-js` dependency:

```bash
pnpm add posthog-js
```

### Nuxt Config Setup

::code-group

```ts [Always enabled]
export default defineNuxtConfig({
scripts: {
registry: {
posthog: {
apiKey: 'YOUR_API_KEY'
}
}
}
})
```

```ts [Production only]
export default defineNuxtConfig({
$production: {
scripts: {
registry: {
posthog: {
apiKey: 'YOUR_API_KEY'
}
}
}
}
})
```

::

#### With Environment Variables

```ts [nuxt.config.ts]
export default defineNuxtConfig({
scripts: {
registry: {
posthog: true,
}
},
runtimeConfig: {
public: {
scripts: {
posthog: {
apiKey: '', // NUXT_PUBLIC_SCRIPTS_POSTHOG_API_KEY
},
},
},
},
})
```

## useScriptPostHog

```ts
const { proxy } = useScriptPostHog({
apiKey: 'YOUR_API_KEY'
})

// Capture an event
proxy.posthog.capture('button_clicked', {
button_name: 'signup'
})
```

Please follow the [Registry Scripts](/docs/guides/registry-scripts) guide to learn more about advanced usage.

### PostHogApi

```ts
import type { PostHog } from 'posthog-js'

export interface PostHogApi {
posthog: PostHog
}
```

### Config Schema

```ts
export const PostHogOptions = object({
apiKey: string(),
region: optional(union([literal('us'), literal('eu')])),
autocapture: optional(boolean()),
capturePageview: optional(boolean()),
capturePageleave: optional(boolean()),
disableSessionRecording: optional(boolean()),
config: optional(object({})), // Full PostHogConfig passthrough
})
```

## Example

Using PostHog to track a signup event.

::code-group

```vue [SignupForm.vue]
<script setup lang="ts">
const { proxy } = useScriptPostHog()

function onSignup(email: string) {
proxy.posthog.identify(email, {
email,
signup_date: new Date().toISOString()
})
proxy.posthog.capture('user_signed_up')
}
</script>

<template>
<form @submit.prevent="onSignup(email)">
<input v-model="email" type="email" />
<button type="submit">Sign Up</button>
</form>
</template>
```

::

## EU Hosting

To use PostHog's EU cloud:

```ts
export default defineNuxtConfig({
scripts: {
registry: {
posthog: {
apiKey: 'YOUR_API_KEY',
region: 'eu'
}
}
}
})
```

## Feature Flags

```ts
const { proxy } = useScriptPostHog()

// Check a feature flag
if (proxy.posthog.isFeatureEnabled('new-dashboard')) {
// Show new dashboard
}

// Get flag payload
const payload = proxy.posthog.getFeatureFlagPayload('experiment-config')
```

## Disabling Session Recording

```ts
export default defineNuxtConfig({
scripts: {
registry: {
posthog: {
apiKey: 'YOUR_API_KEY',
disableSessionRecording: true
}
}
}
})
```
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
"esbuild",
"unimport",
"#nuxt-scripts/types",
"#nuxt-scripts-validator"
"#nuxt-scripts-validator",
"posthog-js"
]
},
"peerDependencies": {
Expand All @@ -78,7 +79,8 @@
"@types/google.maps": "^3.58.1",
"@types/vimeo__player": "^2.18.3",
"@types/youtube": "^0.1.0",
"@unhead/vue": "^2.0.3"
"@unhead/vue": "^2.0.3",
"posthog-js": "^1.0.0"
},
"peerDependenciesMeta": {
"@googlemaps/markerclusterer": {
Expand All @@ -98,6 +100,9 @@
},
"@types/youtube": {
"optional": true
},
"posthog-js": {
"optional": true
}
},
"dependencies": {
Expand Down Expand Up @@ -126,6 +131,7 @@
"@nuxt/scripts": "workspace:*",
"@nuxt/test-utils": "3.19.2",
"@paypal/paypal-js": "^9.1.0",
"posthog-js": "^1.222.0",
"@types/semver": "^7.7.1",
"@typescript-eslint/typescript-estree": "^8.50.0",
"@vue/test-utils": "^2.4.6",
Expand Down
41 changes: 41 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ export async function registry(resolve?: (path: string, opts?: ResolvePathOption
from: await resolve('./runtime/registry/cloudflare-web-analytics'),
},
},
{
label: 'PostHog',
src: false,
scriptBundling: false,
category: 'analytics',
logo: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 128 128"><path fill="#1d4aff" d="M0 .52v32.15l31.79 31.78V32.3L0 .52zm32.3 32.15v32.15l31.78 31.78V64.45L32.3 32.67zM0 64.97v32.15l31.79 31.78V96.75L0 64.97zm64.6-32.3v32.15l31.78 31.78V64.45L64.6 32.67zm31.78 31.78v32.15l31.78 31.78V96.23l-31.78-31.78zm-64.08.52v32.15l31.78 31.78V96.75L32.3 64.97zM64.6 .52v32.15l31.78 31.78V32.3L64.6 .52zm0 64.45v32.15l31.78 31.78V96.75L64.6 64.97z"/></svg>`,
import: {
name: 'useScriptPostHog',
from: await resolve('./runtime/registry/posthog'),
},
},
{
label: 'Fathom Analytics',
scriptBundling: false, // breaks script
Expand Down
Loading
Loading