Hero
Back to all guides

How to add analytics to Vue

Add privacy-first analytics to your Vue application with OpenPanel's Web SDK. Track page views, custom events, and user behavior.

OpenPanel Team

12/14/2025

Beginner
8 min

Adding analytics to your Vue application helps you understand how users interact with your app. OpenPanel's Web SDK integrates smoothly with Vue 3 and Vue Router, providing automatic page view tracking, custom events, and user identification without requiring Vue-specific bindings.

OpenPanel is an open-source alternative to Mixpanel and Google Analytics. It delivers powerful insights while respecting user privacy through cookieless tracking by default.

Prerequisites

  • A Vue 3 project (Vite or Vue CLI)
  • An OpenPanel account (sign up free)
  • Your Client ID from the OpenPanel dashboard

Install the SDK

The OpenPanel Web SDK is a lightweight package that works in any JavaScript environment, including Vue. Install it using npm, and pnpm or yarn work the same way.

npm install @openpanel/web

Create an OpenPanel instance

Create a dedicated file for your OpenPanel instance. This centralizes your analytics configuration and makes the instance easy to import throughout your application.

src/lib/op.ts
import { OpenPanel } from '@openpanel/web';

export const op = new OpenPanel({
  clientId: 'YOUR_CLIENT_ID',
  trackScreenViews: true,
  trackOutgoingLinks: true,
  trackAttributes: true,
});

The trackScreenViews option automatically tracks page views when the URL changes. This works with Vue Router's client-side navigation. The trackAttributes option enables declarative tracking using data-track attributes on HTML elements.

Using environment variables

For production applications, store your Client ID in environment variables.

src/lib/op.ts
import { OpenPanel } from '@openpanel/web';

export const op = new OpenPanel({
  clientId: import.meta.env.VITE_OPENPANEL_CLIENT_ID,
  trackScreenViews: true,
  trackOutgoingLinks: true,
  trackAttributes: true,
});
.env
VITE_OPENPANEL_CLIENT_ID=your-client-id

Initialize on app load

Import the OpenPanel instance in your app's entry point to ensure it initializes when your application loads. This is all you need to start tracking page views automatically.

src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import './lib/op'; // Initialize OpenPanel

const app = createApp(App);
app.use(router);
app.mount('#app');

Make OpenPanel available globally (optional)

If you prefer accessing OpenPanel through the Vue instance rather than importing it in each component, you can add it as a global property.

src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { op } from './lib/op';

const app = createApp(App);
app.config.globalProperties.$op = op;
app.use(router);
app.mount('#app');

This makes this.$op available in Options API components and allows you to inject it in Composition API components.

Track page views

With trackScreenViews: true, OpenPanel automatically tracks page views when the browser's URL changes. This works out of the box with Vue Router.

If you need to track page views manually or want to include additional route metadata, you can use a Vue Router navigation guard.

src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router';
import { op } from '../lib/op';
import routes from './routes';

const router = createRouter({
  history: createWebHistory(),
  routes,
});

router.afterEach((to) => {
  op.track('screen_view', {
    path: to.path,
    name: String(to.name),
  });
});

export default router;

If you use this approach, set trackScreenViews: false in your OpenPanel configuration to avoid duplicate tracking.

Track custom events

Import the OpenPanel instance in your components to track events. The track method accepts an event name and an optional properties object.

Using Composition API

src/components/SignupButton.vue
<template>
  <button type="button" @click="handleClick">Sign Up</button>
</template>

<script setup lang="ts">
import { op } from '../lib/op';

function handleClick() {
  op.track('button_clicked', {
    button_name: 'signup',
    button_location: 'hero',
  });
}
</script>

Using Options API

src/components/SignupButton.vue
<template>
  <button type="button" @click="handleClick">Sign Up</button>
</template>

<script>
import { op } from '../lib/op';

export default {
  methods: {
    handleClick() {
      op.track('button_clicked', {
        button_name: 'signup',
        button_location: 'hero',
      });
    },
  },
};
</script>

Track form submissions

Form tracking helps you understand conversion rates and identify where users drop off.

src/components/ContactForm.vue
<template>
  <form @submit.prevent="handleSubmit">
    <input
      v-model="email"
      type="email"
      placeholder="Enter your email"
    />
    <button type="submit">Submit</button>
  </form>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { op } from '../lib/op';

const email = ref('');

function handleSubmit() {
  op.track('form_submitted', {
    form_name: 'contact',
    form_location: 'homepage',
  });

  // Your form submission logic
}
</script>

Use data attributes for declarative tracking

The Web SDK supports declarative tracking using data-track attributes. This is useful for simple click tracking without writing JavaScript.

<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

Once a user logs in or provides identifying information, call identify to associate their activity with a profile. This enables user-level analytics and cohort analysis.

src/components/UserProfile.vue
<template>
  <div>Welcome, {{ user?.firstName }}!</div>
</template>

<script setup lang="ts">
import { watch } from 'vue';
import { op } from '../lib/op';

interface User {
  id: string;
  firstName: string;
  lastName: string;
  email: string;
  plan: string;
  createdAt: string;
}

const props = defineProps<{ user: User | null }>();

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>

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.

src/components/LogoutButton.vue
<template>
  <button @click="handleLogout">Logout</button>
</template>

<script setup lang="ts">
import { op } from '../lib/op';

const emit = defineEmits<{ logout: [] }>();

function handleLogout() {
  op.clear();
  emit('logout');
}
</script>

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.

src/App.vue
<script setup lang="ts">
import { onMounted } from 'vue';
import { op } from './lib/op';

onMounted(() => {
  op.setGlobalProperties({
    app_version: '1.0.0',
    environment: import.meta.env.MODE,
  });
});
</script>

Verify your setup

Open your Vue app in the browser and navigate between a few pages. Interact with elements that trigger custom events. Then open your OpenPanel dashboard and check the Real-time view to see events appearing.

If events aren't appearing, check the browser console for errors. Verify your Client ID is correct and ensure ad blockers aren't blocking requests to the OpenPanel API. The Network tab in your browser's developer tools can help you confirm that requests are being sent.

Next steps

The Web SDK has additional features like property incrementing and event filtering. Read the full Web SDK documentation for the complete API reference.

For Nuxt.js applications, the setup is similar. Initialize OpenPanel in a Nuxt plugin and the automatic page view tracking will work with Nuxt's router.

Loved by builders everywhere

From indie hackers to global teams, OpenPanel helps people understand their users effortlessly.

  • Steven Tey
    Steven Tey
    @steventey

    Open-source Mixpanel alternative just dropped → http://git.new/openpanel

    It combines the power of Mixpanel + the ease of use of @PlausibleHQ into a fully open-source product.

    Built by @CarlLindesvard and it’s already tracking 750K+ events 🤩

  • Pontus Abrahamsson - oss/acc
    Pontus Abrahamsson - oss/acc
    @pontusab

    Thanks, OpenPanel is a beast, love it!

  • Piotr Kulpinski
    Piotr Kulpinski
    @piotrkulpinski

    The Overview tab in OpenPanel is great. It has everything I need from my analytics: the stats, the graph, traffic sources, locations, devices, etc.

    The UI is beautiful ✨ Clean, modern look, very pleasing to the eye.

  • greg hodson 🍜
    greg hodson 🍜
    @h0dson

    i second this, openpanel is killing it

  • Jacob 🍀 Build in Public
    Jacob 🍀 Build in Public
    @javayhuwx

    🤯 wow, it's amazing! Just integrate @OpenPanelDev into http://indiehackers.site last night, and now I can see visitors coming from all round the world.

    OpenPanel has a more beautiful UI and much more powerful features when compared to Umami.

    #buildinpublic #indiehackers

  • Lee
    Lee
    @DutchEngIishman

    Day two of marketing.

    I like this upward trend..

    P.S. website went live on Sunday

    P.P.S. Openpanel by @CarlLindesvard is awesome.

Ready to understand your users better?
Start tracking in minutes

Join thousands of companies using OpenPanel. Free 30-day trial, no credit card required. Self-host for free or use our cloud.

Get started now