100 lines
3.2 KiB
TypeScript
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;
|
|
}
|