update
This commit is contained in:
117
Frontend/src/components/common/AnalyticsLoader.tsx
Normal file
117
Frontend/src/components/common/AnalyticsLoader.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import privacyService, {
|
||||
PublicPrivacyConfig,
|
||||
} from '../../services/api/privacyService';
|
||||
import { useCookieConsent } from '../../contexts/CookieConsentContext';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
dataLayer: any[];
|
||||
gtag: (...args: any[]) => void;
|
||||
fbq: (...args: any[]) => void;
|
||||
}
|
||||
}
|
||||
|
||||
const AnalyticsLoader: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const { consent } = useCookieConsent();
|
||||
const [config, setConfig] = useState<PublicPrivacyConfig | null>(null);
|
||||
const gaLoadedRef = useRef(false);
|
||||
const fbLoadedRef = useRef(false);
|
||||
|
||||
// Load public privacy config once
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
const loadConfig = async () => {
|
||||
try {
|
||||
const cfg = await privacyService.getPublicConfig();
|
||||
if (!mounted) return;
|
||||
setConfig(cfg);
|
||||
} catch {
|
||||
// Fail silently in production; analytics are non-critical
|
||||
}
|
||||
};
|
||||
void loadConfig();
|
||||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Load Google Analytics when allowed
|
||||
useEffect(() => {
|
||||
if (!config || !consent) return;
|
||||
const measurementId = config.integrations.ga_measurement_id;
|
||||
const analyticsAllowed =
|
||||
config.policy.analytics_enabled && consent.categories.analytics;
|
||||
if (!measurementId || !analyticsAllowed || gaLoadedRef.current) return;
|
||||
|
||||
// Inject GA script
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.src = `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(
|
||||
measurementId
|
||||
)}`;
|
||||
document.head.appendChild(script);
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(...args: any[]) {
|
||||
window.dataLayer.push(args);
|
||||
}
|
||||
window.gtag = gtag;
|
||||
gtag('js', new Date());
|
||||
gtag('config', measurementId, { anonymize_ip: true });
|
||||
|
||||
gaLoadedRef.current = true;
|
||||
|
||||
return () => {
|
||||
// We don't remove GA script on unmount; typical SPA behaviour is to keep it.
|
||||
};
|
||||
}, [config, consent]);
|
||||
|
||||
// Track GA page views on route change
|
||||
useEffect(() => {
|
||||
if (!gaLoadedRef.current || !config?.integrations.ga_measurement_id) return;
|
||||
if (typeof window.gtag !== 'function') return;
|
||||
window.gtag('config', config.integrations.ga_measurement_id, {
|
||||
page_path: location.pathname + location.search,
|
||||
});
|
||||
}, [location, config]);
|
||||
|
||||
// Load Meta Pixel when allowed
|
||||
useEffect(() => {
|
||||
if (!config || !consent) return;
|
||||
const pixelId = config.integrations.fb_pixel_id;
|
||||
const marketingAllowed =
|
||||
config.policy.marketing_enabled && consent.categories.marketing;
|
||||
if (!pixelId || !marketingAllowed || fbLoadedRef.current) return;
|
||||
|
||||
// Meta Pixel base code
|
||||
!(function (f: any, b, e, v, n?, t?, s?) {
|
||||
if (f.fbq) return;
|
||||
n = f.fbq = function () {
|
||||
(n.callMethod ? n.callMethod : n.queue.push).apply(n, arguments);
|
||||
};
|
||||
if (!f._fbq) f._fbq = n;
|
||||
(n as any).push = n;
|
||||
(n as any).loaded = true;
|
||||
(n as any).version = '2.0';
|
||||
(n as any).queue = [];
|
||||
t = b.createElement(e);
|
||||
t.async = true;
|
||||
t.src = 'https://connect.facebook.net/en_US/fbevents.js';
|
||||
s = b.getElementsByTagName(e)[0];
|
||||
s.parentNode?.insertBefore(t, s);
|
||||
})(window, document, 'script');
|
||||
|
||||
window.fbq('init', pixelId);
|
||||
window.fbq('track', 'PageView');
|
||||
fbLoadedRef.current = true;
|
||||
}, [config, consent]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default AnalyticsLoader;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user