From 57655410ab03fd32c26de83978a8e7a3c1903a48 Mon Sep 17 00:00:00 2001 From: dwindown Date: Wed, 24 Sep 2025 01:15:20 +0700 Subject: [PATCH] feat: optimize analytics and mobile UI improvements Analytics & Consent Optimization: - Auto-grant all consent for non-EEA users (maximize analytics data) - EEA users still see consent banner (GDPR compliant) - Removed debugging console logs from consent system - Analytics now works in both development and production Mobile UI Improvements: - Fixed feature list layout on homepage (responsive flex layout) - Improved consent banner button styling (better padding, full-width on mobile) - Fixed mobile dropdown menu positioning (now sticky to header with overlay) - Enhanced mobile navigation UX with proper z-index and backdrop Legal Compliance: - EEA users: Explicit consent required (GDPR compliant) - Non-EEA users: Automatic tracking (legal, maximizes data collection) - Maintains privacy-first approach while optimizing analytics coverage --- src/components/ConsentBanner.js | 14 ++++---- src/components/Layout.js | 11 ++++++- src/pages/Home.js | 2 +- src/utils/analytics.js | 34 ++++++++++++++----- src/utils/consentManager.js | 58 ++++++++++++++++++++++++++------- 5 files changed, 90 insertions(+), 29 deletions(-) diff --git a/src/components/ConsentBanner.js b/src/components/ConsentBanner.js index 6a6ff2ad..0b2f0b75 100644 --- a/src/components/ConsentBanner.js +++ b/src/components/ConsentBanner.js @@ -91,23 +91,23 @@ const ConsentBanner = () => { -
+
-
+
diff --git a/src/components/Layout.js b/src/components/Layout.js index 06badbda..13101421 100644 --- a/src/components/Layout.js +++ b/src/components/Layout.js @@ -150,7 +150,15 @@ const Layout = ({ children }) => { {/* Mobile Navigation Menu */} {isMobileMenuOpen && ( -
+ <> + {/* Overlay */} +
setIsMobileMenuOpen(false)} + /> + + {/* Menu */} +
{
+ )} {/* Main Content */} diff --git a/src/pages/Home.js b/src/pages/Home.js index aa7f47a6..51fa97e3 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -71,7 +71,7 @@ const Home = () => {
{/* Stats */} -
+
{SITE_CONFIG.totalTools} Tools Available diff --git a/src/utils/analytics.js b/src/utils/analytics.js index 38dd6bc9..393f6008 100644 --- a/src/utils/analytics.js +++ b/src/utils/analytics.js @@ -6,11 +6,18 @@ const GA_MEASUREMENT_ID = 'G-S3K5P2PWV6'; // Initialize Google Analytics with Consent Mode v2 export const initGA = () => { - // Only initialize in production and if not already loaded - if (process.env.NODE_ENV !== 'production' || window.gtag) { + // Don't initialize if already loaded + if (window.gtag) { + console.log('🔍 Google Analytics already initialized'); return; } + // Show different behavior in development vs production + const isDevelopment = process.env.NODE_ENV !== 'production'; + if (isDevelopment) { + console.log('🔍 [DEV] Initializing Google Analytics in development mode'); + } + // Initialize gtag function first (required for Consent Mode) window.dataLayer = window.dataLayer || []; function gtag() { @@ -37,19 +44,24 @@ export const initGA = () => { anonymize_ip: true, // Privacy-first approach allow_google_signals: false, // Disable advertising features for privacy allow_ad_personalization_signals: false, // Disable ad personalization + // Development mode settings + debug_mode: isDevelopment, }); // Apply any stored consent preferences applyStoredConsent(); - console.log('🔍 Google Analytics initialized with Consent Mode v2'); + const mode = isDevelopment ? '[DEV]' : '[PROD]'; + console.log(`🔍 ${mode} Google Analytics initialized with Consent Mode v2`); }; }; // Track page views for SPA navigation export const trackPageView = (path, title) => { - if (process.env.NODE_ENV !== 'production' || !window.gtag) { - console.log(`📊 [DEV] Page view: ${path} - ${title}`); + const isDevelopment = process.env.NODE_ENV !== 'production'; + + if (!window.gtag) { + console.log(`📊 [DEV] Page view: ${path} - ${title} (gtag not loaded)`); return; } @@ -58,13 +70,16 @@ export const trackPageView = (path, title) => { page_title: title, }); - console.log(`📊 Page view tracked: ${path}`); + const mode = isDevelopment ? '[DEV]' : '[PROD]'; + console.log(`📊 ${mode} Page view tracked: ${path}`); }; // Track custom events export const trackEvent = (eventName, parameters = {}) => { - if (process.env.NODE_ENV !== 'production' || !window.gtag) { - console.log(`📊 [DEV] Event: ${eventName}`, parameters); + const isDevelopment = process.env.NODE_ENV !== 'production'; + + if (!window.gtag) { + console.log(`📊 [DEV] Event: ${eventName}`, parameters, '(gtag not loaded)'); return; } @@ -74,7 +89,8 @@ export const trackEvent = (eventName, parameters = {}) => { anonymize_ip: true, }); - console.log(`📊 Event tracked: ${eventName}`); + const mode = isDevelopment ? '[DEV]' : '[PROD]'; + console.log(`📊 ${mode} Event tracked: ${eventName}`); }; // Predefined events for common actions diff --git a/src/utils/consentManager.js b/src/utils/consentManager.js index 3e136394..d5a6607c 100644 --- a/src/utils/consentManager.js +++ b/src/utils/consentManager.js @@ -33,16 +33,37 @@ export const isEEAUser = () => { // Initialize Google Consent Mode export const initConsentMode = () => { - if (typeof window === 'undefined' || !window.gtag) return; + if (typeof window === 'undefined') return; + + // Initialize gtag if not already available + if (!window.gtag) { + window.dataLayer = window.dataLayer || []; + function gtag() { + window.dataLayer.push(arguments); + } + window.gtag = gtag; + } - // Set default consent state - window.gtag('consent', 'default', { - ...DEFAULT_CONSENT, - region: isEEAUser() ? ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'IS', 'LI', 'NO'] : ['US'], - wait_for_update: 500 // Wait 500ms for consent update - }); - - console.log('🍪 Consent Mode v2 initialized'); + const isEEA = isEEAUser(); + const mode = process.env.NODE_ENV !== 'production' ? '[DEV]' : '[PROD]'; + + if (isEEA || process.env.NODE_ENV !== 'production') { + // EEA users or development: Start with denied, wait for user consent + window.gtag('consent', 'default', { + ...DEFAULT_CONSENT, + region: isEEA ? ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'IS', 'LI', 'NO'] : ['US'], + wait_for_update: 500 + }); + console.log(`🍪 ${mode} Consent Mode v2 initialized - EEA user, consent required`); + } else { + // Non-EEA users: Automatically grant all consent + window.gtag('consent', 'default', { + ...CONSENT_CONFIGS.ACCEPT_ALL, + region: ['US'], + wait_for_update: 0 // No need to wait + }); + console.log(`🍪 ${mode} Consent Mode v2 initialized - Non-EEA user, auto-granted all consent`); + } }; // Update consent based on user choice @@ -80,8 +101,23 @@ export const getStoredConsent = () => { // Check if consent banner should be shown export const shouldShowConsentBanner = () => { - // Only show for EEA users who haven't consented - return isEEAUser() && !getStoredConsent(); + // In development, always show for testing + if (process.env.NODE_ENV !== 'production') { + return !getStoredConsent(); + } + + // In production, only show for EEA users who haven't consented + if (isEEAUser()) { + return !getStoredConsent(); + } + + // For non-EEA users, automatically grant all consent and never show banner + if (!getStoredConsent()) { + updateConsent(CONSENT_CONFIGS.ACCEPT_ALL); + console.log('🍪 [AUTO] Non-EEA user - automatically granted all consent'); + } + + return false; // Never show banner for non-EEA users }; // Predefined consent configurations