Skip to content

Commit f722f2f

Browse files
committed
adding consent mgmt
1 parent b32fdf4 commit f722f2f

5 files changed

Lines changed: 516 additions & 19 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
node_modules/
66

77
.git/
8-
notes/
8+
notes/
9+
data/

index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,24 @@
77
<title>Java 30Y #CelebrationWeek</title>
88
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
99

10+
<!-- Cookie Consent - Must load before analytics -->
11+
<script src="js/cookie-consent.js"></script>
12+
1013
<!-- Google tag (gtag.js) -->
1114
<script async src="https://www.googletagmanager.com/gtag/js?id=G-K4QDNZB9C7"></script>
1215
<script>
1316
window.dataLayer = window.dataLayer || [];
1417
function gtag(){dataLayer.push(arguments);}
18+
19+
// Configure consent mode before GA4 initialization
20+
gtag('consent', 'default', {
21+
'analytics_storage': 'denied',
22+
'functionality_storage': 'granted',
23+
'personalization_storage': 'granted',
24+
'security_storage': 'granted',
25+
'wait_for_update': 500
26+
});
27+
1528
gtag('js', new Date());
1629
gtag('config', 'G-K4QDNZB9C7');
1730
</script>
@@ -273,5 +286,6 @@ <h3 class="speaker-profile-name" id="modalSpeakerName"></h3>
273286
</div>
274287

275288
<script src="main.js"></script>
289+
<script src="js/event-analytics.js"></script>
276290
</body>
277291
</html>

js/cookie-consent.js

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
/**
2+
* Simple Cookie Consent for Java 30Y Event
3+
* GDPR/LGPD Compliant
4+
*/
5+
6+
const CookieConsent = {
7+
hasConsent: false,
8+
consentKey: 'java30y_analytics_consent',
9+
10+
init() {
11+
// Check if user already gave consent
12+
const savedConsent = localStorage.getItem(this.consentKey);
13+
14+
if (savedConsent === 'accepted') {
15+
this.hasConsent = true;
16+
this.enableAnalytics();
17+
} else if (savedConsent === null) {
18+
// First visit - show banner
19+
this.showBanner();
20+
}
21+
// If rejected, do nothing (analytics stays disabled)
22+
},
23+
24+
showBanner() {
25+
const banner = document.createElement('div');
26+
banner.id = 'cookie-consent-banner';
27+
banner.innerHTML = `
28+
<div class="consent-content">
29+
<div class="consent-text">
30+
<p><strong>We use cookies to improve your experience</strong></p>
31+
<p>We use analytics cookies to understand how you use our site.
32+
<a href="https://policies.google.com/technologies/cookies" target="_blank" rel="noopener">Learn more</a></p>
33+
<p class="consent-legal">By clicking "Accept", you consent to our use of analytics cookies.</p>
34+
</div>
35+
<div class="consent-buttons">
36+
<button class="consent-button consent-reject" onclick="CookieConsent.reject()">Reject</button>
37+
<button class="consent-button consent-accept" onclick="CookieConsent.accept()">Accept</button>
38+
</div>
39+
</div>
40+
`;
41+
42+
// Add styles
43+
const style = document.createElement('style');
44+
style.textContent = `
45+
#cookie-consent-banner {
46+
position: fixed;
47+
bottom: 20px;
48+
right: 20px;
49+
background: rgba(43, 76, 111, 0.95);
50+
color: white;
51+
padding: 1rem 1.5rem;
52+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
53+
z-index: 10000;
54+
border-radius: 0.75rem;
55+
max-width: 400px;
56+
animation: slideUp 0.3s ease-out;
57+
}
58+
59+
@keyframes slideUp {
60+
from { transform: translateY(100%); }
61+
to { transform: translateY(0); }
62+
}
63+
64+
.consent-content {
65+
display: flex;
66+
flex-direction: column;
67+
gap: 1rem;
68+
}
69+
70+
.consent-text {
71+
font-size: 0.875rem;
72+
line-height: 1.4;
73+
}
74+
75+
.consent-text p {
76+
margin: 0 0 0.5rem 0;
77+
font-size: 0.875rem;
78+
line-height: 1.4;
79+
}
80+
81+
.consent-text p:first-child {
82+
display: none;
83+
}
84+
85+
.consent-text a {
86+
color: #5cb6fa;
87+
text-decoration: underline;
88+
font-size: 0.75rem;
89+
}
90+
91+
.consent-legal {
92+
font-size: 0.75rem;
93+
opacity: 0.8;
94+
display: none;
95+
}
96+
97+
.consent-buttons {
98+
display: flex;
99+
gap: 0.75rem;
100+
justify-content: flex-end;
101+
}
102+
103+
.consent-button {
104+
padding: 0.5rem 1.25rem;
105+
border: none;
106+
border-radius: 0.375rem;
107+
font-weight: 500;
108+
cursor: pointer;
109+
transition: all 0.2s ease;
110+
font-size: 0.875rem;
111+
min-width: 70px;
112+
}
113+
114+
.consent-accept {
115+
background: #F77347;
116+
color: white;
117+
}
118+
119+
.consent-accept:hover {
120+
background: #f78128;
121+
transform: translateY(-1px);
122+
}
123+
124+
.consent-reject {
125+
background: transparent;
126+
color: rgba(255, 255, 255, 0.8);
127+
padding: 0.5rem 0.75rem;
128+
min-width: auto;
129+
}
130+
131+
.consent-reject:hover {
132+
color: white;
133+
text-decoration: underline;
134+
}
135+
136+
@media (max-width: 768px) {
137+
#cookie-consent-banner {
138+
bottom: 10px;
139+
right: 10px;
140+
left: 10px;
141+
max-width: none;
142+
}
143+
}
144+
`;
145+
146+
document.head.appendChild(style);
147+
document.body.appendChild(banner);
148+
},
149+
150+
accept() {
151+
this.hasConsent = true;
152+
localStorage.setItem(this.consentKey, 'accepted');
153+
this.removeBanner();
154+
this.enableAnalytics();
155+
156+
// Track consent given
157+
if (typeof gtag !== 'undefined') {
158+
gtag('consent', 'update', {
159+
'analytics_storage': 'granted'
160+
});
161+
162+
gtag('event', 'consent_given', {
163+
event_category: 'Privacy',
164+
consent_type: 'analytics'
165+
});
166+
}
167+
},
168+
169+
reject() {
170+
this.hasConsent = false;
171+
localStorage.setItem(this.consentKey, 'rejected');
172+
this.removeBanner();
173+
174+
// Ensure analytics stays disabled
175+
if (typeof gtag !== 'undefined') {
176+
gtag('consent', 'update', {
177+
'analytics_storage': 'denied'
178+
});
179+
}
180+
},
181+
182+
removeBanner() {
183+
const banner = document.getElementById('cookie-consent-banner');
184+
if (banner) {
185+
banner.style.animation = 'slideDown 0.3s ease-out';
186+
banner.style.animationFillMode = 'forwards';
187+
setTimeout(() => banner.remove(), 300);
188+
}
189+
},
190+
191+
enableAnalytics() {
192+
// Initialize analytics only after consent
193+
if (window.EventAnalytics && typeof window.EventAnalytics.init === 'function') {
194+
window.EventAnalytics.init();
195+
}
196+
197+
// Fire page view if it hasn't been sent
198+
if (typeof gtag !== 'undefined') {
199+
gtag('event', 'page_view', {
200+
page_location: window.location.href,
201+
page_title: document.title
202+
});
203+
}
204+
},
205+
206+
// Check if user has consented (for use in other scripts)
207+
canTrack() {
208+
return this.hasConsent;
209+
}
210+
};
211+
212+
// Wait for DOM to be ready
213+
if (document.readyState === 'loading') {
214+
document.addEventListener('DOMContentLoaded', () => CookieConsent.init());
215+
} else {
216+
CookieConsent.init();
217+
}
218+
219+
// Make it globally available
220+
window.CookieConsent = CookieConsent;

0 commit comments

Comments
 (0)