canina/frontend/application/components/AnalyticsDeferred.tsx

100 lines
3.2 KiB
TypeScript

'use client';
import { useEffect } from 'react';
declare global {
interface Window {
dataLayer?: any[];
clarity?: any;
}
}
interface AnalyticsDeferredProps {
gtmId?: string;
gaId?: string;
clarityId?: string;
}
export default function AnalyticsDeferred({ gtmId, gaId, clarityId }: AnalyticsDeferredProps) {
useEffect(() => {
let loaded = false;
const loadAnalytics = () => {
if (loaded) return;
loaded = true;
// Clean up event listeners
window.removeEventListener('scroll', loadAnalytics);
window.removeEventListener('touchstart', loadAnalytics);
window.removeEventListener('mousemove', loadAnalytics);
window.removeEventListener('keydown', loadAnalytics);
// 1. Google Tag Manager
if (gtmId) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
const gtmScript = document.createElement('script');
gtmScript.async = true;
gtmScript.src = `https://www.googletagmanager.com/gtm.js?id=${gtmId}`;
document.head.appendChild(gtmScript);
}
// 2. Google Analytics 4 (if standalone without GTM)
if (gaId && !gtmId) {
window.dataLayer = window.dataLayer || [];
function gtag(...args: any[]) {
window.dataLayer?.push(args);
}
gtag('js', new Date());
gtag('config', gaId, { page_path: window.location.pathname });
const gaScript = document.createElement('script');
gaScript.async = true;
gaScript.src = `https://www.googletagmanager.com/gtag/js?id=${gaId}`;
document.head.appendChild(gaScript);
}
// 3. Microsoft Clarity
if (clarityId) {
(function (c: any, l: any, a: any, r: any, i: any) {
c[a] =
c[a] ||
function (...args: unknown[]) {
(c[a].q = c[a].q || []).push(args);
};
const t = l.createElement(r);
t.async = 1;
t.src = 'https://www.clarity.ms/tag/' + i;
const y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, 'clarity', 'script', clarityId);
}
};
// Listen to first user interaction
window.addEventListener('scroll', loadAnalytics, { passive: true, once: true });
window.addEventListener('touchstart', loadAnalytics, { passive: true, once: true });
window.addEventListener('mousemove', loadAnalytics, { passive: true, once: true });
window.addEventListener('keydown', loadAnalytics, { passive: true, once: true });
// Fallback: idle execution after 3.5s
const timer = setTimeout(() => {
if (typeof window !== 'undefined' && 'requestIdleCallback' in window) {
(window as any).requestIdleCallback(loadAnalytics, { timeout: 2000 });
} else {
loadAnalytics();
}
}, 3500);
return () => {
clearTimeout(timer);
window.removeEventListener('scroll', loadAnalytics);
window.removeEventListener('touchstart', loadAnalytics);
window.removeEventListener('mousemove', loadAnalytics);
window.removeEventListener('keydown', loadAnalytics);
};
}, [gtmId, gaId, clarityId]);
return null;
}