"use client"; import { useEffect, useState } from "react"; import { Analytics } from "@vercel/analytics/react"; const CONSENT_COOKIE_NAME = "gdpr_consent"; /** * GDPR-Compliant Analytics Wrapper * * This component wraps Vercel Analytics (or any analytics provider) * and only loads it if the user has consented to analytics cookies. * * Usage in your layout.tsx: * * import { GDPRAnalytics } from "@/components/GDPRAnalytics"; * * export default function RootLayout({ children }) { * return ( * * * {children} * * * * ); * } */ export function GDPRAnalytics() { const [analyticsEnabled, setAnalyticsEnabled] = useState(false); useEffect(() => { const checkConsent = () => { const savedConsent = localStorage.getItem(CONSENT_COOKIE_NAME); if (savedConsent) { try { const parsed = JSON.parse(savedConsent); setAnalyticsEnabled(parsed.analytics === true); } catch { setAnalyticsEnabled(false); } } }; // Check on mount checkConsent(); // Listen for consent changes const handleStorageChange = (e: StorageEvent) => { if (e.key === CONSENT_COOKIE_NAME) { checkConsent(); } }; window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); }, []); // Only render Analytics if user has consented if (!analyticsEnabled) { return null; } return ; } /** * Alternative: Google Analytics 4 GDPR wrapper * * If you use Google Analytics instead of Vercel Analytics, * use this component. */ export function GDPRGoogleAnalytics({ measurementId }: { measurementId: string }) { const [analyticsEnabled, setAnalyticsEnabled] = useState(false); useEffect(() => { const savedConsent = localStorage.getItem(CONSENT_COOKIE_NAME); if (savedConsent) { try { const parsed = JSON.parse(savedConsent); setAnalyticsEnabled(parsed.analytics === true); } catch { setAnalyticsEnabled(false); } } }, []); useEffect(() => { if (!analyticsEnabled) return; // Load Google Analytics script dynamically const script = document.createElement("script"); script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`; script.async = true; document.head.appendChild(script); // Initialize gtag window.dataLayer = window.dataLayer || []; function gtag(...args: unknown[]) { window.dataLayer.push(args); } gtag("js", new Date()); gtag("config", measurementId, { anonymize_ip: true, // GDPR requirement cookie_flags: "SameSite=None;Secure", }); return () => { document.head.removeChild(script); }; }, [analyticsEnabled, measurementId]); return null; } // Type declaration for Google Analytics declare global { interface Window { dataLayer: unknown[]; gtag?: (...args: unknown[]) => void; } }