Skip to content

Commit c91eaa5

Browse files
harlan-zwclaude
andauthored
feat(registry): add PostHog analytics script (#568)
Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 757c7a8 commit c91eaa5

File tree

13 files changed

+3456
-2287
lines changed

13 files changed

+3456
-2287
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
---
2+
title: PostHog
3+
description: Use PostHog in your Nuxt app.
4+
links:
5+
- label: Source
6+
icon: i-simple-icons-github
7+
to: https://github.com/nuxt/scripts/blob/main/src/runtime/registry/posthog.ts
8+
size: xs
9+
---
10+
11+
[PostHog](https://posthog.com) is an open-source product analytics platform that provides analytics, session replay, feature flags, A/B testing, and more.
12+
13+
Nuxt Scripts provides a registry script composable `useScriptPostHog` to easily integrate PostHog in your Nuxt app.
14+
15+
## Installation
16+
17+
You must install the `posthog-js` dependency:
18+
19+
```bash
20+
pnpm add posthog-js
21+
```
22+
23+
### Nuxt Config Setup
24+
25+
::code-group
26+
27+
```ts [Always enabled]
28+
export default defineNuxtConfig({
29+
scripts: {
30+
registry: {
31+
posthog: {
32+
apiKey: 'YOUR_API_KEY'
33+
}
34+
}
35+
}
36+
})
37+
```
38+
39+
```ts [Production only]
40+
export default defineNuxtConfig({
41+
$production: {
42+
scripts: {
43+
registry: {
44+
posthog: {
45+
apiKey: 'YOUR_API_KEY'
46+
}
47+
}
48+
}
49+
}
50+
})
51+
```
52+
53+
::
54+
55+
#### With Environment Variables
56+
57+
```ts [nuxt.config.ts]
58+
export default defineNuxtConfig({
59+
scripts: {
60+
registry: {
61+
posthog: true,
62+
}
63+
},
64+
runtimeConfig: {
65+
public: {
66+
scripts: {
67+
posthog: {
68+
apiKey: '', // NUXT_PUBLIC_SCRIPTS_POSTHOG_API_KEY
69+
},
70+
},
71+
},
72+
},
73+
})
74+
```
75+
76+
## useScriptPostHog
77+
78+
```ts
79+
const { proxy } = useScriptPostHog({
80+
apiKey: 'YOUR_API_KEY'
81+
})
82+
83+
// Capture an event
84+
proxy.posthog.capture('button_clicked', {
85+
button_name: 'signup'
86+
})
87+
```
88+
89+
Please follow the [Registry Scripts](/docs/guides/registry-scripts) guide to learn more about advanced usage.
90+
91+
### PostHogApi
92+
93+
```ts
94+
import type { PostHog } from 'posthog-js'
95+
96+
export interface PostHogApi {
97+
posthog: PostHog
98+
}
99+
```
100+
101+
### Config Schema
102+
103+
```ts
104+
export const PostHogOptions = object({
105+
apiKey: string(),
106+
region: optional(union([literal('us'), literal('eu')])),
107+
autocapture: optional(boolean()),
108+
capturePageview: optional(boolean()),
109+
capturePageleave: optional(boolean()),
110+
disableSessionRecording: optional(boolean()),
111+
config: optional(record(string(), any())), // Full PostHogConfig passthrough
112+
})
113+
```
114+
115+
## Example
116+
117+
Using PostHog to track a signup event.
118+
119+
::code-group
120+
121+
```vue [SignupForm.vue]
122+
<script setup lang="ts">
123+
const { proxy } = useScriptPostHog()
124+
125+
function onSignup(email: string) {
126+
proxy.posthog.identify(email, {
127+
email,
128+
signup_date: new Date().toISOString()
129+
})
130+
proxy.posthog.capture('user_signed_up')
131+
}
132+
</script>
133+
134+
<template>
135+
<form @submit.prevent="onSignup(email)">
136+
<input v-model="email" type="email" />
137+
<button type="submit">Sign Up</button>
138+
</form>
139+
</template>
140+
```
141+
142+
::
143+
144+
## EU Hosting
145+
146+
To use PostHog's EU cloud:
147+
148+
```ts
149+
export default defineNuxtConfig({
150+
scripts: {
151+
registry: {
152+
posthog: {
153+
apiKey: 'YOUR_API_KEY',
154+
region: 'eu'
155+
}
156+
}
157+
}
158+
})
159+
```
160+
161+
## Feature Flags
162+
163+
Feature flag methods return values, so you need to wait for PostHog to load first:
164+
165+
```ts
166+
const { onLoaded } = useScriptPostHog()
167+
168+
onLoaded(({ posthog }) => {
169+
// Check a feature flag
170+
if (posthog.isFeatureEnabled('new-dashboard')) {
171+
// Show new dashboard
172+
}
173+
174+
// Get flag payload
175+
const payload = posthog.getFeatureFlagPayload('experiment-config')
176+
})
177+
```
178+
179+
## Disabling Session Recording
180+
181+
```ts
182+
export default defineNuxtConfig({
183+
scripts: {
184+
registry: {
185+
posthog: {
186+
apiKey: 'YOUR_API_KEY',
187+
disableSessionRecording: true
188+
}
189+
}
190+
}
191+
})
192+
```

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
"esbuild",
6969
"unimport",
7070
"#nuxt-scripts/types",
71-
"#nuxt-scripts-validator"
71+
"#nuxt-scripts-validator",
72+
"posthog-js"
7273
]
7374
},
7475
"peerDependencies": {
@@ -78,7 +79,8 @@
7879
"@types/google.maps": "^3.58.1",
7980
"@types/vimeo__player": "^2.18.3",
8081
"@types/youtube": "^0.1.0",
81-
"@unhead/vue": "^2.0.3"
82+
"@unhead/vue": "^2.0.3",
83+
"posthog-js": "^1.0.0"
8284
},
8385
"peerDependenciesMeta": {
8486
"@googlemaps/markerclusterer": {
@@ -98,6 +100,9 @@
98100
},
99101
"@types/youtube": {
100102
"optional": true
103+
},
104+
"posthog-js": {
105+
"optional": true
101106
}
102107
},
103108
"dependencies": {
@@ -126,6 +131,7 @@
126131
"@nuxt/scripts": "workspace:*",
127132
"@nuxt/test-utils": "3.19.2",
128133
"@paypal/paypal-js": "^9.1.0",
134+
"posthog-js": "^1.222.0",
129135
"@types/semver": "^7.7.1",
130136
"@typescript-eslint/typescript-estree": "^8.53.0",
131137
"@vue/test-utils": "^2.4.6",

playground/pages/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function getPlaygroundPath(script: any): string | null {
2020
'cloudflare-web-analytics': '/third-parties/cloudflare-web-analytics/nuxt-scripts',
2121
'fathom-analytics': '/third-parties/fathom-analytics',
2222
'plausible-analytics': '/third-parties/plausible-analytics',
23+
'posthog': '/third-parties/posthog/nuxt-scripts',
2324
'matomo-analytics': '/third-parties/matomo-analytics/nuxt-scripts',
2425
'rybbit-analytics': '/third-parties/rybbit-analytics',
2526
'databuddy-analytics': '/third-parties/databuddy-analytics',
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script lang="ts" setup>
2+
import { useHead, useScriptPostHog } from '#imports'
3+
4+
useHead({
5+
title: 'PostHog',
6+
})
7+
8+
const { status, proxy } = useScriptPostHog({
9+
apiKey: 'phc_YOUR_API_KEY',
10+
})
11+
12+
function captureEvent() {
13+
proxy.posthog.capture('button_clicked', {
14+
button_name: 'test',
15+
})
16+
}
17+
18+
function identifyUser() {
19+
proxy.posthog.identify('[email protected]', {
20+
21+
name: 'Test User',
22+
})
23+
}
24+
</script>
25+
26+
<template>
27+
<div>
28+
<ClientOnly>
29+
<div>
30+
status: {{ status }}
31+
</div>
32+
<div class="flex gap-2 mt-4">
33+
<UButton @click="captureEvent">
34+
Capture Event
35+
</UButton>
36+
<UButton @click="identifyUser">
37+
Identify User
38+
</UButton>
39+
</div>
40+
</ClientOnly>
41+
</div>
42+
</template>

0 commit comments

Comments
 (0)