PageSourceSearch

https://admin.aura.travel/assets/7508853d/js/cookie-consent.js

js aura.travel collected 2026-09-28 11:43:13 UTC 16,815 bytes, 459 lines download raw bytes

1(function (window, document) {
2    'use strict';
3
4    if (!window || !document) {
5        return;
6    }
7
8    const STORAGE_KEY = 'aura_cookie_consent';
9    // Set when the visitor closes the banner without choosing: it stays closed for the rest of the browser session.
10    const CLOSED_KEY = 'aura_cookie_banner_closed';
11
12    function safeParse(value) {
13        try {
14            return value ? JSON.parse(value) : null;
15        } catch (error) {
16            return null;
17        }
18    }
19
20    const CookieConsent = {
21        initialized: false,
22        options: null,
23
24        init: function (options) {
25            if (this.initialized) {
26                this.options = options || this.options || {};
27                return;
28            }
29
30            this.options = options || {};
31            this.initialized = true;
32            this.setupEvents();
33
34            const serverConsent = this.getServerConsent();
35            const localConsent = this.getConsent();
36            const current = serverConsent || (localConsent && !this.isExpired(localConsent) ? localConsent : null);
37            // The visitor's choice, or until they make one, the default for their country (options.*Default).
38            const prefs = current ? current.preferences || {} : this.defaultPreferences();
39
40            this.startGoogleTags(prefs);
41            this.applyConsent(prefs);
42
43            if (serverConsent) {
44                this.persistConsent(serverConsent);
45                this.showCollapsedTrigger();
46
47                if (serverConsent.needsSessionSync) {
48                    this.sendToServer(serverConsent.preferences || {});
49                }
50                return;
51            }
52
53            if (current) {
54                this.showCollapsedTrigger();
55                this.sendToServer(localConsent.preferences || {});
56                return;
57            }
58
59            this.clearConsent();
60            if ((this.options.initialMode || 'popup') === 'collapsed' || this.bannerClosed()) {
61                this.showCollapsedTrigger();
62            } else {
63                this.showBanner();
64            }
65        },
66
67        getServerConsent: function () {
68            const consent = this.options.serverConsent || null;
69            if (!consent || !consent.preferences) {
70                return null;
71            }
72
73            return consent;
74        },
75
76        getConsent: function () {
77            try {
78                return safeParse(window.localStorage.getItem(STORAGE_KEY));
79            } catch (error) {
80                return null;
81            }
82        },
83
84        isExpired: function (consent) {
85            if (!consent || !consent.timestamp) {
86                return true;
87            }
88
89            const expiry = new Date(consent.timestamp);
90            expiry.setDate(expiry.getDate() + (this.options.expiryDays || 182));
91            return new Date() > expiry;
92        },
93
94        isBannerActive: function () {
95            const banner = document.getElementById('cookie-consent-banner');
96            const modal = document.getElementById('cookie-settings-modal');
97
98            if (!banner || banner.classList.contains('d-none')) {
99                return false;
100            }
101
102            return !modal || modal.classList.contains('d-none');
103        },
104
105        acceptAll: function () {
106            this.saveConsent({
107                necessary: true,
108                preferences: true,
109                analytics: true,
110                marketing: true,
111            });
112        },
113
114        showBanner: function () {
115            const banner = document.getElementById('cookie-consent-banner');
116            if (banner) {
117                banner.classList.remove('d-none');
118                banner.classList.add('show');
119            }
120
121            this.hideCollapsedTrigger();
122        },
123
124        // Closing is not a choice: the defaults stay in force and the banner stays closed for this browser session.
125        closeBanner: function () {
126            try {
127                window.sessionStorage.setItem(CLOSED_KEY, '1');
128            } catch (error) {
129                // storage blocked: the banner comes back on the next page
130            }
131            this.showCollapsedTrigger();
132        },
133
134        bannerClosed: function () {
135            try {
136                return window.sessionStorage.getItem(CLOSED_KEY) === '1';
137            } catch (error) {
138                return false;
139            }
140        },
141
142        hideBanner: function () {
143            const banner = document.getElementById('cookie-consent-banner');
144            if (banner) {
145                banner.classList.remove('show');
146                banner.classList.add('d-none');
147            }
148        },
149
150        showCollapsedTrigger: function () {
151            this.hideBanner();
152
153            const collapsed = document.getElementById('cookie-consent-collapsed');
154            if (collapsed) {
155                collapsed.classList.remove('d-none');
156            }
157        },
158
159        hideCollapsedTrigger: function () {
160            const collapsed = document.getElementById('cookie-consent-collapsed');
161            if (collapsed) {
162                collapsed.classList.add('d-none');
163            }
164        },
165
166        showModal: function () {
167            const modal = document.getElementById('cookie-settings-modal');
168            if (!modal) {
169                return;
170            }
171
172            modal.classList.remove('d-none');
173            modal.classList.add('show', 'd-flex');
174            const consent = this.getConsent() || this.getServerConsent();
175            if (consent && consent.preferences) {
176                this.loadPreferencesToModal(consent.preferences);
177            } else {
178                this.loadPreferencesToModal(this.defaultPreferences());
179            }
180        },
181
182        hideModal: function () {
183            const modal = document.getElementById('cookie-settings-modal');
184            if (modal) {
185                modal.classList.remove('show');
186                modal.classList.remove('d-flex');
187                modal.classList.add('d-none');
188            }
189        },
190
191        defaultPreferences: function () {
192            return {
193                necessary: true,
194                preferences: false,
195                analytics: !!this.options.analyticsDefault,
196                marketing: !!this.options.marketingDefault,
197            };
198        },
199
200        loadPreferencesToModal: function (prefs) {
201            const normalized = this.normalizePreferences(prefs || {});
202            const preferenceToggle = document.getElementById('cookie-preferences');
203            const analyticsToggle = document.getElementById('cookie-analytics');
204            const marketingToggle = document.getElementById('cookie-marketing');
205
206            if (preferenceToggle) {
207                preferenceToggle.checked = !!normalized.preferences;
208            }
209            if (analyticsToggle) {
210                analyticsToggle.checked = !!normalized.analytics;
211            }
212            if (marketingToggle) {
213                marketingToggle.checked = !!normalized.marketing;
214            }
215        },
216
217        normalizePreferences: function (prefs) {
218            return {
219                necessary: true,
220                preferences: !!prefs.preferences,
221                analytics: !!prefs.analytics,
222                marketing: !!prefs.marketing,
223            };
224        },
225
226        persistConsent: function (consent) {
227            try {
228                window.localStorage.setItem(STORAGE_KEY, JSON.stringify({
229                    preferences: this.normalizePreferences(consent.preferences || {}),
230                    timestamp: consent.timestamp || new Date().toISOString(),
231                    version: consent.version || '2.0'
232                }));
233            } catch (error) {
234                console.error('Cookie consent save failed:', error);
235            }
236        },
237
238        clearConsent: function () {
239            try {
240                window.localStorage.removeItem(STORAGE_KEY);
241            } catch (error) {
242                console.error('Cookie consent clear failed:', error);
243            }
244        },
245
246        saveConsent: function (prefs) {
247            const normalized = this.normalizePreferences(prefs || {});
248            const consent = {
249                preferences: normalized,
250                timestamp: new Date().toISOString(),
251                version: '2.0',
252            };
253
254            this.persistConsent(consent);
255
256            this.sendToServer(normalized);
257            if (window.ENABLE_GOOGLE_TAG_MANAGER && window.GTM_ID) {
258                this.setGoogleConsent('update', normalized);
259                window.dataLayer.push({ event: 'cookie_consent_update' });
260            }
261            this.applyConsent(normalized);
262            this.showCollapsedTrigger();
263            this.hideModal();
264        },
265
266        sendToServer: function (prefs) {
267            if (!this.options.saveUrl) {
268                return;
269            }
270
271            window.fetch(this.options.saveUrl, {
272                method: 'POST',
273                credentials: 'same-origin',
274                headers: {
275                    'Accept': 'application/json',
276                    'Content-Type': 'application/json',
277                    'X-Requested-With': 'XMLHttpRequest',
278                    'X-CSRF-Token': this.options.csrfToken || '',
279                },
280                body: JSON.stringify({ consent: prefs }),
281            }).catch(function (error) {
282                console.error('Server save failed:', error);
283            });
284        },
285
286        // The scripts the site loads itself (GTM loads on every page, see startGoogleTags()).
287        applyConsent: function (prefs) {
288            const normalized = this.normalizePreferences(prefs || {});
289
290            if (normalized.analytics) {
291                this.enableAnalytics();
292            }
293            if (normalized.marketing) {
294                this.enableMarketing();
295            }
296        },
297
298        // Google Consent Mode v2: GTM loads on every page, after the consent default, so each tag stores and sends
299        // only what the visitor allows (Google tags check it themselves; other tags need consent settings in GTM).
300        startGoogleTags: function (prefs) {
301            if (!window.ENABLE_GOOGLE_TAG_MANAGER || !window.GTM_ID) {
302                return;
303            }
304
305            this.setGoogleConsent('default', prefs);
306            this.enableGoogleTagManager();
307        },
308
309        // command: 'default' (before GTM loads) or 'update' (the visitor chose).
310        setGoogleConsent: function (command, prefs) {
311            const normalized = this.normalizePreferences(prefs || {});
312            const analytics = normalized.analytics ? 'granted' : 'denied';
313            const marketing = normalized.marketing ? 'granted' : 'denied';
314
315            window.dataLayer = window.dataLayer || [];
316            window.gtag = window.gtag || function () { window.dataLayer.push(arguments); };
317            window.gtag('consent', command, {
318                analytics_storage: analytics,
319                ad_storage: marketing,
320                ad_user_data: marketing,
321                ad_personalization: marketing,
322            });
323        },
324
325        enableGoogleTagManager: function () {
326            if (!window.ENABLE_GOOGLE_TAG_MANAGER || !window.GTM_ID || document.querySelector('script[data-cookie-consent-gtm]')) {
327                return;
328            }
329
330            window.dataLayer = window.dataLayer || [];
331            window.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
332
333            const gtmScript = document.createElement('script');
334            gtmScript.async = true;
335            gtmScript.src = 'https://www.googletagmanager.com/gtm.js?id=' + encodeURIComponent(window.GTM_ID);
336            gtmScript.setAttribute('data-cookie-consent-gtm', '1');
337            document.head.appendChild(gtmScript);
338        },
339
340        enableAnalytics: function () {
341            if (window.ENABLE_GOOGLE_ANALYTICS && window.GA_TRACKING_ID && !document.querySelector('script[data-cookie-consent-ga]')) {
342                const gaScript = document.createElement('script');
343                gaScript.async = true;
344                gaScript.src = 'https://www.google-analytics.com/analytics.js';
345                gaScript.setAttribute('data-cookie-consent-ga', '1');
346                document.head.appendChild(gaScript);
347            }
348
349            if (window.ENABLE_GOOGLE_GTAG && window.GTAG_ID && !document.querySelector('script[data-cookie-consent-gtag]')) {
350                const gtagScript = document.createElement('script');
351                gtagScript.async = true;
352                gtagScript.src = 'https://www.googletagmanager.com/gtag/js?i
352d=' + encodeURIComponent(window.GTAG_ID);
353                gtagScript.setAttribute('data-cookie-consent-gtag', '1');
354                document.head.appendChild(gtagScript);
355                window.dataLayer = window.dataLayer || [];
356                window.gtag = window.gtag || function () { window.dataLayer.push(arguments); };
357                window.gtag('js', new Date());
358                window.gtag('config', window.GTAG_ID);
359            }
360        },
361
362        enableMarketing: function () {
363            if (window.FB_PIXEL_ID && !window.fbq) {
364                !(function (f, b, e, v, n, t, s) {
365                    if (f.fbq) {
366                        return;
367                    }
368                    n = f.fbq = function () {
369                        n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);
370                    };
371                    if (!f._fbq) {
372                        f._fbq = n;
373                    }
374                    n.push = n;
375                    n.loaded = true;
376                    n.version = '2.0';
377                    n.queue = [];
378                    t = b.createElement(e);
379                    t.async = true;
380                    t.src = v;
381                    s = b.getElementsByTagName(e)[0];
382                    s.parentNode.insertBefore(t, s);
383                })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
384                window.fbq('init', window.FB_PIXEL_ID);
385                window.fbq('track', 'PageView');
386            }
387        },
388
389        setupEvents: function () {
390            const self = this;
391
392            window.openCookieSettings = function () {
393                self.showModal();
394            };
395
396            document.getElementById('cookie-consent-collapsed-trigger')?.addEventListener('click', function (event) {
397                event.preventDefault();
398                self.showModal();
399            });
400
401            document.getElementById('cookie-accept-all')?.addEventListener('click', function () {
402                self.acceptAll();
403            });
404
405            document.getElementById('cookie-banner-close')?.addEventListener('click', function () {
406                self.closeBanner();
407            });
408
409            document.getElementById('cookie-reject-all')?.addEventListener('click', function () {
410                self.saveConsent({
411                    necessary: true,
412                    preferences: false,
413                    analytics: false,
414                    marketing: false,
415                });
416            });
417
418            document.getElementById('cookie-settings-btn')?.addEventListener('click', function () {
419                self.showModal();
420            });
421
422            document.getElementById('cookie-settings-close')?.addEventListener('click', function () {
423                self.hideModal();
424            });
425
426            document.getElementById('cookie-save-settings')?.addEventListener('click', function () {
427                self.saveConsent({
428                    necessary: true,
429                    preferences: document.getElementById('cookie-preferences')?.checked || false,
430                    analytics: document.getElementById('cookie-analytics')?.checked || false,
431                    marketing: document.getElementById('cookie-marketing')?.checked || false,
432                });
433            });
434
435            document.getElementById('cookie-settings-modal')?.addEventListener('click', function (event) {
436                if (event.target === this) {
437                    self.hideModal();
438                }
439            });
440
441            document.addEventListener('keydown', function (event) {
442                if (!self.isBannerActive()) {
443                    return;
444                }
445
446                if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
447                    return;
448                }
449
450                if (event.key === 'Escape') {
451                    event.preventDefault();
452                    self.closeBanner();
453                }
454            });
455        },
456    };
457
458    window.AuraCookieConsent = CookieConsent;
459})(window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.