@jwiedeman/gtm-kit-vue
v1.2.2
Published
Vue 3 composables and plugin for GTM Kit - Google Tag Manager integration with Vue Router support.
Maintainers
Readme
@jwiedeman/gtm-kit-vue
Vue 3 plugin and composables for Google Tag Manager. Composition API ready.
The Vue adapter for GTM Kit - provides a plugin and composables for clean Vue integration.
Installation
npm install @jwiedeman/gtm-kit @jwiedeman/gtm-kit-vueyarn add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-vuepnpm add @jwiedeman/gtm-kit @jwiedeman/gtm-kit-vueQuick Start
Step 1: Add Plugin
// main.ts
import { createApp } from 'vue';
import { GtmPlugin } from '@jwiedeman/gtm-kit-vue';
import App from './App.vue';
createApp(App).use(GtmPlugin, { containers: 'GTM-XXXXXX' }).mount('#app');Step 2: Push Events
<script setup>
import { useGtm } from '@jwiedeman/gtm-kit-vue';
const { push } = useGtm();
function handleClick() {
push({ event: 'purchase', value: 49.99 });
}
</script>
<template>
<button @click="handleClick">Buy Now</button>
</template>That's it! GTM is now running.
Features
| Feature | Description | | ------------------- | ------------------------------ | | Vue 3 Native | Built for Composition API | | Composables | Clean, reactive Vue patterns | | TypeScript | Full type definitions included | | Consent Mode v2 | Built-in GDPR compliance | | SSR Compatible | Safe for Nuxt and Vite SSR | | Lightweight | ~4KB gzipped |
Available Composables
useGtm()
Get the full GTM API.
<script setup>
import { useGtm } from '@jwiedeman/gtm-kit-vue';
const { client, push, updateConsent, setConsentDefaults } = useGtm();
push({ event: 'page_view', page_path: '/' });
</script>useGtmPush()
Get just the push function.
<script setup>
import { useGtmPush } from '@jwiedeman/gtm-kit-vue';
const push = useGtmPush();
push({ event: 'button_click', button_id: 'cta-main' });
</script>useGtmConsent()
Manage consent state.
<script setup>
import { useGtmConsent } from '@jwiedeman/gtm-kit-vue';
const { updateConsent } = useGtmConsent();
function acceptAll() {
updateConsent({
ad_storage: 'granted',
analytics_storage: 'granted',
ad_user_data: 'granted',
ad_personalization: 'granted'
});
}
</script>useGtmClient()
Get the raw GTM client instance.
<script setup>
import { useGtmClient } from '@jwiedeman/gtm-kit-vue';
const client = useGtmClient();
onMounted(async () => {
await client.whenReady();
console.log('GTM is ready!');
});
</script>useGtmReady()
Get a function that resolves when GTM is loaded.
<script setup>
import { useGtmReady } from '@jwiedeman/gtm-kit-vue';
const whenReady = useGtmReady();
onMounted(async () => {
await whenReady();
console.log('GTM scripts loaded!');
});
</script>Plugin Options
app.use(GtmPlugin, {
containers: 'GTM-XXXXXX', // Required
dataLayerName: 'dataLayer', // Optional
host: 'https://custom.host.com', // Optional
scriptAttributes: { nonce: '...' }, // Optional: CSP
onBeforeInit: (client) => {
// Called before GTM initializes
// Perfect for consent defaults
},
onAfterInit: (client) => {
// Called after GTM initializes
}
});Vue Router Integration
<script setup>
import { useGtm } from '@jwiedeman/gtm-kit-vue';
import { watch } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const { push } = useGtm();
watch(
() => route.fullPath,
(path) => {
push({ event: 'page_view', page_path: path });
}
);
</script>Or create a reusable composable:
// composables/usePageTracking.ts
import { useGtm } from '@jwiedeman/gtm-kit-vue';
import { watch, onMounted } from 'vue';
import { useRoute } from 'vue-router';
export function usePageTracking() {
const route = useRoute();
const { push } = useGtm();
onMounted(() => {
// Track initial page
push({ event: 'page_view', page_path: route.fullPath });
});
watch(
() => route.fullPath,
(path, oldPath) => {
if (path !== oldPath) {
push({ event: 'page_view', page_path: path });
}
}
);
}Consent Mode v2 (GDPR)
// main.ts
import { createApp } from 'vue';
import { GtmPlugin } from '@jwiedeman/gtm-kit-vue';
import { consentPresets } from '@jwiedeman/gtm-kit';
import App from './App.vue';
createApp(App)
.use(GtmPlugin, {
containers: 'GTM-XXXXXX',
onBeforeInit: (client) => {
// Deny by default for EU users
client.setConsentDefaults(consentPresets.eeaDefault, { region: ['EEA'] });
}
})
.mount('#app');<!-- CookieBanner.vue -->
<script setup>
import { useGtmConsent } from '@jwiedeman/gtm-kit-vue';
import { consentPresets } from '@jwiedeman/gtm-kit';
const { updateConsent } = useGtmConsent();
// Accept all tracking
const acceptAll = () => updateConsent(consentPresets.allGranted);
// Reject all tracking
const rejectAll = () => updateConsent(consentPresets.eeaDefault);
// Analytics only (mixed consent)
const analyticsOnly = () => updateConsent(consentPresets.analyticsOnly);
// Granular: custom selection
const customChoice = () =>
updateConsent({
analytics_storage: 'granted',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied'
});
</script>
<template>
<div class="cookie-banner">
<p>We use cookies to improve your experience.</p>
<button @click="acceptAll">Accept All</button>
<button @click="rejectAll">Reject All</button>
<button @click="analyticsOnly">Analytics Only</button>
</div>
</template>Partial Updates - Only update changed categories:
<script setup>
import { useGtmConsent } from '@jwiedeman/gtm-kit-vue';
const { updateConsent } = useGtmConsent();
// User later opts into ads from preference center
const enableAds = () =>
updateConsent({
ad_storage: 'granted',
ad_user_data: 'granted'
});
// Other categories (analytics_storage, ad_personalization) remain unchanged
</script>Nuxt 3
For Nuxt 3 projects, use @jwiedeman/gtm-kit-nuxt which provides:
- Native Nuxt module integration
- Auto-import of composables
- Automatic page tracking
- SSR support out of the box
Requirements
- Vue 3.3+
@jwiedeman/gtm-kit(peer dependency)
Related Packages
- Core: @jwiedeman/gtm-kit (required)
- Nuxt 3: @jwiedeman/gtm-kit-nuxt
Support
Have a question, found a bug, or need help?
Open an issue on GitHub — we're actively maintaining this project and respond quickly.
License
MIT
