Vue
This guide sets up ConsentLayer in a Vue application with Vite and Vue Router:
a module-level analytics instance, a Vue plugin that holds consent state for
your consent banner, page views on every navigation, event tracking, and error
reporting. consentlayer/vue supports Vue 3.5.17 and later. For Nuxt, follow
Nuxt instead.
It assumes you have installed consentlayer and the
SDKs of the providers you use.
1. Create the instance
Section titled “1. Create the instance”Create the instance once, at module level, in a file your components import.
Pass each provider its ID from the environment; with Vite, that is
import.meta.env:
import { createAnalytics } from 'consentlayer'import { ga4 } from 'consentlayer/providers/ga4'import { meta } from 'consentlayer/providers/meta'import { autoTracking } from 'consentlayer/auto-tracking'
export const analytics = createAnalytics({ providers: [ ga4({ measurementId: import.meta.env.VITE_GA4_MEASUREMENT_ID }), meta({ pixelId: import.meta.env.VITE_FACEBOOK_PIXEL_ID }), ], autoTracking: autoTracking(),})The options are the same as in React; React
explains how missing IDs, autoTracking, enabled and debug behave.
2. Install the plugin
Section titled “2. Install the plugin”Install consentLayer after your router, and pass it the router so it sends a
page view on every navigation:
import { consentLayer } from 'consentlayer/vue'import { createApp } from 'vue'import App from './App.vue'import { analytics } from './analytics'import { router } from './router'
createApp(App) .use(router) .use(consentLayer, { analytics, router }) .mount('#app')In the browser, app.use(consentLayer, options) performs these steps:
- It calls
analytics.consent.bootstrap(), which reads the stored choice fromlocalStorage, or from your consent adapters if nothing is stored. When neither yields a choice, or the stored choice is stale,useConsentController()reportsbannerVisible: true, unlessautoShowBannerisfalse. - It schedules
analytics.boot()according to thebootoption. - Once the router is ready, it sends a page view to every active provider. A provider that becomes active later, because the visitor grants its category, receives the current page view at that point.
- After every successful navigation to a new path or query string, it sends a
page view and calls
analytics.newPageSession(). A change to the hash alone sends nothing.
Without router, it sends one page view for the page load. On the server, it
only provides the instance and the initial state.
| Option | Type | Default | Description |
|---|---|---|---|
analytics |
Analytics |
Required | The instance from createAnalytics(). |
router |
Vue Router instance | None | Sends a page view per navigation. |
page |
{ url?, path?, title? } |
location and document.title |
Overrides the page view’s details. |
boot |
{ mode?, timeoutMs? } |
{ mode: 'immediate' } |
When providers start. |
autoShowBanner |
boolean |
true |
Whether bannerVisible becomes true when there is no stored choice or the stored choice is stale. |
openConsentGlobalKey |
string |
'CONSENTLAYER_openConsent' |
The window function that opens the settings dialog from outside Vue. |
captureErrors |
boolean |
true |
Reports errors from app.config.errorHandler. See Report errors. |
3. Add the banner
Section titled “3. Add the banner”Copy the Vue consent banner recipe into
src/components/ConsentBanner.vue, render it once, and give visitors a way to
reopen their settings:
<script setup lang="ts">import { useConsentController } from 'consentlayer/vue'import ConsentBanner from './components/ConsentBanner.vue'
const { bannerVisible, openDialog } = useConsentController()</script>
<template> <RouterView /> <ConsentBanner privacy-policy-url="/privacy" /> <button v-if="!bannerVisible" type="button" @click="openDialog">Cookie settings</button></template>useConsentController() returns the state as read-only refs and the actions
as functions. It throws when consentLayer is not installed.
Meta Pixel and GTM without JavaScript
<MetaPixelNoscript> renders Meta’s <noscript> PageView image,
https://www.facebook.com/tr?id=<pixelId>&ev=PageView&noscript=1, for visitors
with JavaScript disabled:
<script setup lang="ts">import { MetaPixelNoscript } from 'consentlayer/vue'</script>
<template> <MetaPixelNoscript :pixel-id="pixelId" enabled /></template>Those visitors never see the consent banner, so the image tracks them without
consent. For that reason it renders nothing unless you pass enabled, and
nothing while pixel-id is undefined or empty. Other attributes are passed
to the image. It only has an effect in HTML rendered on the server, as with
Nuxt or Vue’s renderToString; an application rendered only in the browser
never shows it.
<GtmNoscript :container-id="…" enabled /> from consentlayer/vue does the
same for Google Tag Manager’s <noscript> iframe; see
Google Tag Manager.
4. Track events
Section titled “4. Track events”useAnalytics() returns the instance passed to consentLayer, or the most
recently created instance when the plugin is not installed. Outside
components, import the instance from src/analytics.ts.
<script setup lang="ts">import { useAnalytics } from 'consentlayer/vue'
const analytics = useAnalytics()</script>
<template> <button @click="analytics.track('sign_up', { method: 'email' })">Sign up</button></template>useConsent() returns { consent, engine, setConsent, update }. consent is a
read-only ref holding the current consent, null before a choice. Called in a
component’s setup, it stops listening when the component unmounts. engine
is analytics.consent; setConsent(consent) saves a complete choice and
update(partial) merges a partial one into the current consent.
Events and identity lists the standard events and what each provider receives.
5. Report errors
Section titled “5. Report errors”The plugin wraps app.config.errorHandler, so errors thrown in components,
watchers and lifecycle hooks are sent through
captureError(error, { source: 'boundary', tags: { vue_info } }), where
vue_info is Vue’s description of where the error happened. It then calls the
handler that was set before app.use(consentLayer), or console.error when
there was none. A handler assigned after app.use(consentLayer) replaces the
wrapper, so set yours first. Pass captureErrors: false to leave the handler
alone.
As in React, captureError reaches the providers that implement error
reporting, Sentry and PostHog, and the window’s error and
unhandledrejection events are reported after boot unless you set
errors: { globalHandlers: false }.