docs: fix missing nuxt guide
This commit is contained in:
354
apps/public/content/guides/nuxt-analytics.mdx
Normal file
354
apps/public/content/guides/nuxt-analytics.mdx
Normal file
@@ -0,0 +1,354 @@
|
||||
---
|
||||
title: "How to add analytics to Nuxt"
|
||||
description: "Add privacy-first analytics to your Nuxt app in under 5 minutes with OpenPanel's official Nuxt module."
|
||||
difficulty: beginner
|
||||
timeToComplete: 5
|
||||
date: 2025-01-07
|
||||
cover: /content/cover-default.jpg
|
||||
team: OpenPanel Team
|
||||
steps:
|
||||
- name: "Install the module"
|
||||
anchor: "install"
|
||||
- name: "Configure the module"
|
||||
anchor: "setup"
|
||||
- name: "Track custom events"
|
||||
anchor: "events"
|
||||
- name: "Identify users"
|
||||
anchor: "identify"
|
||||
- name: "Set up server-side tracking"
|
||||
anchor: "server"
|
||||
- name: "Verify your setup"
|
||||
anchor: "verify"
|
||||
---
|
||||
|
||||
# How to add analytics to Nuxt
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Nuxt 3 project
|
||||
- An OpenPanel account ([sign up free](https://dashboard.openpanel.dev/onboarding))
|
||||
- Your Client ID from the OpenPanel dashboard
|
||||
|
||||
## Install the module [#install]
|
||||
|
||||
Start by installing the OpenPanel Nuxt module. This package includes everything you need for client-side tracking, including the auto-imported `useOpenPanel` composable.
|
||||
|
||||
```bash
|
||||
npm install @openpanel/nuxt
|
||||
```
|
||||
|
||||
If you prefer pnpm or yarn, those work too.
|
||||
|
||||
## Configure the module [#setup]
|
||||
|
||||
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.
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
export default defineNuxtConfig({
|
||||
modules: ['@openpanel/nuxt'],
|
||||
openpanel: {
|
||||
clientId: 'your-client-id',
|
||||
trackScreenViews: true,
|
||||
trackOutgoingLinks: true,
|
||||
trackAttributes: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
That's it. Page views are now being tracked automatically as users navigate your app.
|
||||
|
||||
### Configuration options
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `clientId` | — | Your OpenPanel client ID (required) |
|
||||
| `apiUrl` | `https://api.openpanel.dev` | The API URL to send events to |
|
||||
| `trackScreenViews` | `true` | Automatically track page views |
|
||||
| `trackOutgoingLinks` | `true` | Track clicks on external links |
|
||||
| `trackAttributes` | `true` | Track elements with `data-track` attributes |
|
||||
| `trackHashChanges` | `false` | Track hash changes in URL |
|
||||
| `disabled` | `false` | Disable all tracking |
|
||||
| `proxy` | `false` | Route events through your server |
|
||||
|
||||
### Using environment variables
|
||||
|
||||
For production applications, store your Client ID in environment variables.
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
export default defineNuxtConfig({
|
||||
modules: ['@openpanel/nuxt'],
|
||||
openpanel: {
|
||||
clientId: process.env.NUXT_PUBLIC_OPENPANEL_CLIENT_ID,
|
||||
trackScreenViews: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```bash title=".env"
|
||||
NUXT_PUBLIC_OPENPANEL_CLIENT_ID=your-client-id
|
||||
```
|
||||
|
||||
## Track custom events [#events]
|
||||
|
||||
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.
|
||||
|
||||
### Using the composable
|
||||
|
||||
The `useOpenPanel` composable is auto-imported, so you can use it directly in any component without importing anything.
|
||||
|
||||
```vue title="components/SignupButton.vue"
|
||||
<script setup>
|
||||
const op = useOpenPanel();
|
||||
|
||||
function handleClick() {
|
||||
op.track('button_clicked', {
|
||||
button_name: 'signup',
|
||||
button_location: 'hero',
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button type="button" @click="handleClick">Sign Up</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Accessing via useNuxtApp
|
||||
|
||||
You can also access the OpenPanel instance through `useNuxtApp()` if you prefer.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const { $openpanel } = useNuxtApp();
|
||||
|
||||
$openpanel.track('my_event', { foo: 'bar' });
|
||||
</script>
|
||||
```
|
||||
|
||||
### Track form submissions
|
||||
|
||||
Form tracking helps you understand conversion rates and identify where users drop off.
|
||||
|
||||
```vue title="components/ContactForm.vue"
|
||||
<script setup>
|
||||
const op = useOpenPanel();
|
||||
const email = ref('');
|
||||
|
||||
async function handleSubmit() {
|
||||
op.track('form_submitted', {
|
||||
form_name: 'contact',
|
||||
form_location: 'homepage',
|
||||
});
|
||||
|
||||
// Your form submission logic
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<input v-model="email" type="email" placeholder="Enter your email" />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Use data attributes for declarative tracking
|
||||
|
||||
The SDK supports declarative tracking using `data-track` attributes. This is useful for simple click tracking without writing JavaScript.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<button
|
||||
data-track="button_clicked"
|
||||
data-track-button_name="signup"
|
||||
data-track-button_location="hero"
|
||||
>
|
||||
Sign Up
|
||||
</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
When a user clicks this button, OpenPanel automatically sends a `button_clicked` event with the specified properties. This requires `trackAttributes: true` in your configuration.
|
||||
|
||||
## Identify users [#identify]
|
||||
|
||||
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.
|
||||
|
||||
Call `identify` after a user logs in or when you have their information available.
|
||||
|
||||
```vue title="components/UserProfile.vue"
|
||||
<script setup>
|
||||
const op = useOpenPanel();
|
||||
const props = defineProps(['user']);
|
||||
|
||||
watch(() => props.user, (user) => {
|
||||
if (user) {
|
||||
op.identify({
|
||||
profileId: user.id,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
email: user.email,
|
||||
properties: {
|
||||
plan: user.plan,
|
||||
signupDate: user.createdAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, { immediate: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>Welcome, {{ user?.firstName }}!</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Set global properties
|
||||
|
||||
Properties set with `setGlobalProperties` are included with every event. This is useful for app version tracking, feature flags, or A/B test variants.
|
||||
|
||||
```vue title="app.vue"
|
||||
<script setup>
|
||||
const op = useOpenPanel();
|
||||
|
||||
onMounted(() => {
|
||||
op.setGlobalProperties({
|
||||
app_version: '1.0.0',
|
||||
environment: useRuntimeConfig().public.environment,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Clear user data on logout
|
||||
|
||||
When users log out, clear the stored profile data to ensure subsequent events aren't associated with the previous user.
|
||||
|
||||
```vue title="components/LogoutButton.vue"
|
||||
<script setup>
|
||||
const op = useOpenPanel();
|
||||
|
||||
function handleLogout() {
|
||||
op.clear();
|
||||
navigateTo('/login');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="handleLogout">Logout</button>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Set up server-side tracking [#server]
|
||||
|
||||
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.
|
||||
|
||||
### Install the SDK
|
||||
|
||||
```bash
|
||||
npm install @openpanel/sdk
|
||||
```
|
||||
|
||||
### Create a server instance
|
||||
|
||||
```ts title="server/utils/op.ts"
|
||||
import { OpenPanel } from '@openpanel/sdk';
|
||||
|
||||
export const op = new OpenPanel({
|
||||
clientId: process.env.OPENPANEL_CLIENT_ID!,
|
||||
clientSecret: process.env.OPENPANEL_CLIENT_SECRET!,
|
||||
});
|
||||
```
|
||||
|
||||
### Track events in server routes
|
||||
|
||||
```ts title="server/api/webhook.post.ts"
|
||||
export default defineEventHandler(async (event) => {
|
||||
const body = await readBody(event);
|
||||
|
||||
await op.track('webhook_received', {
|
||||
source: body.source,
|
||||
event_type: body.type,
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
```
|
||||
|
||||
Never expose your client secret on the client side. Keep it in server-only code.
|
||||
|
||||
### Awaiting in serverless environments
|
||||
|
||||
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.
|
||||
|
||||
```ts
|
||||
export default defineEventHandler(async (event) => {
|
||||
// Always await in serverless environments
|
||||
await op.track('my_server_event', { foo: 'bar' });
|
||||
return { message: 'Event logged!' };
|
||||
});
|
||||
```
|
||||
|
||||
## Bypass ad blockers with proxy [#proxy]
|
||||
|
||||
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.
|
||||
|
||||
Enable the proxy option in your configuration:
|
||||
|
||||
```ts title="nuxt.config.ts"
|
||||
export default defineNuxtConfig({
|
||||
modules: ['@openpanel/nuxt'],
|
||||
openpanel: {
|
||||
clientId: 'your-client-id',
|
||||
proxy: true, // Routes events through /api/openpanel/*
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When `proxy: true` is set:
|
||||
- The module automatically sets `apiUrl` to `/api/openpanel`
|
||||
- A server handler is registered at `/api/openpanel/**`
|
||||
- All tracking requests route through your Nuxt server
|
||||
|
||||
This makes tracking requests invisible to browser extensions that block third-party analytics.
|
||||
|
||||
## Verify your setup [#verify]
|
||||
|
||||
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.
|
||||
|
||||
If events aren't showing up, check the browser console for errors. The most common issues are:
|
||||
- Incorrect client ID
|
||||
- Ad blockers intercepting requests (enable the proxy option)
|
||||
- Client ID exposed in server-only code
|
||||
|
||||
The Network tab in your browser's developer tools can help you confirm that requests are being sent.
|
||||
|
||||
## Next steps
|
||||
|
||||
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).
|
||||
|
||||
<Faqs>
|
||||
<FaqItem question="Does OpenPanel work with Nuxt 3 and Nuxt 4?">
|
||||
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.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Is the useOpenPanel composable auto-imported?">
|
||||
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`.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Does OpenPanel use cookies?">
|
||||
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.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="How do I avoid ad blockers?">
|
||||
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.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Is OpenPanel GDPR compliant?">
|
||||
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.
|
||||
</FaqItem>
|
||||
</Faqs>
|
||||
|
||||
Reference in New Issue
Block a user