"use client"; import Script from "next/script"; import { useCallback, useEffect, useRef, useState } from "react"; import { type AnalyticsConsent, CONSENT_STORAGE_KEY, COOKIE_BAR_ID, GA_DISABLE_KEY, GA_MEASUREMENT_ID, GOOGLE_ADS_ID, type Gtag, OPEN_COOKIE_PREFERENCES_EVENT, readConsent, } from "@/lib/analytics"; import "./conversion.css"; const GA_SCRIPT_SRC = `https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`; const SITE_DOMAIN = "evandro.dev.br"; const deniedConsent = { analytics_storage: "denied", ad_storage: "denied", ad_user_data: "denied", ad_personalization: "denied", } as const; function persistConsent(value: AnalyticsConsent): boolean { try { localStorage.setItem(CONSENT_STORAGE_KEY, value); return true; } catch { return false; } } function getGtag(): Gtag { window.dataLayer ??= []; const dataLayer = window.dataLayer; if (!window.gtag) { window.gtag = function gtag() { // biome-ignore lint/complexity/noArguments: The official gtag bootstrap requires an IArguments entry, not an Array. dataLayer.push(arguments); }; } return window.gtag; } function removeAnalyticsLoader() { document.getElementById("google-analytics-script")?.remove(); } function writeCookie(value: string) { // biome-ignore lint/suspicious/noDocumentCookie: Cookie Store is not universal and domain-scoped GA cookies must also be expired. document.cookie = value; } function expireAnalyticsCookies() { const cookieNames = new Set( document.cookie .split(";") .map((cookie) => cookie.split("=")[0]?.trim()) .filter( (name): name is string => name === "_ga" || Boolean(name?.startsWith("_ga_")), ), ); const { hostname } = window.location; const domains = hostname === SITE_DOMAIN || hostname.endsWith(`.${SITE_DOMAIN}`) ? new Set([hostname, SITE_DOMAIN]) : new Set(); for (const name of cookieNames) { const expiration = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; SameSite=Lax`; writeCookie(expiration); for (const domain of domains) { writeCookie(`${expiration}; Domain=${domain}`); } } } const barButtonClassName = "cv-btn inline-flex min-h-10 min-w-11 items-center justify-center border px-[10px] py-sp-1 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--ink)] motion-reduce:transition-none"; function GoogleAnalyticsConsent() { const [consent, setConsent] = useState(); const [preferencesOpen, setPreferencesOpen] = useState(false); const [consentError, setConsentError] = useState(null); const configuredRef = useRef(false); const barRef = useRef(null); const acceptRef = useRef(null); const openerRef = useRef(null); const enableAnalytics = useCallback(() => { const gtag = getGtag(); window[GA_DISABLE_KEY] = false; if (!configuredRef.current) { gtag("consent", "default", deniedConsent); gtag("set", "ads_data_redaction", true); gtag("js", new Date()); configuredRef.current = true; } gtag("consent", "update", { ...deniedConsent, analytics_storage: "granted", }); gtag("config", GA_MEASUREMENT_ID, { allow_ad_personalization_signals: false, anonymize_ip: true, }); // One loader serves both destinations; GT IDs are aliases, not extra installs. gtag("config", GOOGLE_ADS_ID, { allow_ad_personalization_signals: false, }); }, []); useEffect(() => { const storedConsent = readConsent(); if (storedConsent === "granted") enableAnalytics(); setConsent(storedConsent); }, [enableAnalytics]); useEffect(() => { if (consent !== "granted" && consent !== undefined) { removeAnalyticsLoader(); } }, [consent]); // O link "Preferências de cookies" do rodapé reabre a barra; quem pediu recebe o foco de volta ao fechar. useEffect(() => { const reopen = () => { openerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null; setPreferencesOpen(true); }; window.addEventListener(OPEN_COOKIE_PREFERENCES_EVENT, reopen); return () => window.removeEventListener(OPEN_COOKIE_PREFERENCES_EVENT, reopen); }, []); const barOpen = consent === null || preferencesOpen; // Enquanto a barra está na tela, publica a altura dela para o botão flutuante do WhatsApp subir. useEffect(() => { const bar = barRef.current; if (!barOpen || !bar) return; const root = document.documentElement; const publish = () => root.style.setProperty("--cookie-bar-height", `${bar.offsetHeight}px`); publish(); root.setAttribute("data-cookie-bar", "open"); const observer = new ResizeObserver(publish); observer.observe(bar); return () => { observer.disconnect(); root.style.removeProperty("--cookie-bar-height"); root.removeAttribute("data-cookie-bar"); }; }, [barOpen]); // Reaberta pelo rodapé, a barra está no começo do documento: leva o foco para ela. useEffect(() => { if (preferencesOpen) acceptRef.current?.focus(); }, [preferencesOpen]); function closePreferences() { setPreferencesOpen(false); openerRef.current?.focus(); openerRef.current = null; } function acceptAnalytics() { if (consent === "granted") { closePreferences(); return; } if (!persistConsent("granted")) { setConsentError( "Não foi possível salvar sua aceitação. Tente novamente para concluir.", ); return; } setConsentError(null); enableAnalytics(); setConsent("granted"); closePreferences(); } function denyAnalytics() { const revoking = consent === "granted"; if (!persistConsent("denied")) { setConsentError( revoking ? "Não foi possível salvar a revogação. Tente novamente para concluir." : "Não foi possível salvar sua recusa. Tente novamente para concluir.", ); return; } setConsentError(null); if (revoking) { window[GA_DISABLE_KEY] = true; window.gtag?.("consent", "update", deniedConsent); expireAnalyticsCookies(); } setConsent("denied"); closePreferences(); } if (consent === undefined) return null; return ( <> {consent === "granted" && process.env.NODE_ENV === "production" && (