diff --git a/apps/web-roo-code/src/components/providers/google-analytics-provider.tsx b/apps/web-roo-code/src/components/providers/google-analytics-provider.tsx index 3d274db5090f..7c0a7edfc62c 100644 --- a/apps/web-roo-code/src/components/providers/google-analytics-provider.tsx +++ b/apps/web-roo-code/src/components/providers/google-analytics-provider.tsx @@ -8,146 +8,53 @@ import { hasConsent, onConsentChange } from "@/lib/analytics/consent-manager" const GTM_ID = "AW-17391954825" /** - * Google Analytics Provider with Consent Mode v2 - * Implements cookieless pings and advanced consent management + * Google Analytics Provider + * Implements Google's standard gtag.js loading pattern */ export function GoogleAnalyticsProvider({ children }: { children: React.ReactNode }) { const [shouldLoad, setShouldLoad] = useState(false) useEffect(() => { - // Initialize consent defaults BEFORE loading gtag.js (required for Consent Mode v2) - initializeConsentDefaults() - // Check initial consent status if (hasConsent()) { setShouldLoad(true) - updateConsentGranted() } // Listen for consent changes const unsubscribe = onConsentChange((consented) => { if (consented) { - if (!shouldLoad) { - setShouldLoad(true) - } - updateConsentGranted() - } else { - updateConsentDenied() + setShouldLoad(true) } }) return unsubscribe - // eslint-disable-next-line react-hooks/exhaustive-deps -- shouldLoad intentionally omitted to prevent re-initialization loop }, []) - const initializeConsentDefaults = () => { - // Set up consent defaults before gtag loads (Consent Mode v2 requirement) - if (typeof window !== "undefined") { - window.dataLayer = window.dataLayer || [] - window.gtag = function (...args: GtagArgs) { - window.dataLayer.push(args) - } - - // Set default consent state to 'denied' with cookieless pings enabled - window.gtag("consent", "default", { - ad_storage: "denied", - ad_user_data: "denied", - ad_personalization: "denied", - analytics_storage: "denied", - functionality_storage: "denied", - personalization_storage: "denied", - security_storage: "granted", // Always granted for security - wait_for_update: 500, // Wait 500ms for consent before sending data - }) - - // Enable cookieless pings for Google Ads - window.gtag("set", "url_passthrough", true) - } - } - - const updateConsentGranted = () => { - // User accepted cookies - update consent to granted - if (typeof window !== "undefined" && window.gtag) { - window.gtag("consent", "update", { - ad_storage: "granted", - ad_user_data: "granted", - ad_personalization: "granted", - analytics_storage: "granted", - functionality_storage: "granted", - personalization_storage: "granted", - }) - } - } - - const updateConsentDenied = () => { - // User declined cookies - keep consent denied (cookieless pings still work) - if (typeof window !== "undefined" && window.gtag) { - window.gtag("consent", "update", { - ad_storage: "denied", - ad_user_data: "denied", - ad_personalization: "denied", - analytics_storage: "denied", - functionality_storage: "denied", - personalization_storage: "denied", - }) - } - } - - // Always render scripts (Consent Mode v2 needs gtag loaded even without consent) - // Cookieless pings will work with denied consent - return ( <> - {/* Google tag (gtag.js) - Loads immediately for Consent Mode v2 */} - + + )} {children} ) } -// Type definitions for Google Analytics with Consent Mode v2 -type ConsentState = "granted" | "denied" - -interface ConsentParams { - ad_storage?: ConsentState - ad_user_data?: ConsentState - ad_personalization?: ConsentState - analytics_storage?: ConsentState - functionality_storage?: ConsentState - personalization_storage?: ConsentState - security_storage?: ConsentState - wait_for_update?: number -} - -type GtagArgs = - | ["js", Date] - | ["config", string, GtagConfig?] - | ["event", string, GtagEventParameters?] - | ["consent", "default" | "update", ConsentParams] - | ["set", string, unknown] - -interface GtagConfig { - [key: string]: unknown -} - -interface GtagEventParameters { - [key: string]: unknown -} - // Declare global types for TypeScript declare global { interface Window { - dataLayer: GtagArgs[] - gtag: (...args: GtagArgs) => void + dataLayer: unknown[] + gtag: (...args: unknown[]) => void } }