diff --git a/docs/content/scripts/tracking/google-tag-manager.md b/docs/content/scripts/tracking/google-tag-manager.md index bcdb544c..124e0056 100644 --- a/docs/content/scripts/tracking/google-tag-manager.md +++ b/docs/content/scripts/tracking/google-tag-manager.md @@ -128,12 +128,18 @@ export const GoogleTagManagerOptions = object({ id: string(), /** * The name of the dataLayer you want to use - * @default 'defaultGtm' + * @default 'dataLayer' */ dataLayerName: optional(string()) }) ``` +### Options types + +```ts +type GoogleTagManagerInput = typeof GoogleTagManagerOptions & { onBeforeGtmStart?: ((gtag: Gtag) => void) => void } +``` + ## Example Using Google Tag Manager only in production while using `dataLayer` to send a conversion event. @@ -163,3 +169,9 @@ function sendConversion() { :: + +## Configuring GTM before it starts + +`useScriptGoogleTagManager` initialize Google Tag Manager by itself. This means it pushes the `js`, `config` and the `gtm.start` events for you. + +If you need to configure GTM before it starts. For example, (setting the consent mode)[https://developers.google.com/tag-platform/security/guides/consent?hl=fr&consentmode=basic]. You can use the `onBeforeGtmStart` hook which is run right before we push the `gtm.start` event into the dataLayer. \ No newline at end of file diff --git a/playground/pages/third-parties/google-tag-manager.vue b/playground/pages/third-parties/google-tag-manager.vue index 18978db2..911c8141 100644 --- a/playground/pages/third-parties/google-tag-manager.vue +++ b/playground/pages/third-parties/google-tag-manager.vue @@ -8,6 +8,15 @@ useHead({ // composables return the underlying api as a proxy object and the script state const { dataLayer, then, status } = useScriptGoogleTagManager({ id: 'GTM-MNJD4B', + onBeforeGtmStart(gtag) { + gtag('consent', 'default', { + ad_user_data: 'denied', + ad_personalization: 'denied', + ad_storage: 'denied', + analytics_storage: 'denied', + wait_for_update: 500, + }) + }, }) // id is set via runtime config dataLayer.push({ event: 'page_view', diff --git a/src/runtime/registry/google-analytics.ts b/src/runtime/registry/google-analytics.ts index bef523cd..ab8a53d4 100644 --- a/src/runtime/registry/google-analytics.ts +++ b/src/runtime/registry/google-analytics.ts @@ -10,7 +10,7 @@ export interface GTag { (fn: 'config' | 'get', opt: string): void (fn: 'event', opt: string, opt2?: Record): void (fn: 'set', opt: Record): void - (fn: 'consent', opt: ConsentOptions, opt2: Record): void + (fn: 'consent', opt: ConsentOptions, opt2: Record): void } type DataLayer = Array | Record> diff --git a/src/runtime/registry/google-tag-manager.ts b/src/runtime/registry/google-tag-manager.ts index 5b41e1e7..4af85cf6 100644 --- a/src/runtime/registry/google-tag-manager.ts +++ b/src/runtime/registry/google-tag-manager.ts @@ -41,7 +41,7 @@ export const GoogleTagManagerOptions = object({ export type GoogleTagManagerInput = RegistryScriptInput -export function useScriptGoogleTagManager(_options?: GoogleTagManagerInput) { +export function useScriptGoogleTagManager(_options?: GoogleTagManagerInput & { onBeforeGtmStart?: (gtag: GTag) => void }) { return useRegistryScript(_options?.key || 'googleTagManager', options => ({ scriptInput: { src: withQuery('https://www.googletagmanager.com/gtm.js', { id: options?.id, l: options?.l }), @@ -53,13 +53,18 @@ export function useScriptGoogleTagManager(_option }, stub: import.meta.client ? undefined : ({ fn }) => { return fn === 'dataLayer' ? [] : void 0 }, performanceMarkFeature: 'nuxt-third-parties-gtm', - ...({ tagPriority: 1 }), + tagPriority: 1, }, clientInit: import.meta.server ? undefined : () => { const dataLayerName = options?.l ?? 'dataLayer'; (window as any)[dataLayerName] = (window as any)[(options?.l ?? 'dataLayer')] || [] + function gtag() { + // eslint-disable-next-line prefer-rest-params + (window as any)[dataLayerName].push(arguments) + } + _options?.onBeforeGtmStart?.(gtag) ;(window as any)[dataLayerName].push({ 'gtm.start': new Date().getTime(), 'event': 'gtm.js' }) }, }), _options)