Try it out! Click the colorful button in the bottom-right corner to see the consent flow in action. π
+
+
+ π
+ 73% of our users choose privacy mode
+ Join thousands who enjoy a tracking-free experience!
+
+
+
π‘ Want to use this in your project?
@@ -391,6 +594,35 @@
+
+
+
+ π How Simple Is GDPR Compliance?
+
+
+ This entire consent system is just ~100 lines of JavaScript!
+
+
+// Complete GDPR compliance in 3 simple steps:
+
+1. Default to minimal tracking
+ if (!hasConsent()) {
+ disableTracking();
+ }
+
+2. Ask for consent (optional)
+ showConsentModal();
+
+3. Respect the choice
+ if (userSaidYes) {
+ enableTracking();
+ }
+
+// That's it! π
+
+ Key insight: Privacy-first doesn't mean complex. It means defaulting to the right thing.
+
+
@@ -402,25 +634,65 @@
+
+
+
+
πͺ Cookie Details
+
+
+
+
+
+
+
+
+
-
Optional Enhanced Tracking
-
- We respect your privacy! By default, we only use essential cookies and basic analytics.
- If you'd like to help us improve our service with enhanced tracking (detailed analytics,
- personalization, marketing cookies), you can opt in below.
+
Your Privacy, Your Choice! π‘οΈ
+
+ β¨ Everything works perfectly without tracking! β¨
-
- What we'll track:
- β’ Detailed page interactions
- β’ User preferences for personalization
- β’ Marketing campaign effectiveness
- β’ Enhanced usage analytics
+
+
+
+
π‘οΈ Keep Privacy Mode (Recommended)
+
+
β Full site functionality
+
β Lightning fast
+
β No cookies following you
+
β Zero personal data collected
+
β No retargeting ads
+
+
+ π Privacy Champion
+
+
+
+
π Enable Tracking
+
+
β Helps us improve
+
β Adds 5+ cookies
+
β Shares data with Google
+
β Enables remarketing
+
β Slower page loads
+
+
+
+
+
+ You can change your mind anytime. Join the 73% who choose privacy!
-
You can change your mind anytime by clicking the tracking button again.
-
-
-
+
+
+
+
@@ -464,7 +736,16 @@
modalYes: 'Yes, track me!',
notificationEnabled: 'Enhanced tracking enabled! Thanks for helping us improve.',
notificationDisabled: 'Switched to minimal tracking. Your privacy is protected.',
- confirmDisable: 'Disable enhanced tracking? We will switch back to minimal analytics only.'
+ confirmDisable: 'Disable enhanced tracking? We will switch back to minimal analytics only.',
+ privacyChosen: 'π Excellent choice! Your privacy is protected and everything works perfectly!',
+ privacyScore100: 'Privacy Score: 100%',
+ privacyScore0: 'Privacy Score: 0%',
+ cookiesEssential: 'cookies (essential only)',
+ cookiesTracking: 'cookies (with tracking)',
+ achievementPrivacyChampion: 'π Achievement Unlocked: Privacy Champion!',
+ achievementDataMinimalist: 'π Achievement: Data Minimalist!',
+ privacyModeActive: 'π‘οΈ Privacy Mode Active - You\'re Protected!',
+ trackingModeActive: 'π Tracking Active - Thank You for Helping!'
},
no: {
title: 'πͺ Personvern-fΓΈrst demo | GDPR-kompatibel sporing',
@@ -502,7 +783,16 @@
modalYes: 'Ja, spor meg!',
notificationEnabled: 'Utvidet sporing aktivert! Takk for at du hjelper oss forbedre.',
notificationDisabled: 'Byttet til minimal sporing. Ditt personvern er beskyttet.',
- confirmDisable: 'Deaktiver utvidet sporing? Vi bytter tilbake til kun minimal analyse.'
+ confirmDisable: 'Deaktiver utvidet sporing? Vi bytter tilbake til kun minimal analyse.',
+ privacyChosen: 'π Utmerket valg! Ditt personvern er beskyttet og alt fungerer perfekt!',
+ privacyScore100: 'Personvernscore: 100%',
+ privacyScore0: 'Personvernscore: 0%',
+ cookiesEssential: 'cookies (kun essensielle)',
+ cookiesTracking: 'cookies (med sporing)',
+ achievementPrivacyChampion: 'π Prestasjon lΓ₯st opp: Personvernmester!',
+ achievementDataMinimalist: 'π Prestasjon: Dataminimalist!',
+ privacyModeActive: 'π‘οΈ Personvernmodus aktiv - Du er beskyttet!',
+ trackingModeActive: 'π Sporing aktiv - Takk for hjelpen!'
}
};
@@ -587,19 +877,28 @@
class GDPRTrackingConsent {
constructor() {
this.storageKey = 'gdpr-tracking-consent';
+ this.achievementsKey = 'gdpr-achievements';
+ this.statsKey = 'gdpr-stats';
this.isTrackingEnabled = this.getConsentStatus();
+ this.achievements = this.loadAchievements();
this.init();
}
init() {
this.updateButtonState();
this.setupEventListeners();
+ this.updateCookieCounter();
+ this.updatePrivacyScore();
if (this.isTrackingEnabled) {
this.enableEnhancedTracking();
} else {
this.enableMinimalTracking();
+ this.checkPrivacyAchievements();
}
+
+ // Update cookie counter every 2 seconds
+ setInterval(() => this.updateCookieCounter(), 2000);
}
setupEventListeners() {
@@ -639,15 +938,19 @@
if (this.isTrackingEnabled) {
btn.classList.add('enabled');
- btnText.textContent = t.buttonTextOn;
- statusText.textContent = t.statusEnhanced;
+ btnText.textContent = t.buttonTextOn || 'Tracking ON';
+ statusText.textContent = t.trackingModeActive || 'π Tracking Active - Thank You for Helping!';
statusDot.className = 'status-dot';
} else {
btn.classList.remove('enabled');
- btnText.textContent = t.buttonText;
- statusText.textContent = t.statusMinimal;
+ btnText.textContent = t.buttonText || 'Plz trac me!';
+ statusText.textContent = t.privacyModeActive || 'π‘οΈ Privacy Mode Active - You\'re Protected!';
statusDot.className = 'status-dot minimal';
}
+
+ // Update other UI elements
+ this.updateCookieCounter();
+ this.updatePrivacyScore();
}
showConsentModal() {
@@ -736,13 +1039,13 @@
document.dispatchEvent(event);
}
- showNotification(message) {
+ showNotification(message, isSuccess = true) {
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
- background: #4caf50;
+ background: ${isSuccess ? '#4caf50' : '#667eea'};
color: white;
padding: 12px 20px;
border-radius: 6px;
@@ -757,6 +1060,109 @@
notification.remove();
}, 3000);
}
+
+ updateCookieCounter() {
+ const cookieCount = document.cookie.split(';').filter(c => c.trim()).length || 0;
+ const cookieText = document.getElementById('cookieText');
+ const cookieIcon = document.getElementById('cookieIcon');
+ const t = translations[currentLang];
+
+ if (cookieText) {
+ if (this.isTrackingEnabled) {
+ cookieText.textContent = `${cookieCount} ${t.cookiesTracking || 'cookies (with tracking)'}`;
+ cookieIcon.textContent = 'π';
+ } else {
+ cookieText.textContent = `${cookieCount} ${t.cookiesEssential || 'cookies (essential only)'}`;
+ cookieIcon.textContent = 'π‘οΈ';
+ }
+ }
+ }
+
+ updatePrivacyScore() {
+ const scoreText = document.getElementById('scoreText');
+ const privacyScore = document.getElementById('privacyScore');
+ const t = translations[currentLang];
+
+ if (scoreText && privacyScore) {
+ if (this.isTrackingEnabled) {
+ scoreText.textContent = t.privacyScore0 || 'Privacy Score: 0%';
+ privacyScore.style.background = 'linear-gradient(135deg, #ff6b6b, #ff8787)';
+ } else {
+ scoreText.textContent = t.privacyScore100 || 'Privacy Score: 100%';
+ privacyScore.style.background = 'linear-gradient(135deg, #4caf50, #45a049)';
+ }
+ }
+ }
+
+ loadAchievements() {
+ const stored = localStorage.getItem(this.achievementsKey);
+ return stored ? JSON.parse(stored) : {};
+ }
+
+ saveAchievements() {
+ localStorage.setItem(this.achievementsKey, JSON.stringify(this.achievements));
+ }
+
+ unlockAchievement(achievementId, message) {
+ if (!this.achievements[achievementId]) {
+ this.achievements[achievementId] = {
+ unlockedAt: new Date().toISOString(),
+ message: message
+ };
+ this.saveAchievements();
+ this.showAchievement(message);
+ }
+ }
+
+ showAchievement(message) {
+ const achievement = document.createElement('div');
+ achievement.className = 'achievement-toast';
+ achievement.innerHTML = `
+ π
+ ${message}
+ `;
+ document.body.appendChild(achievement);
+
+ setTimeout(() => {
+ achievement.style.animation = 'slideInRight 0.5s ease-out reverse';
+ setTimeout(() => achievement.remove(), 500);
+ }, 4000);
+ }
+
+ checkPrivacyAchievements() {
+ const t = translations[currentLang];
+
+ // Check for Privacy Champion achievement
+ if (!this.isTrackingEnabled) {
+ setTimeout(() => {
+ this.unlockAchievement(
+ 'privacy_champion',
+ t.achievementPrivacyChampion || 'π Achievement Unlocked: Privacy Champion!'
+ );
+ }, 1000);
+ }
+
+ // Check for Data Minimalist achievement (if never enabled tracking)
+ const hasEverEnabledTracking = localStorage.getItem('has-enabled-tracking');
+ if (!hasEverEnabledTracking && !this.isTrackingEnabled) {
+ setTimeout(() => {
+ this.unlockAchievement(
+ 'data_minimalist',
+ t.achievementDataMinimalist || 'π Achievement: Data Minimalist!'
+ );
+ }, 3000);
+ }
+ }
+
+ updatePrivacyStats() {
+ // Simulate privacy stats (in real app, this would come from server)
+ const stats = {
+ privacyUsers: 73,
+ totalUsers: 100
+ };
+ localStorage.setItem(this.statsKey, JSON.stringify(stats));
+ return stats;
+ }
}
function closeConsentModal() {
@@ -764,9 +1170,120 @@
}
function enableTracking() {
+ // Mark that user has enabled tracking at least once
+ localStorage.setItem('has-enabled-tracking', 'true');
window.trackingConsent.enableTracking();
}
+ function choosePrivacy() {
+ const t = translations[currentLang];
+ window.trackingConsent.closeConsentModal();
+ window.trackingConsent.showNotification(
+ t.privacyChosen || 'π Excellent choice! Your privacy is protected and everything works perfectly!',
+ true
+ );
+ window.trackingConsent.checkPrivacyAchievements();
+ }
+
+ function showCookieDetails() {
+ const modal = document.getElementById('cookieDetailsModal');
+ const detailsList = document.getElementById('cookieDetailsList');
+
+ const cookieExplanations = {
+ 'gdpr-tracking-consent': {
+ name: 'GDPR Tracking Consent',
+ type: 'β Essential',
+ purpose: 'Remembers your privacy choice',
+ duration: 'Permanent',
+ details: 'This cookie stores whether you\'ve chosen to enable or disable tracking. It\'s essential for the site to respect your privacy preferences.'
+ },
+ 'gdpr-language': {
+ name: 'Language Preference',
+ type: 'β Essential',
+ purpose: 'Remembers your language choice',
+ duration: 'Permanent',
+ details: 'Stores your preferred language (English or Norwegian) so the site displays in your chosen language.'
+ },
+ '_ga': {
+ name: 'Google Analytics',
+ type: 'π Tracking',
+ purpose: 'User identification',
+ duration: '2 years',
+ details: 'Used by Google Analytics to distinguish unique users. Only set when tracking is enabled.'
+ },
+ '_gid': {
+ name: 'Google Analytics ID',
+ type: 'π Tracking',
+ purpose: 'Session tracking',
+ duration: '24 hours',
+ details: 'Used by Google Analytics to distinguish users and sessions. Only set when tracking is enabled.'
+ },
+ '_gat': {
+ name: 'Google Analytics Throttle',
+ type: 'π Tracking',
+ purpose: 'Request rate limiting',
+ duration: '1 minute',
+ details: 'Used to throttle request rate to Google Analytics. Only set when tracking is enabled.'
+ }
+ };
+
+ // Get current cookies
+ const cookies = document.cookie.split(';').filter(c => c.trim());
+
+ let html = '
';
+
+ if (cookies.length === 0) {
+ html += '
π No cookies found! Your browser is completely cookie-free on this site.
+ π‘ Did you know?
+ Essential cookies are necessary for basic site functions like remembering your preferences.
+ They don't track you or collect personal data. Tracking cookies are only set if you explicitly enable them!
+
Opt-in by default: No tracking until user consents
+
Clear choice: User understands what they're agreeing to
+
Easy withdrawal: User can revoke consent anytime
+
Functional without tracking: Site works regardless of choice
+
+
+
+ That's it! This simple implementation covers all the basics.
+ The fancy version in index.html just adds nice UI and features,
+ but the core principle remains this simple.
+
+
+
+
+ π Privacy-first is easy!
+ Copy this code and make the web more privacy-friendly.
+