Skip to content

Commit 6d9e3ce

Browse files
committed
docs: fix missing nuxt guide
1 parent f187065 commit 6d9e3ce

File tree

1 file changed

+354
-0
lines changed

1 file changed

+354
-0
lines changed
Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
---
2+
title: "How to add analytics to Nuxt"
3+
description: "Add privacy-first analytics to your Nuxt app in under 5 minutes with OpenPanel's official Nuxt module."
4+
difficulty: beginner
5+
timeToComplete: 5
6+
date: 2025-01-07
7+
cover: /content/cover-default.jpg
8+
team: OpenPanel Team
9+
steps:
10+
- name: "Install the module"
11+
anchor: "install"
12+
- name: "Configure the module"
13+
anchor: "setup"
14+
- name: "Track custom events"
15+
anchor: "events"
16+
- name: "Identify users"
17+
anchor: "identify"
18+
- name: "Set up server-side tracking"
19+
anchor: "server"
20+
- name: "Verify your setup"
21+
anchor: "verify"
22+
---
23+
24+
# How to add analytics to Nuxt
25+
26+
This guide walks you through adding OpenPanel to a Nuxt 3 application. The official `@openpanel/nuxt` module makes integration effortless with auto-imported composables, automatic page view tracking, and a built-in proxy option to bypass ad blockers.
27+
28+
OpenPanel is an open-source alternative to Mixpanel and Google Analytics. It uses cookieless tracking by default, so you won't need cookie consent banners for basic analytics.
29+
30+
## Prerequisites
31+
32+
- A Nuxt 3 project
33+
- An OpenPanel account ([sign up free](https://dashboard.openpanel.dev/onboarding))
34+
- Your Client ID from the OpenPanel dashboard
35+
36+
## Install the module [#install]
37+
38+
Start by installing the OpenPanel Nuxt module. This package includes everything you need for client-side tracking, including the auto-imported `useOpenPanel` composable.
39+
40+
```bash
41+
npm install @openpanel/nuxt
42+
```
43+
44+
If you prefer pnpm or yarn, those work too.
45+
46+
## Configure the module [#setup]
47+
48+
Add the module to your `nuxt.config.ts` and configure it with your Client ID. The module automatically sets up page view tracking and makes the `useOpenPanel` composable available throughout your app.
49+
50+
```ts title="nuxt.config.ts"
51+
export default defineNuxtConfig({
52+
modules: ['@openpanel/nuxt'],
53+
openpanel: {
54+
clientId: 'your-client-id',
55+
trackScreenViews: true,
56+
trackOutgoingLinks: true,
57+
trackAttributes: true,
58+
},
59+
});
60+
```
61+
62+
That's it. Page views are now being tracked automatically as users navigate your app.
63+
64+
### Configuration options
65+
66+
| Option | Default | Description |
67+
|--------|---------|-------------|
68+
| `clientId` || Your OpenPanel client ID (required) |
69+
| `apiUrl` | `https://api.openpanel.dev` | The API URL to send events to |
70+
| `trackScreenViews` | `true` | Automatically track page views |
71+
| `trackOutgoingLinks` | `true` | Track clicks on external links |
72+
| `trackAttributes` | `true` | Track elements with `data-track` attributes |
73+
| `trackHashChanges` | `false` | Track hash changes in URL |
74+
| `disabled` | `false` | Disable all tracking |
75+
| `proxy` | `false` | Route events through your server |
76+
77+
### Using environment variables
78+
79+
For production applications, store your Client ID in environment variables.
80+
81+
```ts title="nuxt.config.ts"
82+
export default defineNuxtConfig({
83+
modules: ['@openpanel/nuxt'],
84+
openpanel: {
85+
clientId: process.env.NUXT_PUBLIC_OPENPANEL_CLIENT_ID,
86+
trackScreenViews: true,
87+
},
88+
});
89+
```
90+
91+
```bash title=".env"
92+
NUXT_PUBLIC_OPENPANEL_CLIENT_ID=your-client-id
93+
```
94+
95+
## Track custom events [#events]
96+
97+
Page views only tell part of the story. To understand how users interact with your product, track custom events like button clicks, form submissions, or feature usage.
98+
99+
### Using the composable
100+
101+
The `useOpenPanel` composable is auto-imported, so you can use it directly in any component without importing anything.
102+
103+
```vue title="components/SignupButton.vue"
104+
<script setup>
105+
const op = useOpenPanel();
106+
107+
function handleClick() {
108+
op.track('button_clicked', {
109+
button_name: 'signup',
110+
button_location: 'hero',
111+
});
112+
}
113+
</script>
114+
115+
<template>
116+
<button type="button" @click="handleClick">Sign Up</button>
117+
</template>
118+
```
119+
120+
### Accessing via useNuxtApp
121+
122+
You can also access the OpenPanel instance through `useNuxtApp()` if you prefer.
123+
124+
```vue
125+
<script setup>
126+
const { $openpanel } = useNuxtApp();
127+
128+
$openpanel.track('my_event', { foo: 'bar' });
129+
</script>
130+
```
131+
132+
### Track form submissions
133+
134+
Form tracking helps you understand conversion rates and identify where users drop off.
135+
136+
```vue title="components/ContactForm.vue"
137+
<script setup>
138+
const op = useOpenPanel();
139+
const email = ref('');
140+
141+
async function handleSubmit() {
142+
op.track('form_submitted', {
143+
form_name: 'contact',
144+
form_location: 'homepage',
145+
});
146+
147+
// Your form submission logic
148+
}
149+
</script>
150+
151+
<template>
152+
<form @submit.prevent="handleSubmit">
153+
<input v-model="email" type="email" placeholder="Enter your email" />
154+
<button type="submit">Submit</button>
155+
</form>
156+
</template>
157+
```
158+
159+
### Use data attributes for declarative tracking
160+
161+
The SDK supports declarative tracking using `data-track` attributes. This is useful for simple click tracking without writing JavaScript.
162+
163+
```vue
164+
<template>
165+
<button
166+
data-track="button_clicked"
167+
data-track-button_name="signup"
168+
data-track-button_location="hero"
169+
>
170+
Sign Up
171+
</button>
172+
</template>
173+
```
174+
175+
When a user clicks this button, OpenPanel automatically sends a `button_clicked` event with the specified properties. This requires `trackAttributes: true` in your configuration.
176+
177+
## Identify users [#identify]
178+
179+
Anonymous tracking is useful, but identifying users unlocks more valuable insights. You can track behavior across sessions, segment users by properties, and build cohort analyses.
180+
181+
Call `identify` after a user logs in or when you have their information available.
182+
183+
```vue title="components/UserProfile.vue"
184+
<script setup>
185+
const op = useOpenPanel();
186+
const props = defineProps(['user']);
187+
188+
watch(() => props.user, (user) => {
189+
if (user) {
190+
op.identify({
191+
profileId: user.id,
192+
firstName: user.firstName,
193+
lastName: user.lastName,
194+
email: user.email,
195+
properties: {
196+
plan: user.plan,
197+
signupDate: user.createdAt,
198+
},
199+
});
200+
}
201+
}, { immediate: true });
202+
</script>
203+
204+
<template>
205+
<div>Welcome, {{ user?.firstName }}!</div>
206+
</template>
207+
```
208+
209+
### Set global properties
210+
211+
Properties set with `setGlobalProperties` are included with every event. This is useful for app version tracking, feature flags, or A/B test variants.
212+
213+
```vue title="app.vue"
214+
<script setup>
215+
const op = useOpenPanel();
216+
217+
onMounted(() => {
218+
op.setGlobalProperties({
219+
app_version: '1.0.0',
220+
environment: useRuntimeConfig().public.environment,
221+
});
222+
});
223+
</script>
224+
```
225+
226+
### Clear user data on logout
227+
228+
When users log out, clear the stored profile data to ensure subsequent events aren't associated with the previous user.
229+
230+
```vue title="components/LogoutButton.vue"
231+
<script setup>
232+
const op = useOpenPanel();
233+
234+
function handleLogout() {
235+
op.clear();
236+
navigateTo('/login');
237+
}
238+
</script>
239+
240+
<template>
241+
<button @click="handleLogout">Logout</button>
242+
</template>
243+
```
244+
245+
## Set up server-side tracking [#server]
246+
247+
For tracking events in server routes, API endpoints, or server middleware, use the `@openpanel/sdk` package. Server-side tracking requires a client secret for authentication.
248+
249+
### Install the SDK
250+
251+
```bash
252+
npm install @openpanel/sdk
253+
```
254+
255+
### Create a server instance
256+
257+
```ts title="server/utils/op.ts"
258+
import { OpenPanel } from '@openpanel/sdk';
259+
260+
export const op = new OpenPanel({
261+
clientId: process.env.OPENPANEL_CLIENT_ID!,
262+
clientSecret: process.env.OPENPANEL_CLIENT_SECRET!,
263+
});
264+
```
265+
266+
### Track events in server routes
267+
268+
```ts title="server/api/webhook.post.ts"
269+
export default defineEventHandler(async (event) => {
270+
const body = await readBody(event);
271+
272+
await op.track('webhook_received', {
273+
source: body.source,
274+
event_type: body.type,
275+
});
276+
277+
return { success: true };
278+
});
279+
```
280+
281+
Never expose your client secret on the client side. Keep it in server-only code.
282+
283+
### Awaiting in serverless environments
284+
285+
If you're deploying to a serverless platform like Vercel or Netlify, make sure to await the tracking call to ensure it completes before the function terminates.
286+
287+
```ts
288+
export default defineEventHandler(async (event) => {
289+
// Always await in serverless environments
290+
await op.track('my_server_event', { foo: 'bar' });
291+
return { message: 'Event logged!' };
292+
});
293+
```
294+
295+
## Bypass ad blockers with proxy [#proxy]
296+
297+
Many ad blockers block requests to third-party analytics domains. The Nuxt module includes a built-in proxy that routes events through your own server.
298+
299+
Enable the proxy option in your configuration:
300+
301+
```ts title="nuxt.config.ts"
302+
export default defineNuxtConfig({
303+
modules: ['@openpanel/nuxt'],
304+
openpanel: {
305+
clientId: 'your-client-id',
306+
proxy: true, // Routes events through /api/openpanel/*
307+
},
308+
});
309+
```
310+
311+
When `proxy: true` is set:
312+
- The module automatically sets `apiUrl` to `/api/openpanel`
313+
- A server handler is registered at `/api/openpanel/**`
314+
- All tracking requests route through your Nuxt server
315+
316+
This makes tracking requests invisible to browser extensions that block third-party analytics.
317+
318+
## Verify your setup [#verify]
319+
320+
Open your Nuxt app in the browser and navigate between a few pages. Interact with elements that trigger custom events. Then open your [OpenPanel dashboard](https://dashboard.openpanel.dev) and check the Real-time view to see events appearing within seconds.
321+
322+
If events aren't showing up, check the browser console for errors. The most common issues are:
323+
- Incorrect client ID
324+
- Ad blockers intercepting requests (enable the proxy option)
325+
- Client ID exposed in server-only code
326+
327+
The Network tab in your browser's developer tools can help you confirm that requests are being sent.
328+
329+
## Next steps
330+
331+
The [Nuxt SDK reference](/docs/sdks/nuxt) covers additional features like incrementing user properties and event filtering. If you're interested in understanding how OpenPanel handles privacy, read our article on [cookieless analytics](/articles/cookieless-analytics).
332+
333+
<Faqs>
334+
<FaqItem question="Does OpenPanel work with Nuxt 3 and Nuxt 4?">
335+
Yes. The `@openpanel/nuxt` module supports both Nuxt 3 and Nuxt 4. It uses Nuxt's module system and auto-imports, so everything works seamlessly with either version.
336+
</FaqItem>
337+
338+
<FaqItem question="Is the useOpenPanel composable auto-imported?">
339+
Yes. The module automatically registers the `useOpenPanel` composable, so you can use it in any component without importing it. You can also access the instance via `useNuxtApp().$openpanel`.
340+
</FaqItem>
341+
342+
<FaqItem question="Does OpenPanel use cookies?">
343+
No. OpenPanel uses cookieless tracking by default. This means you don't need cookie consent banners for basic analytics under most privacy regulations, including GDPR and PECR.
344+
</FaqItem>
345+
346+
<FaqItem question="How do I avoid ad blockers?">
347+
Enable the `proxy: true` option in your configuration. This routes all tracking requests through your Nuxt server at `/api/openpanel/*`, which ad blockers don't typically block.
348+
</FaqItem>
349+
350+
<FaqItem question="Is OpenPanel GDPR compliant?">
351+
Yes. OpenPanel is designed for GDPR compliance with cookieless tracking, data minimization, and full support for data subject rights. With self-hosting, you also eliminate international data transfer concerns entirely.
352+
</FaqItem>
353+
</Faqs>
354+

0 commit comments

Comments
 (0)