Spaces:
Running
on
A100
Running
on
A100
| import React from "react"; | |
| import CookieBanner from "./CookieBanner"; | |
| export const CONSENT_COOKIE_NAME = "omniasr_transcription_consent"; | |
| // Declare gtag global function | |
| declare global { | |
| interface Window { | |
| gtag: (...args: any[]) => void; | |
| dataLayer: any[]; | |
| } | |
| } | |
| const Analytics = () => { | |
| const [analyticsEnabled, setAnalyticsEnabled] = React.useState(false); | |
| const [consentState, setConsentState] = React.useState<boolean | null>(null); // In-memory fallback | |
| const [showBanner, setShowBanner] = React.useState(false); // Control banner visibility | |
| // Check if we're in iframe (like HuggingFace Spaces) | |
| const isInIframe = () => { | |
| try { | |
| return window.self !== window.top; | |
| } catch (e) { | |
| return true; | |
| } | |
| }; | |
| // Get consent with fallback chain: memory -> localStorage -> sessionStorage -> cookies | |
| const getConsent = (): boolean => { | |
| // First check in-memory state (for HF spaces that block all storage) | |
| if (consentState !== null) { | |
| return consentState; | |
| } | |
| // Try localStorage | |
| try { | |
| const localValue = window.localStorage.getItem(CONSENT_COOKIE_NAME); | |
| if (localValue !== null) { | |
| return localValue === "true"; | |
| } | |
| } catch (e) {} | |
| // Try sessionStorage | |
| try { | |
| const sessionValue = window.sessionStorage.getItem(CONSENT_COOKIE_NAME); | |
| if (sessionValue !== null) { | |
| return sessionValue === "true"; | |
| } | |
| } catch (e) {} | |
| // Try cookies | |
| try { | |
| return document.cookie.includes(`${CONSENT_COOKIE_NAME}=true`); | |
| } catch (e) {} | |
| return false; | |
| }; | |
| // Set consent with fallback chain | |
| const setConsent = (accepted: boolean) => { | |
| // Always set in-memory state first (works in all environments) | |
| setConsentState(accepted); | |
| // Try localStorage | |
| try { | |
| window.localStorage.setItem(CONSENT_COOKIE_NAME, accepted.toString()); | |
| } catch (e) {} | |
| // Try sessionStorage as fallback | |
| try { | |
| window.sessionStorage.setItem(CONSENT_COOKIE_NAME, accepted.toString()); | |
| } catch (e) {} | |
| // Try cookies (mainly for non-iframe environments) | |
| if (!isInIframe()) { | |
| try { | |
| const expires = new Date(); | |
| expires.setFullYear(expires.getFullYear() + 1); | |
| document.cookie = `${CONSENT_COOKIE_NAME}=${accepted}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`; | |
| } catch (e) {} | |
| } | |
| }; | |
| // Load gtag script dynamically | |
| const loadGtagScript = (gaId: string) => { | |
| return new Promise<void>((resolve, reject) => { | |
| // Check if gtag is already loaded | |
| if (window.gtag) { | |
| resolve(); | |
| return; | |
| } | |
| // Create script element | |
| const script = document.createElement('script'); | |
| script.async = true; | |
| script.src = `https://www.googletagmanager.com/gtag/js?id=${gaId}`; | |
| script.onload = () => { | |
| // Initialize gtag | |
| window.dataLayer = window.dataLayer || []; | |
| window.gtag = function gtag() { | |
| window.dataLayer.push(arguments); | |
| }; | |
| window.gtag('js', new Date()); | |
| window.gtag('config', gaId, { | |
| // Settings for iframe environments | |
| send_page_view: false, // We'll send manually | |
| cookie_flags: 'max-age=7200;secure;samesite=none', // For iframe support | |
| }); | |
| console.log('GA: gtag script loaded'); | |
| resolve(); | |
| }; | |
| script.onerror = () => { | |
| console.error('❌ Failed to load gtag script'); | |
| reject(new Error('Failed to load gtag script')); | |
| }; | |
| document.head.appendChild(script); | |
| }); | |
| }; | |
| // Enable analytics if consent given | |
| const handleAcceptCookie = React.useCallback(() => { | |
| console.log('User accepted analytics cookies'); | |
| setConsent(true); | |
| setShowBanner(false); // Hide banner after acceptance | |
| const gaId = import.meta.env.VITE_REACT_APP_GOOGLE_ANALYTICS_ID; | |
| const analyticsEnabled = import.meta.env.VITE_ENABLE_ANALYTICS === 'true'; | |
| if (gaId && analyticsEnabled) { | |
| loadGtagScript(gaId) | |
| .then(() => { | |
| setAnalyticsEnabled(true); | |
| console.log('GA initialized successfully'); | |
| // Send initial pageview | |
| const pathname = window.location.pathname; | |
| window.gtag('event', 'page_view', { | |
| page_title: document.title, | |
| page_location: window.location.href, | |
| page_path: pathname, | |
| }); | |
| }) | |
| .catch((e) => { | |
| console.error('GA initialization failed:', e); | |
| }); | |
| } | |
| }, []); | |
| const handleDeclineCookie = React.useCallback(() => { | |
| console.log('User declined analytics cookies'); | |
| setConsent(false); | |
| setShowBanner(false); // Hide banner after decline | |
| }, []); | |
| // Check for existing consent on mount | |
| React.useEffect(() => { | |
| const existingConsent = getConsent(); | |
| if (existingConsent) { | |
| console.log('GA: Found existing consent, initializing...'); | |
| handleAcceptCookie(); | |
| setShowBanner(false); // Don't show banner if consent already exists | |
| } else { | |
| setShowBanner(true); // Show banner if no consent | |
| } | |
| }, [handleAcceptCookie]); | |
| // Note: pageview is now sent directly in handleAcceptCookie when gtag is loaded | |
| return showBanner ? ( | |
| <CookieBanner | |
| onAccept={handleAcceptCookie} | |
| onDecline={handleDeclineCookie} | |
| /> | |
| ) : null; | |
| }; | |
| export default Analytics; | |