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