import { useEffect } from 'react'; import { usePage } from '@inertiajs/react'; import { useConsent } from '@/contexts/consent'; export type MatomoConfig = { enabled: boolean; url?: string; siteId?: string; }; declare global { interface Window { _paq?: Array<[string, ...unknown[]]>; __matomoInitialized?: boolean; __CSP_NONCE?: string; } } interface MatomoTrackerProps { config: MatomoConfig | undefined; } const MatomoTracker: React.FC = ({ config }) => { const page = usePage<{ security?: { csp?: { scriptNonce?: string } } }>(); const { hasConsent } = useConsent(); const scriptNonce = (page.props.security as { csp?: { scriptNonce?: string } } | undefined)?.csp?.scriptNonce; const analyticsConsent = hasConsent('analytics'); useEffect(() => { if (!config?.enabled || !config.url || !config.siteId || typeof window === 'undefined') { return; } const base = config.url.replace(/\/$/, ''); const scriptSelector = `script[data-matomo="${base}"]`; if (!analyticsConsent) { const existing = document.querySelector(scriptSelector); existing?.remove(); if (window._paq) { window._paq.length = 0; } delete window.__matomoInitialized; return; } window._paq = window._paq || []; const { _paq } = window; if (!window.__matomoInitialized) { _paq.push(['setTrackerUrl', `${base}/matomo.php`]); _paq.push(['setSiteId', config.siteId]); _paq.push(['disableCookies']); _paq.push(['enableLinkTracking']); if (!document.querySelector(scriptSelector)) { const script = document.createElement('script'); script.async = true; script.src = `${base}/matomo.js`; script.dataset.matomo = base; if (scriptNonce) { script.setAttribute('nonce', scriptNonce); } else if (typeof window !== 'undefined' && window.__CSP_NONCE) { script.setAttribute('nonce', window.__CSP_NONCE); } else { const metaNonce = document .querySelector('meta[name="csp-nonce"]') ?.getAttribute('content'); if (metaNonce) { script.setAttribute('nonce', metaNonce); } } document.body.appendChild(script); } window.__matomoInitialized = true; } }, [config, analyticsConsent, scriptNonce]); useEffect(() => { if ( !config?.enabled || !config.url || !config.siteId || typeof window === 'undefined' || !analyticsConsent ) { return; } window._paq = window._paq || []; const { _paq } = window; const currentUrl = typeof window !== 'undefined' ? `${window.location.origin}${page.url}` : page.url; _paq.push(['setCustomUrl', currentUrl]); if (typeof document !== 'undefined') { _paq.push(['setDocumentTitle', document.title]); } _paq.push(['trackPageView']); }, [config, analyticsConsent, page.url]); if (!config?.enabled || !config.url || !config.siteId || !analyticsConsent) { return null; } const base = config.url.replace(/\/$/, ''); const noscriptSrc = `${base}/matomo.php?idsite=${encodeURIComponent(config.siteId)}&rec=1`; return ( ); }; export default MatomoTracker;