Spaces:
Running
on
A100
Running
on
A100
File size: 5,381 Bytes
ae238b3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
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;
|