Add Google Analytics (GA4) to Vue 3, VitePress, and Quasar with one line of code. Works with Nuxt 3 via the Vue plugin. GDPR/CCPA compliant cookie consent with Google Consent Mode v2, EU auto-detection, and SPA page tracking.
npm install @structured-world/vue-privacyGDPR-compliant cookie consent with Google Consent Mode v2 support for Vue 3, Quasar, VitePress, and plain HTML.






Documentation · GitHub · npm
- Google Consent Mode v2 — Full support for analytics_storage, ad_storage, ad_user_data, ad_personalization
- EU Detection — Auto-detect EU users via Cloudflare headers, IP API, or timezone heuristics
- Consent Banner — Customizable GDPR/CCPA banner with dark mode support
- Preference Center — OneTrust-style modal with category toggles (necessary, analytics, marketing, functional)
- Script Blocking — Block third-party scripts until consent is granted
- i18n — 13 built-in locales (en, de, fr, es, it, pt, nl, pl, ru, uk, ja, zh, ko)
- Remote Storage — Pluggable backend for cross-device consent sync
- GA4 Event Tracking — Typed helpers for ecommerce and conversion events
- Framework Support — Vue 3, Quasar, VitePress, Nuxt 3
- UMD/CDN — Use via tag, no build tools needed
- TypeScript — Full type safety
- Lightweight — ~11kB gzip (UMD), no external dependencies
- SSR Safe — Works with server-side rendering
- Accessible — ARIA-compliant components with focus trap
``bash`
npm install @structured-world/vue-privacyor
yarn add @structured-world/vue-privacyor
pnpm add @structured-world/vue-privacy
`typescript
import { createApp } from 'vue';
import { createConsentPlugin } from '@structured-world/vue-privacy/vue';
import router from './router';
import App from './App.vue';
const app = createApp(App);
app.use(router);
app.use(createConsentPlugin({
gaId: 'G-XXXXXXXXXX',
euDetection: 'auto',
router: router, // Enables automatic SPA page tracking
}));
app.mount('#app');
`
`vue`
> TypeScript users: Add vue-router as a dev dependency for type resolution:npm i -D vue-router
> (not needed at runtime)
`typescript
// docs/.vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme';
import { enhanceWithConsent } from '@structured-world/vue-privacy/vitepress';
export default enhanceWithConsent(DefaultTheme, {
gaId: 'G-XXXXXXXXXX',
});
`
Fire GA4 events from frontmatter:
`md`
---
ga4Title: Pricing Page
ga4Event:
name: view_pricing
params:
page_type: pricing
---
`typescript
// src/boot/consent.ts
import { boot } from 'quasar/wrappers';
import { consentBoot } from '@structured-world/vue-privacy/quasar';
export default boot(consentBoot({
gaId: 'G-XXXXXXXXXX',
}));
`
`html`
`typescript
interface ConsentConfig {
// Google Analytics measurement ID
gaId?: string;
// Locale for UI text (auto-detected if not set)
// Supported: en, de, fr, es, it, pt, nl, pl, ru, uk, ja, zh, ko
locale?: SupportedLocale;
// Consent categories
categories?: {
analytics?: boolean; // Default: false
marketing?: boolean; // Default: false
functional?: boolean; // Default: true
};
// Banner UI
banner?: {
title?: string;
message?: string;
acceptAll?: string;
rejectAll?: string;
customize?: string;
privacyLink?: string;
privacyLinkText?: string;
};
// Preference center UI
preferenceCenter?: {
title?: string;
description?: string;
savePreferences?: string;
acceptAll?: string;
categories?: {
necessary?: { name?: string; description?: string };
analytics?: { name?: string; description?: string };
marketing?: { name?: string; description?: string };
functional?: { name?: string; description?: string };
};
};
// Cookie settings
cookie?: {
name?: string; // Default: 'consent_preferences'
expiry?: number; // Days, default: 365
domain?: string;
path?: string; // Default: '/'
};
// Remote consent storage (pluggable backend)
storage?: ConsentStorage;
// EU detection mode
euDetection?: 'auto' | 'cloudflare' | 'api' | 'always' | 'never';
// Consent version (changing resets all consents)
version?: string;
// Callbacks
onConsentChange?: (consent: StoredConsent) => void;
onBannerShow?: () => void;
onBannerHide?: () => void;
onPreferenceCenterShow?: () => void;
onPreferenceCenterHide?: () => void;
}
`
`vue
`
Block third-party scripts until consent is granted:
`html
src="https://example.com/analytics.js">
src="https://example.com/ads.js">
`
Scripts are automatically unblocked when the matching category is accepted.
Sync consent across devices with a pluggable backend:
`typescript
import { createConsentManager, createKVStorage } from '@structured-world/vue-privacy';
// Built-in Cloudflare KV adapter
const manager = createConsentManager({
gaId: 'G-XXXXXXXXXX',
storage: createKVStorage('/api/consent'),
});
// Or implement your own
const manager = createConsentManager({
storage: {
get: (uid, version) => fetch(/api/consent?id=${uid}).then(r => r.json()),`
set: (uid, consent) => fetch('/api/consent', {
method: 'POST',
body: JSON.stringify({ id: uid, ...consent }),
}).then(r => r.json()).then(d => d.id),
},
});
`typescript
import { createConsentManager } from '@structured-world/vue-privacy';
const manager = createConsentManager({
gaId: 'G-XXXXXXXXXX',
});
await manager.init();
// Programmatic consent
await manager.acceptAll();
await manager.rejectAll();
await manager.savePreferences({ analytics: true, marketing: false });
// Preference center
manager.showPreferenceCenter();
// Check state
const consent = manager.getConsent();
const isEU = manager.isEUUser();
// Cleanup
manager.destroy();
`
`typescript`
createConsentPlugin({ euDetection: 'auto' })
Tries in order:
1. Cloudflare X-Is-EU-Country header
2. IP API (ipapi.co)
3. Timezone heuristics fallback
The banner and preference center use CSS custom properties:
`css`
:root {
--consent-bg: #ffffff;
--consent-text: #1a1a1a;
--consent-text-secondary: #666666;
--consent-link: #0066cc;
--consent-btn-accept-bg: #0066cc;
--consent-btn-accept-text: #ffffff;
--consent-btn-reject-bg: #e0e0e0;
--consent-btn-reject-text: #1a1a1a;
--consent-font: system-ui, -apple-system, sans-serif;
}
Dark mode is automatically supported via prefers-color-scheme`.
| Feature | Status |
|---------|--------|
| Consent banner component | ✅ |
| Preference center modal | ✅ |
| Google Consent Mode v2 | ✅ |
| GA4 integration | ✅ |
| GA4 event tracking (ecommerce, conversions) | ✅ |
| EU geo-detection | ✅ |
| Script blocking | ✅ |
| i18n (13 locales) | ✅ |
| Vue 3 / VitePress / Quasar / Nuxt 3 | ✅ |
| UMD/CDN build | ✅ |
| Remote consent storage | ✅ |
| Dark mode support | ✅ |
| Feature | Description |
|---------|-------------|
| CCPA support | California Consumer Privacy Act compliance |
| Analytics dashboard | Opt-in rates, banner interactions (via privacy.structured.world) |
- vue-privacy-worker — Cloudflare Worker for server-side consent storage
Apache 2.0 — see LICENSE