552 lines
18 KiB
HTML
552 lines
18 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>🍪 Privacy-First Demo | GDPR Compliant Tracking</title>
|
||
|
|
<style>
|
||
|
|
* {
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
|
||
|
|
body {
|
||
|
|
margin: 0;
|
||
|
|
padding: 0;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
|
|
min-height: 100vh;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
min-height: 100vh;
|
||
|
|
text-align: center;
|
||
|
|
padding: 2rem;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero::before {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
right: 0;
|
||
|
|
bottom: 0;
|
||
|
|
background: rgba(255, 255, 255, 0.95);
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero-content {
|
||
|
|
position: relative;
|
||
|
|
z-index: 1;
|
||
|
|
max-width: 800px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero h1 {
|
||
|
|
font-size: 3.5rem;
|
||
|
|
font-weight: 700;
|
||
|
|
margin: 0 0 1rem 0;
|
||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero .subtitle {
|
||
|
|
font-size: 1.4rem;
|
||
|
|
color: #666;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
font-weight: 300;
|
||
|
|
}
|
||
|
|
|
||
|
|
.privacy-badge {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
background: #e8f5e8;
|
||
|
|
color: #2e7d2e;
|
||
|
|
padding: 8px 16px;
|
||
|
|
border-radius: 20px;
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 600;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
box-shadow: 0 2px 8px rgba(46, 125, 46, 0.1);
|
||
|
|
}
|
||
|
|
|
||
|
|
.demo-info {
|
||
|
|
background: white;
|
||
|
|
padding: 2rem;
|
||
|
|
border-radius: 16px;
|
||
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||
|
|
margin-top: 2rem;
|
||
|
|
text-align: left;
|
||
|
|
}
|
||
|
|
|
||
|
|
.demo-info h2 {
|
||
|
|
color: #333;
|
||
|
|
margin-top: 0;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-list {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
|
|
gap: 1rem;
|
||
|
|
margin: 1.5rem 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 12px;
|
||
|
|
padding: 1rem;
|
||
|
|
background: #f8f9fa;
|
||
|
|
border-radius: 8px;
|
||
|
|
border-left: 4px solid #667eea;
|
||
|
|
}
|
||
|
|
|
||
|
|
.feature-icon {
|
||
|
|
font-size: 1.5rem;
|
||
|
|
min-width: 24px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-status {
|
||
|
|
position: fixed;
|
||
|
|
top: 20px;
|
||
|
|
left: 20px;
|
||
|
|
background: rgba(255, 255, 255, 0.9);
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
padding: 12px 20px;
|
||
|
|
border-radius: 25px;
|
||
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||
|
|
z-index: 999;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-dot {
|
||
|
|
width: 8px;
|
||
|
|
height: 8px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: #4caf50;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-dot.minimal {
|
||
|
|
background: #ff9800;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 768px) {
|
||
|
|
.hero h1 {
|
||
|
|
font-size: 2.5rem;
|
||
|
|
}
|
||
|
|
.hero .subtitle {
|
||
|
|
font-size: 1.2rem;
|
||
|
|
}
|
||
|
|
.demo-info {
|
||
|
|
padding: 1.5rem;
|
||
|
|
}
|
||
|
|
.tracking-status {
|
||
|
|
position: static;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
.tracking-consent-container {
|
||
|
|
position: fixed;
|
||
|
|
bottom: 20px;
|
||
|
|
right: 20px;
|
||
|
|
z-index: 1000;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-consent-btn {
|
||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
|
|
color: white;
|
||
|
|
border: none;
|
||
|
|
padding: 12px 24px;
|
||
|
|
border-radius: 25px;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 600;
|
||
|
|
cursor: pointer;
|
||
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-consent-btn:hover {
|
||
|
|
transform: translateY(-2px);
|
||
|
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-consent-btn:active {
|
||
|
|
transform: translateY(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-consent-btn.enabled {
|
||
|
|
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-consent-btn.enabled::after {
|
||
|
|
content: "✓";
|
||
|
|
margin-left: 4px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tracking-icon {
|
||
|
|
font-size: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-modal {
|
||
|
|
display: none;
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
background: rgba(0, 0, 0, 0.5);
|
||
|
|
z-index: 1001;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-modal-content {
|
||
|
|
background: white;
|
||
|
|
padding: 30px;
|
||
|
|
border-radius: 12px;
|
||
|
|
max-width: 500px;
|
||
|
|
margin: 20px;
|
||
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-modal h3 {
|
||
|
|
margin: 0 0 16px 0;
|
||
|
|
color: #333;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-modal p {
|
||
|
|
margin: 0 0 20px 0;
|
||
|
|
color: #666;
|
||
|
|
line-height: 1.5;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-modal-buttons {
|
||
|
|
display: flex;
|
||
|
|
gap: 12px;
|
||
|
|
justify-content: flex-end;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-btn {
|
||
|
|
padding: 10px 20px;
|
||
|
|
border: none;
|
||
|
|
border-radius: 6px;
|
||
|
|
font-weight: 600;
|
||
|
|
cursor: pointer;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-btn.primary {
|
||
|
|
background: #667eea;
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-btn.secondary {
|
||
|
|
background: #f5f5f5;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.consent-btn:hover {
|
||
|
|
opacity: 0.9;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="tracking-status" id="trackingStatus">
|
||
|
|
<div class="status-dot minimal" id="statusDot"></div>
|
||
|
|
<span id="statusText">Privacy Mode: Minimal Tracking</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="hero">
|
||
|
|
<div class="hero-content">
|
||
|
|
<div class="privacy-badge">
|
||
|
|
🔒 <span>GDPR Compliant by Default</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<h1>Privacy-First Demo</h1>
|
||
|
|
<p class="subtitle">
|
||
|
|
Experience truly optional tracking. Your privacy is protected by default,<br>
|
||
|
|
with enhanced features available only when <em>you</em> choose to enable them.
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<div class="demo-info">
|
||
|
|
<h2>🎯 How It Works</h2>
|
||
|
|
<p>This demo shows how modern websites can respect your privacy while still providing great experiences:</p>
|
||
|
|
|
||
|
|
<div class="feature-list">
|
||
|
|
<div class="feature">
|
||
|
|
<span class="feature-icon">🔒</span>
|
||
|
|
<div>
|
||
|
|
<strong>Default: Privacy Protected</strong><br>
|
||
|
|
<small>Only essential cookies, anonymized analytics</small>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="feature">
|
||
|
|
<span class="feature-icon">📊</span>
|
||
|
|
<div>
|
||
|
|
<strong>Optional: Enhanced Tracking</strong><br>
|
||
|
|
<small>Detailed analytics, personalization when you opt-in</small>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="feature">
|
||
|
|
<span class="feature-icon">🎚️</span>
|
||
|
|
<div>
|
||
|
|
<strong>Full Control</strong><br>
|
||
|
|
<small>Toggle anytime with the button below</small>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="feature">
|
||
|
|
<span class="feature-icon">🍪</span>
|
||
|
|
<div>
|
||
|
|
<strong>Smart Cookie Management</strong><br>
|
||
|
|
<small>Automatic cleanup when disabled</small>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<p><strong>Try it out!</strong> Click the colorful button in the bottom-right corner to see the consent flow in action. 👇</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="tracking-consent-container">
|
||
|
|
<button id="trackingConsentBtn" class="tracking-consent-btn">
|
||
|
|
<span class="tracking-icon">📊</span>
|
||
|
|
<span id="btnText">Plz trac me!</span>
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="consentModal" class="consent-modal">
|
||
|
|
<div class="consent-modal-content">
|
||
|
|
<h3>Optional Enhanced Tracking</h3>
|
||
|
|
<p>
|
||
|
|
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.
|
||
|
|
</p>
|
||
|
|
<p>
|
||
|
|
<strong>What we'll track:</strong><br>
|
||
|
|
• Detailed page interactions<br>
|
||
|
|
• User preferences for personalization<br>
|
||
|
|
• Marketing campaign effectiveness<br>
|
||
|
|
• Enhanced usage analytics
|
||
|
|
</p>
|
||
|
|
<p>You can change your mind anytime by clicking the tracking button again.</p>
|
||
|
|
<div class="consent-modal-buttons">
|
||
|
|
<button class="consent-btn secondary" onclick="closeConsentModal()">No, thanks</button>
|
||
|
|
<button class="consent-btn primary" onclick="enableTracking()">Yes, track me!</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
class GDPRTrackingConsent {
|
||
|
|
constructor() {
|
||
|
|
this.storageKey = 'gdpr-tracking-consent';
|
||
|
|
this.isTrackingEnabled = this.getConsentStatus();
|
||
|
|
this.init();
|
||
|
|
}
|
||
|
|
|
||
|
|
init() {
|
||
|
|
this.updateButtonState();
|
||
|
|
this.setupEventListeners();
|
||
|
|
|
||
|
|
if (this.isTrackingEnabled) {
|
||
|
|
this.enableEnhancedTracking();
|
||
|
|
} else {
|
||
|
|
this.enableMinimalTracking();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
setupEventListeners() {
|
||
|
|
const btn = document.getElementById('trackingConsentBtn');
|
||
|
|
btn.addEventListener('click', () => {
|
||
|
|
if (this.isTrackingEnabled) {
|
||
|
|
this.showDisableConfirm();
|
||
|
|
} else {
|
||
|
|
this.showConsentModal();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const modal = document.getElementById('consentModal');
|
||
|
|
modal.addEventListener('click', (e) => {
|
||
|
|
if (e.target === modal) {
|
||
|
|
this.closeConsentModal();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
getConsentStatus() {
|
||
|
|
const stored = localStorage.getItem(this.storageKey);
|
||
|
|
return stored === 'true';
|
||
|
|
}
|
||
|
|
|
||
|
|
setConsentStatus(status) {
|
||
|
|
localStorage.setItem(this.storageKey, status.toString());
|
||
|
|
this.isTrackingEnabled = status;
|
||
|
|
}
|
||
|
|
|
||
|
|
updateButtonState() {
|
||
|
|
const btn = document.getElementById('trackingConsentBtn');
|
||
|
|
const btnText = document.getElementById('btnText');
|
||
|
|
const statusText = document.getElementById('statusText');
|
||
|
|
const statusDot = document.getElementById('statusDot');
|
||
|
|
|
||
|
|
if (this.isTrackingEnabled) {
|
||
|
|
btn.classList.add('enabled');
|
||
|
|
btnText.textContent = 'Tracking ON';
|
||
|
|
statusText.textContent = 'Privacy Mode: Enhanced Tracking';
|
||
|
|
statusDot.className = 'status-dot';
|
||
|
|
} else {
|
||
|
|
btn.classList.remove('enabled');
|
||
|
|
btnText.textContent = 'Plz trac me!';
|
||
|
|
statusText.textContent = 'Privacy Mode: Minimal Tracking';
|
||
|
|
statusDot.className = 'status-dot minimal';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
showConsentModal() {
|
||
|
|
document.getElementById('consentModal').style.display = 'flex';
|
||
|
|
}
|
||
|
|
|
||
|
|
closeConsentModal() {
|
||
|
|
document.getElementById('consentModal').style.display = 'none';
|
||
|
|
}
|
||
|
|
|
||
|
|
showDisableConfirm() {
|
||
|
|
if (confirm('Disable enhanced tracking? We\'ll switch back to minimal analytics only.')) {
|
||
|
|
this.disableTracking();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
enableTracking() {
|
||
|
|
this.setConsentStatus(true);
|
||
|
|
this.updateButtonState();
|
||
|
|
this.closeConsentModal();
|
||
|
|
this.enableEnhancedTracking();
|
||
|
|
|
||
|
|
this.showNotification('Enhanced tracking enabled! Thanks for helping us improve.');
|
||
|
|
}
|
||
|
|
|
||
|
|
disableTracking() {
|
||
|
|
this.setConsentStatus(false);
|
||
|
|
this.updateButtonState();
|
||
|
|
this.enableMinimalTracking();
|
||
|
|
|
||
|
|
this.showNotification('Switched to minimal tracking. Your privacy is protected.');
|
||
|
|
}
|
||
|
|
|
||
|
|
enableMinimalTracking() {
|
||
|
|
console.log('🔒 GDPR Mode: Minimal tracking enabled');
|
||
|
|
|
||
|
|
if (typeof gtag !== 'undefined') {
|
||
|
|
gtag('consent', 'update', {
|
||
|
|
'analytics_storage': 'denied',
|
||
|
|
'ad_storage': 'denied',
|
||
|
|
'personalization_storage': 'denied',
|
||
|
|
'functionality_storage': 'granted'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
this.cleanupEnhancedCookies();
|
||
|
|
this.fireCustomEvent('trackingModeChanged', { mode: 'minimal' });
|
||
|
|
}
|
||
|
|
|
||
|
|
enableEnhancedTracking() {
|
||
|
|
console.log('📊 Enhanced tracking enabled');
|
||
|
|
|
||
|
|
if (typeof gtag !== 'undefined') {
|
||
|
|
gtag('consent', 'update', {
|
||
|
|
'analytics_storage': 'granted',
|
||
|
|
'ad_storage': 'granted',
|
||
|
|
'personalization_storage': 'granted',
|
||
|
|
'functionality_storage': 'granted'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
this.initEnhancedAnalytics();
|
||
|
|
this.fireCustomEvent('trackingModeChanged', { mode: 'enhanced' });
|
||
|
|
}
|
||
|
|
|
||
|
|
initEnhancedAnalytics() {
|
||
|
|
if (typeof gtag !== 'undefined') {
|
||
|
|
gtag('event', 'enhanced_tracking_enabled', {
|
||
|
|
'event_category': 'privacy',
|
||
|
|
'event_label': 'user_opted_in'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
cleanupEnhancedCookies() {
|
||
|
|
const cookiesToRemove = ['_ga', '_gid', '_gat', '_fbp', '_fbc'];
|
||
|
|
cookiesToRemove.forEach(cookie => {
|
||
|
|
document.cookie = `${cookie}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
||
|
|
document.cookie = `${cookie}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${window.location.hostname}`;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
fireCustomEvent(eventName, data) {
|
||
|
|
const event = new CustomEvent(eventName, { detail: data });
|
||
|
|
document.dispatchEvent(event);
|
||
|
|
}
|
||
|
|
|
||
|
|
showNotification(message) {
|
||
|
|
const notification = document.createElement('div');
|
||
|
|
notification.style.cssText = `
|
||
|
|
position: fixed;
|
||
|
|
top: 20px;
|
||
|
|
right: 20px;
|
||
|
|
background: #4caf50;
|
||
|
|
color: white;
|
||
|
|
padding: 12px 20px;
|
||
|
|
border-radius: 6px;
|
||
|
|
z-index: 1002;
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
||
|
|
`;
|
||
|
|
notification.textContent = message;
|
||
|
|
document.body.appendChild(notification);
|
||
|
|
|
||
|
|
setTimeout(() => {
|
||
|
|
notification.remove();
|
||
|
|
}, 3000);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function closeConsentModal() {
|
||
|
|
window.trackingConsent.closeConsentModal();
|
||
|
|
}
|
||
|
|
|
||
|
|
function enableTracking() {
|
||
|
|
window.trackingConsent.enableTracking();
|
||
|
|
}
|
||
|
|
|
||
|
|
document.addEventListener('DOMContentLoaded', () => {
|
||
|
|
window.trackingConsent = new GDPRTrackingConsent();
|
||
|
|
});
|
||
|
|
|
||
|
|
document.addEventListener('trackingModeChanged', (e) => {
|
||
|
|
console.log('Tracking mode changed to:', e.detail.mode);
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|