gdpr-compliance-kit/components/GDPRAnalytics.tsx

123 lines
3.0 KiB
TypeScript

"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 (
* <html>
* <body>
* {children}
* <GDPRAnalytics />
* </body>
* </html>
* );
* }
*/
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 <Analytics />;
}
/**
* 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;
}
}