'use client' import { useEffect } from 'react' import type { AnalyticsConfig } from './types.js' import { gtag } from '../consent/googleConsent.js' import { CONSENT_COOKIE, DEFAULT_CONSENT, parseConsent, setDefaultConsent } from '../consent/index.js' declare global { interface Window { dataLayer?: unknown[] } } const GTM_SCRIPT = (id: string) => `https://www.googletagmanager.com/gtm.js?id=${id}` const GA4_SCRIPT = (id: string) => `https://www.googletagmanager.com/gtag/js?id=${id}` /** Reads the current consent state from cookie, or defaults if none. */ function readConsent() { if (typeof document === 'undefined') {return DEFAULT_CONSENT} const raw = document.cookie .split('; ') .find((c) => c.startsWith(`${CONSENT_COOKIE}=`)) ?.split('=')[1] return parseConsent(raw) ?? DEFAULT_CONSENT } function injectScript(src: string) { if (document.querySelector(`script[src="${src}"]`)) {return} const s = document.createElement('script') s.src = src s.async = true document.head.appendChild(s) } /** * Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag. * * Consent Mode is initialised to the visitor's stored consent BEFORE the tag * loads (via setDefaultConsent from the consent module), so tags respect the * choice from the first hit; useConsent sends an update the moment the visitor * decides. IDs are public and come from SiteIntegrations, passed in as props * (the client project reads them server-side). * * Renders nothing — it only injects the scripts. Mount once, high in the tree * (e.g. root layout), inside ConsentProvider. */ export function Analytics({ ga4MeasurementId, gtmContainerId }: AnalyticsConfig) { useEffect(() => { if (!ga4MeasurementId && !gtmContainerId) {return} // 1. Consent Mode default = the visitor's stored choice, before tags load. setDefaultConsent(readConsent()) // 2. Load the tag. if (gtmContainerId) { window.dataLayer = window.dataLayer || [] window.dataLayer.push({ event: 'gtm.js', 'gtm.start': Date.now() }) injectScript(GTM_SCRIPT(gtmContainerId)) } else if (ga4MeasurementId) { injectScript(GA4_SCRIPT(ga4MeasurementId)) // Uses the shared gtag (pushes `arguments`, as Google's tags expect); // real gtag.js wires itself up once the script loads. gtag('js', new Date()) gtag('config', ga4MeasurementId) } }, [ga4MeasurementId, gtmContainerId]) return null }