Chapter 149 · Integration Vue 3
Subchapter 149.7
references/vue-js.mdMarkdown9 KBView on GitHub
PostHog makes it easy to get data about usage of your Vue.js app. Integrating PostHog into your app enables analytics about user behavior, custom events capture, session replays, feature flags, and more.
This guide walks you through integrating PostHog into your app for both Vue 2 and Vue 3. We’ll use the JavaScript Web SDK (opens in a new tab) for this.
For integrating PostHog into a Nuxt.js (opens in a new tab) app, see our Nuxt guide (opens in a new tab).
To follow this guide along, you need:
Start by installing posthog-js using your package manager:
PostHog AI
npm install --save posthog-jsyarn add posthog-jspnpm add posthog-jsbun add posthog-jsNext, depending on your Vue version, we recommend initializing PostHog using the composition API or as a plugin.
We use the Composition API as it provides better accessibility, maintainability, and type safety.
PostHog initializes as a singleton, so you can initialize it in your main.ts file before you mount your app. This ensures PostHog is initialized before any other code runs.
src/main.ts
PostHog AI
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import posthog from "posthog-js";
const app = createApp(App);
posthog.init(import.meta.env.VITE_POSTHOG_TOKEN || '<ph_project_token>', {
api_host: import.meta.env.VITE_POSTHOG_HOST || 'https://us.i.posthog.com',
defaults: '2026-01-30',
});
app.use(createPinia())
app.use(router)
app.config.errorHandler = (err, instance, info) => {
posthog.captureException(err)
}
app.mount('#app')Then, you can access PostHog throughout your app just by importing it from posthog-js.
TypeScript
PostHog AI
// src/App.vue
<script setup>
import posthog from 'posthog-js'
const handleClick = () => {
posthog.capture('button_clicked')
}
</script>Once done, PostHog will begin autocapturing (opens in a new tab) events and pageviews (if enabled) and is ready to use throughout your app.
Start by creating a plugins folder and adding a posthog.js file to that folder. In posthog.js, initialize PostHog using the install method with your project token and host. You can find these in your project settings (opens in a new tab).
JavaScript
PostHog AI
// src/plugins/posthog.js
import posthog from 'posthog-js'
export default {
install(Vue) {
posthog.init('<ph_project_token>', {
api_host: 'https://us.i.posthog.com',
defaults: '2026-01-30'
})
Vue.prototype.$posthog = posthog
}
}Next, in main.js, import and use the plugin.
JavaScript
PostHog AI
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import PosthogPlugin from './plugins/posthog'
Vue.config.productionTip = false
Vue.use(PosthogPlugin)
new Vue({
render: h => h(App),
}).$mount('#app')This makes PostHog available as this.$posthog in any Vue component.
Identifying users is required. Call
posthog.identify('your-user-id')after login to link events to a known user. This is what connects frontend event captures, session replays (opens in a new tab), LLM traces (opens in a new tab), and error tracking (opens in a new tab) to the same person — and lets backend events link back too.See our guide on identifying users (opens in a new tab) for how to set this up.
Once you have PostHog initialized, there is a lot more you can do with it beyond autocapture, pageviews, and pageleaves. You can find the full details in our JavaScript SDK docs (opens in a new tab), but we’ll cover a few examples here.
To capture custom events, evaluate feature flags, and use any of the other PostHog features, you can use the posthog object returned from the usePostHog composable like this:
JavaScript
PostHog AI
// src/App.vue
<script setup>
import { RouterView } from 'vue-router'
import { usePostHog } from './composables/usePostHog'
const { posthog } = usePostHog()
const handleClick = () => {
posthog.capture('button_clicked', { location: 'homepage' })
}
</script>
<template>
<div>
<button @click="handleClick">Click me!</button>
</div>
<RouterView />
</template>When using feature flags on pages that users navigate to directly, the flags may not be loaded when the component first renders. To ensure your UI updates reactively when flags load, create a composable that returns a reactive ref:
JavaScript
PostHog AI
// src/composables/usePostHogFeatureFlag.ts
import { ref, type Ref } from 'vue'
import { usePostHog } from './usePostHog'
export function usePostHogFeatureFlag(
feature: string,
): Ref<string | boolean | undefined> {
const { posthog } = usePostHog()
const flag = ref(posthog.getFeatureFlag(feature))
posthog.onFeatureFlags(() => {
flag.value = posthog.getFeatureFlag(feature)
})
return flag
}Then use it in your components:
JavaScript
PostHog AI
// src/App.vue
<script setup>
import { RouterView } from 'vue-router'
import { usePostHog } from './composables/usePostHog'
import { usePostHogFeatureFlag } from './composables/usePostHogFeatureFlag'
const { posthog } = usePostHog()
const isFeatureEnabled = usePostHogFeatureFlag('test-flag')
const handleClick = () => {
posthog.capture('button_clicked', { location: 'homepage' })
}
</script>
<template>
<div>
<button @click="handleClick">Click me!</button>
<p>Is feature flag enabled? {{ isFeatureEnabled ? 'Yes' : 'No' }}</p>
</div>
<RouterView />
</template>This ensures your component will automatically update when feature flags load, even if the page is accessed directly.
To capture custom events, evaluate feature flags, and use any of the other PostHog features, you can use the $posthog object returned from the plugin like this:
JavaScript
PostHog AI
// src/components/AboutPage.vue
<template>
<div class="about">
<h1>About Page</h1>
<button @click="handleClick">Test PostHog</button>
<router-link to="/">Go to Home</router-link>
<p>Feature enabled? {{ isFeatureEnabled ? 'Yes' : 'No' }}</p>
</div>
</template>
<script>
export default {
name: 'AboutPage',
data() {
return {
isFeatureEnabled: false
}
},
created() {
this.isFeatureEnabled = this.$posthog.isFeatureEnabled('test-flag')
},
methods: {
handleClick() {
this.$posthog.capture('button_clicked')
}
}
}
</script>Set up a reverse proxy (recommended)
We recommend setting up a reverse proxy (opens in a new tab), so that events are less likely to be intercepted by tracking blockers.
We have our own managed reverse proxy service (opens in a new tab), which is free for all PostHog Cloud users, routes through our infrastructure, and makes setting up your proxy easy.
If you don’t want to use our managed service then there are several other options for creating a reverse proxy, including using Cloudflare (opens in a new tab), AWS Cloudfront (opens in a new tab), and Vercel (opens in a new tab).
Grouping products in one project (recommended)
If you have multiple customer-facing products (e.g. a marketing website + mobile app + web app), it’s best to install PostHog on them all and group them in one project (opens in a new tab).
This makes it possible to track users across their entire journey (e.g. from visiting your marketing website to signing up for your product), or how they use your product across multiple platforms.
Add IPs to Firewall/WAF allowlists (recommended)
For certain features like heatmaps (opens in a new tab), your Web Application Firewall (WAF) may be blocking PostHog’s requests to your site. Add these IP addresses to your WAF allowlist or rules to let PostHog access your site.
EU: 3.75.65.221, 18.197.246.42, 3.120.223.253
US: 44.205.89.55, 52.4.194.122, 44.208.188.173
These are public, stable IPs used by PostHog services (e.g., Celery tasks for snapshots).
For any technical questions for how to integrate specific PostHog features into Vue (such as analytics, feature flags, A/B testing, or surveys), have a look at our JavaScript Web (opens in a new tab) SDK docs.
Alternatively, the following tutorials can help you get started:
Ask a question
HelpfulCould be better