1/* ============================================================ 2 DNT Cookies â frontend JS 3 Consent Mode v2 + GA4 e-commerce events 4 PrestaShop 8.x | by Doneta 5 ============================================================ */ 6 7(function () { 8 'use strict'; 9 10 // ========================================================= 11 // Banner â zmienne DOM 12 // ========================================================= 13 14 var banner = document.getElementById('cookie-consent-banner'); 15 var overlay = document.getElementById('dnt-overlay'); 16 17 // ========================================================= 18 // Banner â show / hide (publiczne, dostÄpne z szablonu) 19 // ========================================================= 20 21 function hideBanner() { 22 if (banner) banner.style.display = 'none'; 23 if (overlay) overlay.style.display = 'none'; 24 } 25 26 window.dnt_cookie_showBanner = function () { 27 if (banner) banner.style.display = 'flex'; 28 if (overlay) overlay.style.display = 'block'; 29 }; 30 31 // RozwiniÄcie szczegóÅów (przycisk "Dowiedz siÄ wiÄcej") 32 window.dntShowMoreOptions = function () { 33 var opts = document.querySelector('.cookie-consent-options'); 34 var saveBtn = document.querySelector('.cookie-consent-button.btn-outline'); 35 var moreBtn = document.getElementById('btn-more-options'); 36 37 if (opts) opts.style.display = 'flex'; 38 if (saveBtn) saveBtn.style.display = 'block'; 39 if (moreBtn) moreBtn.style.display = 'none'; 40 41 document.querySelectorAll('.hide-reject').forEach(function (el) { 42 el.style.display = 'block'; 43 }); 44 }; 45 46 // Pokaż banner jeÅli brak zapisanej zgody 47 if (!document.cookie.includes('dnt_cookies=')) { 48 window.dnt_cookie_showBanner(); 49 } 50 51 // ========================================================= 52 // Banner â obsÅuga przycisków 53 // ========================================================= 54 55 var btnAll = document.getElementById('btn-accept-all'); 56 var btnSome = document.getElementById('btn-accept-some'); 57 var btnRej = document.getElementById('btn-reject-all'); 58 59 if (btnAll) { 60 btnAll.addEventListener('click', function () { 61 setConsent({ 62 functionality_storage: 'granted', 63 personalization_storage: 'granted', 64 ad_storage: 'granted', 65 analytics_storage: 'granted', 66 ad_user_data: 'granted', 67 ad_personalization: 'granted', 68 security_storage: 'granted', 69 }); 70 hideBanner(); 71 }); 72 } 73 74 if (btnSome) { 75 btnSome.addEventListener('click', function () { 76 setConsent({ 77 functionality_storage: 'granted', 78 personalization_storage: getChecked('consent-personalization_storage'), 79 ad_storage: getChecked('consent-ad_storage'), 80 analytics_storage: getChecked('consent-analytics_storage'), 81 ad_user_data: getChecked('consent-ad_user_data'), 82 ad_personalization: getChecked('consent-ad_personalization'), 83 security_storage: 'granted', 84 }); 85 hideBanner(); 86 }); 87 } 88 89 if (btnRej) { 90 btnRej.addEventListener('click', function () { 91 setConsent({ 92 functionality_storage: 'granted', 93 personalization_storage: 'denied', 94 ad_storage: 'denied', 95 analytics_storage: 'denied', 96 ad_user_data: 'denied', 97 ad_personalization: 'denied', 98 security_storage: 'granted', 99 }); 100 hideBanner(); 101 }); 102 } 103 104 // ========================================================= 105 // Banner â helper: stan checkboxa 106 // ========================================================= 107 108 function getChecked(id) { 109 var el = document.getElementById(id); 110 return (el && el.checked) ? 'granted' : 'denied'; 111 } 112 113 // ========================================================= 114 // Banner â setConsent: GTM update + cookie + zapis do DB 115 // ========================================================= 116 117 function setConsent(consent) { 118 // Zaktualizuj Consent Mode v2 w GTM 119 if (typeof gtag === 'function') { 120 gtag('consent', 'update', consent); 121 } 122 if (window.dataLayer) { 123 dataLayer.push({ event: 'consent-updated' }); 124 } 125 126 // ZamieÅ 'granted'/'denied' na true/false dla cookie i bazy 127 var stored = {}; 128 Object.keys(consent).forEach(function (k) { 129 stored[k] = (consent[k] === 'granted'); 130 }); 131 132 // Zapisz cookie (365 dni) 133 var expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toUTCString(); 134 document.cookie = 'dnt_cookies=' + JSON.stringify(stored) 135 + ';expires=' + expires + ';path=/;SameSite=Lax'; 136 137 // WyÅlij do bazy via PS AJAX controller 138 if (typeof dntAjaxUrl !== 'undefined' && dntAjaxUrl) { 139 fetch(dntAjaxUrl, { 140 method: 'POST', 141 credentials: 'same-origin', 142 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, 143 body: 'consent_mode=' + encodeURIComponent(JSON.stringify(stored)) 144 + '&page_url=' + encodeURIComponent(window.location.href), 145 }).catch(function () { 146 // silent fail â zapis do bazy nie jest krytyczny 147 }); 148 } 149 } 150 151 // ========================================================= 152 // Banner â przywrÃ³Ä stan checkboxów z zapisanego cookie 153 // ========================================================= 154 155 (function restoreCheckboxes() { 156 var match = document.cookie.match(/(?:^|; )dnt_cookies=([^;]*)/); 157 if (!match) { return; } 158 try { 159 var c = JSON.parse(decodeURIComponent(match[1])); 160 [ 161 'functionality_storage', 162 'personalization_storage', 163 'ad_storage',
164 'analytics_storage', 165 'ad_user_data', 166 'ad_personalization', 167 'security_storage', 168 ].forEach(function (k) { 169 var el = document.getElementById('consent-' + k); 170 if (el) { el.checked = !!c[k]; } 171 }); 172 } catch (e) { /* ignoruj bÅÄdne cookie */ } 173 }()); 174 175 176 // ========================================================= 177 // GA4 E-commerce â add_to_cart / remove_from_cart 178 // NasÅuch na natywny event bus PrestaShop 179 // ========================================================= 180 181 if (typeof prestashop !== 'undefined' && typeof prestashop.on === 'function' 182 && window.dntConfig && dntConfig.ev_cart_events) { 183 prestashop.on('updateCart', function (event) { 184 if (!event || !event.reason) { return; } 185 186 var reason = event.reason; 187 var isAdd = (reason.linkAction === 'add-to-cart'); 188 var isDel = (reason.linkAction === 'delete-from-cart' 189 || reason.linkAction === 'remove-product-in-cart'); 190 191 if (!isAdd && !isDel) { return; } 192 if (!window.dataLayer) { return; } 193 194 var idProduct = String(reason.idProduct || reason.id_product || ''); 195 var product = {}; 196 197 // ŹródÅo 1: produkty z odpowiedzi serwera (event.resp.cart.products) 198 // PS 8 zwraca peÅny koszyk po każdej operacji 199 if (event.resp && event.resp.cart && Array.isArray(event.resp.cart.products)) { 200 var cartProducts = event.resp.cart.products; 201 for (var i = 0; i < cartProducts.length; i++) { 202 if (String(cartProducts[i].id_product) === idProduct) { 203 product = cartProducts[i]; 204 break; 205 } 206 } 207 } 208 209 // ŹródÅo 2: prestashop.product â dostÄpne na stronie produktu 210 if (!product.name && typeof prestashop.product !== 'undefined') { 211 product = prestashop.product; 212 } 213 214 // ŹródÅo 3: reason.product â starsze wersje PS 215 if (!product.name && reason.product) { 216 product = reason.product; 217 } 218 219 dataLayer.push({ ecommerce: null }); 220 dataLayer.push({ 221 event: isAdd ? 'add_to_cart' : 'remove_from_cart', 222 ecommerce: { 223 items: [{ 224 item_id: String(product.id_product || product.id || idProduct || ''), 225 item_name: product.name || '', 226 price: parseFloat(product.price_amount || product.price_wt || product.price || 0), 227 quantity: parseInt(reason.quantity || product.cart_quantity || 1, 10), 228 }], 229 }, 230 }); 231 }); 232 } 233 234 235 // ========================================================= 236 // GA4 â click_email / click_phone 237 // Delegacja na document (Åapie dynamiczne linki) 238 // ========================================================= 239 240 if (window.dntConfig && dntConfig.ev_click) { 241 document.addEventListener('click', function (e) { 242 var target = e.target.closest('a[href]'); 243 if (!target || !window.dataLayer) { return; } 244 245 var href = target.getAttribute('href') || ''; 246 247 if (href.indexOf('mailto:') === 0) { 248 dataLayer.push({ 249 event: 'click_email', 250 email_address: href.replace('mailto:', '').split('?')[0], 251 }); 252 } else if (href.indexOf('tel:') === 0) { 253 dataLayer.push({ 254 event: 'click_phone', 255 phone_number: href.replace('tel:', ''), 256 }); 257 } 258 }); 259 } // end if dntConfig.ev_click 260 261}());
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.