Skip to content

Commit 45fef04

Browse files
updates
1 parent 0e3fabf commit 45fef04

2 files changed

Lines changed: 70 additions & 23 deletions

File tree

EssentialCSharp.Web/Views/Shared/_Layout.cshtml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,11 @@
105105
gtag('js', new Date());
106106
107107
// Configuration will be handled by consent manager
108-
// Only configure if consent is already granted or region doesn't require consent
109-
document.addEventListener('DOMContentLoaded', function() {
110-
// Small delay to ensure consent manager is initialized
111-
setTimeout(function() {
112-
if (window.consentManager &&
113-
(window.consentManager.hasAnalyticsConsent() || !window.consentManager.requiresConsent)) {
114-
gtag('config', 'G-761B4BMK2R');
115-
}
116-
}, 100);
108+
// Listen for consent manager initialization event
109+
document.addEventListener('consentManagerReady', function(event) {
110+
if (event.detail.hasAnalyticsConsent || !event.detail.requiresConsent) {
111+
gtag('config', 'G-761B4BMK2R');
112+
}
117113
});
118114
</script>
119115
<style>

EssentialCSharp.Web/wwwroot/js/consent-manager.js

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
*/
66

77
class ConsentManager {
8-
constructor() {
8+
constructor(options = {}) {
99
this.COOKIE_NAME = 'essential-csharp-consent';
1010
this.COOKIE_DURATION = 365; // days
11+
this.GOOGLE_ANALYTICS_ID = options.googleAnalyticsId || 'G-761B4BMK2R';
1112
this.consentState = {
1213
analytics_storage: 'denied',
1314
ad_storage: 'denied',
@@ -35,6 +36,21 @@ class ConsentManager {
3536
if (this.shouldShowConsentBanner()) {
3637
this.showConsentBanner();
3738
}
39+
40+
// Dispatch initialization event for other scripts to listen to
41+
this.dispatchInitializationEvent();
42+
}
43+
44+
dispatchInitializationEvent() {
45+
// Create and dispatch custom event to signal consent manager is ready
46+
const event = new CustomEvent('consentManagerReady', {
47+
detail: {
48+
hasAnalyticsConsent: this.hasAnalyticsConsent(),
49+
hasAdvertisingConsent: this.hasAdvertisingConsent(),
50+
requiresConsent: this.requiresConsent
51+
}
52+
});
53+
document.dispatchEvent(event);
3854
}
3955

4056
initGoogleConsentMode() {
@@ -54,7 +70,8 @@ class ConsentManager {
5470
return true;
5571
}
5672

57-
// Simple region detection - in production, you might want to use a more reliable service
73+
// Timezone-based region detection for GDPR compliance
74+
// Users can change timezones, but this provides reasonable detection for most cases
5875
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
5976

6077
// EEA countries, UK, and Switzerland timezones
@@ -90,7 +107,23 @@ class ConsentManager {
90107
if (saved) {
91108
try {
92109
const preferences = JSON.parse(saved);
93-
this.consentState = { ...this.consentState, ...preferences };
110+
111+
// Validate and only apply known consent properties for security
112+
const validConsentKeys = [
113+
'analytics_storage', 'ad_storage', 'ad_user_data',
114+
'ad_personalization', 'functionality_storage',
115+
'security_storage', 'personalization_storage'
116+
];
117+
118+
const validatedPreferences = {};
119+
validConsentKeys.forEach(key => {
120+
if (preferences.hasOwnProperty(key) &&
121+
(preferences[key] === 'granted' || preferences[key] === 'denied')) {
122+
validatedPreferences[key] = preferences[key];
123+
}
124+
});
125+
126+
this.consentState = { ...this.consentState, ...validatedPreferences };
94127
this.updateConsentMode();
95128
} catch (e) {
96129
console.warn('Failed to parse consent preferences', e);
@@ -261,20 +294,30 @@ class ConsentManager {
261294

262295
updateConsentMode() {
263296
if (window.gtag) {
264-
gtag('consent', 'update', this.consentState);
265-
266-
// Configure Google Analytics if analytics consent is granted
267-
if (this.consentState.analytics_storage === 'granted') {
268-
gtag('config', 'G-761B4BMK2R');
297+
try {
298+
gtag('consent', 'update', this.consentState);
299+
300+
// Configure Google Analytics if analytics consent is granted
301+
if (this.consentState.analytics_storage === 'granted') {
302+
gtag('config', 'G-761B4BMK2R');
303+
}
304+
} catch (error) {
305+
console.warn('Failed to update Google Consent Mode:', error);
269306
}
270307
}
271308
}
272309

273310
updateClarityConsent() {
274-
// Send consent signal to Microsoft Clarity
311+
// Send consent signal to Microsoft Clarity using Consent API v2
275312
if (window.clarity) {
276-
const analyticsConsent = this.consentState.analytics_storage === 'granted';
277-
clarity('consent', analyticsConsent);
313+
try {
314+
clarity('consentv2', {
315+
ad_Storage: this.consentState.ad_storage,
316+
analytics_Storage: this.consentState.analytics_storage
317+
});
318+
} catch (error) {
319+
console.warn('Failed to update Clarity consent:', error);
320+
}
278321
}
279322
}
280323

@@ -435,11 +478,15 @@ class ConsentManager {
435478
this.rejectAllConsent();
436479
// Also clear any existing tracking cookies
437480
this.clearTrackingCookies();
481+
// Erase Clarity cookies according to documentation
482+
if (window.clarity) {
483+
clarity('consent', false);
484+
}
438485
}
439486

440487
clearTrackingCookies() {
441-
// Clear common tracking cookies
442-
const trackingCookies = ['_ga', '_gid', '_gat', '_clck', '_clsk'];
488+
// Clear common tracking cookies (Google Analytics and Microsoft Clarity)
489+
const trackingCookies = ['_ga', '_gid', '_gat', '_clck', '_clsk', 'CLID', 'ANONCHK', 'MR', 'MUID', 'SM'];
443490
trackingCookies.forEach(cookieName => {
444491
document.cookie = `${cookieName}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
445492
});
@@ -448,7 +495,11 @@ class ConsentManager {
448495

449496
// Initialize consent manager when DOM is ready
450497
document.addEventListener('DOMContentLoaded', function() {
451-
window.consentManager = new ConsentManager();
498+
// Check for configuration from script tag data attributes
499+
const configScript = document.querySelector('script[data-consent-config]');
500+
const config = configScript ? JSON.parse(configScript.dataset.consentConfig) : {};
501+
502+
window.consentManager = new ConsentManager(config);
452503
});
453504

454505
// Global function for opening consent preferences

0 commit comments

Comments
 (0)