Cookie consent banner linking to posthog

This commit is contained in:
Connor Yoh 2025-08-28 17:20:16 +01:00
parent f3323ffeb3
commit 48d9e86c6c
2 changed files with 41 additions and 39 deletions

View File

@ -26,7 +26,6 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
// Prevent double initialization // Prevent double initialization
if (window.CookieConsent) { if (window.CookieConsent) {
console.log('Cookie consent already loaded, forcing show...');
setIsInitialized(true); setIsInitialized(true);
// Force show the modal if it exists but isn't visible // Force show the modal if it exists but isn't visible
setTimeout(() => { setTimeout(() => {
@ -35,38 +34,34 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
return; return;
} }
console.log('Loading cookie consent library...');
// Load the cookie consent CSS files first // Load the cookie consent CSS files first
const mainCSS = document.createElement('link'); const mainCSS = document.createElement('link');
mainCSS.rel = 'stylesheet'; mainCSS.rel = 'stylesheet';
mainCSS.href = '/css/cookieconsent.css'; mainCSS.href = '/css/cookieconsent.css';
document.head.appendChild(mainCSS); document.head.appendChild(mainCSS);
const customCSS = document.createElement('link'); const customCSS = document.createElement('link');
customCSS.rel = 'stylesheet'; customCSS.rel = 'stylesheet';
customCSS.href = '/css/cookieconsentCustomisation.css'; customCSS.href = '/css/cookieconsentCustomisation.css';
document.head.appendChild(customCSS); document.head.appendChild(customCSS);
// Load the cookie consent library // Load the cookie consent library
const script = document.createElement('script'); const script = document.createElement('script');
script.src = '/js/thirdParty/cookieconsent.umd.js'; script.src = '/js/thirdParty/cookieconsent.umd.js';
script.onload = () => { script.onload = () => {
console.log('Cookie consent script loaded successfully');
// Small delay to ensure DOM is ready // Small delay to ensure DOM is ready
setTimeout(() => { setTimeout(() => {
console.log('Initializing cookie consent...');
// Detect current theme and set appropriate mode // Detect current theme and set appropriate mode
const detectTheme = () => { const detectTheme = () => {
const mantineScheme = document.documentElement.getAttribute('data-mantine-color-scheme'); const mantineScheme = document.documentElement.getAttribute('data-mantine-color-scheme');
const hasLightClass = document.documentElement.classList.contains('light'); const hasLightClass = document.documentElement.classList.contains('light');
const hasDarkClass = document.documentElement.classList.contains('dark'); const hasDarkClass = document.documentElement.classList.contains('dark');
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
// Priority: Mantine attribute > CSS classes > system preference // Priority: Mantine attribute > CSS classes > system preference
let isDarkMode = false; let isDarkMode = false;
if (mantineScheme) { if (mantineScheme) {
isDarkMode = mantineScheme === 'dark'; isDarkMode = mantineScheme === 'dark';
} else if (hasLightClass) { } else if (hasLightClass) {
@ -76,15 +71,13 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
} else { } else {
isDarkMode = systemPrefersDark; isDarkMode = systemPrefersDark;
} }
console.log('Theme detection:', { mantineScheme, hasLightClass, hasDarkClass, systemPrefersDark, isDarkMode });
// Always explicitly set or remove the class // Always explicitly set or remove the class
document.documentElement.classList.toggle('cc--darkmode', isDarkMode); document.documentElement.classList.toggle('cc--darkmode', isDarkMode);
return isDarkMode; return isDarkMode;
}; };
// Initial theme detection with slight delay to ensure DOM is ready // Initial theme detection with slight delay to ensure DOM is ready
setTimeout(() => { setTimeout(() => {
detectTheme(); detectTheme();
@ -95,26 +88,23 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
console.error('CookieConsent is not available on window object'); console.error('CookieConsent is not available on window object');
return; return;
} }
// Listen for theme changes // Listen for theme changes
const themeObserver = new MutationObserver((mutations) => { const themeObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => { mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && if (mutation.type === 'attributes' &&
(mutation.attributeName === 'data-mantine-color-scheme' || (mutation.attributeName === 'data-mantine-color-scheme' ||
mutation.attributeName === 'class')) { mutation.attributeName === 'class')) {
console.log('Theme changed, re-detecting...');
detectTheme(); detectTheme();
} }
}); });
}); });
themeObserver.observe(document.documentElement, { themeObserver.observe(document.documentElement, {
attributes: true, attributes: true,
attributeFilter: ['data-mantine-color-scheme', 'class'] attributeFilter: ['data-mantine-color-scheme', 'class']
}); });
// Clear any existing cookie to force show
document.cookie = 'cc_cookie=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';
// Initialize cookie consent with full configuration // Initialize cookie consent with full configuration
try { try {
@ -190,26 +180,20 @@ export const useCookieConsent = ({ analyticsEnabled = false }: CookieConsentConf
} }
} }
}); });
// Force show after initialization // Force show after initialization
setTimeout(() => { setTimeout(() => {
console.log('Forcing cookie consent to show...');
window.CookieConsent.show(); window.CookieConsent.show();
// Debug: Check if modal elements exist // Debug: Check if modal elements exist
const ccMain = document.getElementById('cc-main'); const ccMain = document.getElementById('cc-main');
const consentModal = document.querySelector('.cm-wrapper'); const consentModal = document.querySelector('.cm-wrapper');
console.log('cc-main element:', ccMain);
console.log('consent modal element:', consentModal);
if (ccMain) {
console.log('cc-main styles:', window.getComputedStyle(ccMain));
}
}, 200); }, 200);
} catch (error) { } catch (error) {
console.error('Error initializing CookieConsent:', error); console.error('Error initializing CookieConsent:', error);
} }
console.log('Cookie consent initialized successfully');
setIsInitialized(true); setIsInitialized(true);
}, 100); // Small delay to ensure DOM is ready }, 100); // Small delay to ensure DOM is ready
}; };

View File

@ -7,6 +7,7 @@ import { ColorSchemeScript } from '@mantine/core';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import App from './App'; import App from './App';
import './i18n'; // Initialize i18next import './i18n'; // Initialize i18next
import posthog from 'posthog-js';
import { PostHogProvider } from 'posthog-js/react'; import { PostHogProvider } from 'posthog-js/react';
// Compute initial color scheme // Compute initial color scheme
@ -21,22 +22,39 @@ function getInitialScheme(): 'light' | 'dark' {
} }
} }
posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, {
api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
defaults: '2025-05-24',
capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this
debug: false,
opt_out_capturing_by_default: false, // We handle opt-out via cookie consent
});
function UpdatePosthogConsent(){
if(typeof(posthog) == "undefined") {
return;
}
const optIn = (window.CookieConsent as any).acceptedCategory('analytics');
optIn?
posthog.opt_in_capturing() : posthog.opt_out_capturing();
console.log("Updated analytics consent: ", optIn? "opted in" : "opted out");
}
window.addEventListener("cc:onConsent", UpdatePosthogConsent);
window.addEventListener("cc:onChange", UpdatePosthogConsent);
const container = document.getElementById('root'); const container = document.getElementById('root');
if (!container) { if (!container) {
throw new Error("Root container missing in index.html"); throw new Error("Root container missing in index.html");
} }
const root = ReactDOM.createRoot(container); // Finds the root DOM element const root = ReactDOM.createRoot(container); // Finds the root DOM element
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<ColorSchemeScript defaultColorScheme={getInitialScheme()} /> <ColorSchemeScript defaultColorScheme={getInitialScheme()} />
<PostHogProvider <PostHogProvider
apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY} client={posthog}
options={{
api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST,
defaults: '2025-05-24',
capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this
debug: import.meta.env.MODE === 'development',
}}
> >
<BrowserRouter> <BrowserRouter>
<App /> <App />