🢂Implementacja zgody (RODO) i cookies dla gtag.js (GA4)
Zarządzanie zgodą użytkownika i zapisem cookies w Google Analytics
Ten fragment kodu ustawia domyślnie brak zgody na przetwarzanie danych, tworzy lekki „shim” gtag() przed załadowaniem GA4 oraz zapisuje wybór użytkownika w cookie. Po akceptacji lub odmowie zgody aktualizuje status w gtag('consent', ...)
, dzięki czemu Analytics i funkcje reklamowe działają wyłącznie zgodnie z wyborem użytkownika.
Krótki opis
- Naprawa błędu setCookie is not defined przez dodanie własnej, prostej implementacji.
- Rozdzielenie logiki: domyślnie denied, a „granted” dopiero po świadomej akceptacji (np. klik w baner).
- Przechowywanie wyboru w cookie (SameSite=Lax, Secure przy HTTPS) i jego odtwarzanie przy kolejnych wizytach.
- Zgodność z GA4: użycie gtag('consent', 'default'|'update', {...}) dla poszczególnych obszarów zgód.
<script>
// --- utils: cookies ---
function setCookie(name, value, days) {
var expires = "";
if (typeof days === "number") {
var d = new Date();
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
expires = "; expires=" + d.toUTCString();
}
var secure = location.protocol === "https:" ? "; Secure" : "";
document.cookie =
encodeURIComponent(name) + "=" + encodeURIComponent(value) +
expires + "; path=/; SameSite=Lax" + secure;
}
function getCookie(name) {
var n = encodeURIComponent(name) + "=";
var parts = document.cookie.split("; ");
for (var i = 0; i < parts.length; i++) {
if (parts[i].indexOf(n) === 0) return decodeURIComponent(parts[i].slice(n.length));
}
return "";
}
// --- gtag shim + domyślna zgoda: DENIED ---
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
var CONSENT_DENIED = {
analytics_storage: 'denied',
display_features: 'denied',
personalization_storage: 'denied',
security_storage: 'denied',
functionality_storage: 'denied',
ad_personalization: 'denied',
ad_storage: 'denied',
ad_personalization_signals: 'denied',
ad_user_data: 'denied'
};
var CONSENT_GRANTED = {
analytics_storage: 'granted',
display_features: 'granted',
personalization_storage: 'granted',
security_storage: 'granted',
functionality_storage: 'granted',
ad_personalization: 'granted',
ad_storage: 'granted',
ad_personalization_signals: 'granted',
ad_user_data: 'granted'
};
// Przy starcie ustawiamy domyślnie DENIED (zgodnie z RODO)
gtag('consent', 'default', CONSENT_DENIED);
setCookie('consent', JSON.stringify(CONSENT_DENIED), 180);
// Jeśli masz zapisany wybór z poprzedniej wizyty, zastosuj go:
(function restoreSavedConsent(){
try {
var saved = getCookie('consent');
if (saved) {
var obj = JSON.parse(saved);
gtag('consent', 'update', obj);
}
} catch(e) {}
})();
// Wywołaj to dopiero po zgodzie użytkownika (np. handler przycisku „Akceptuję”)
function grantConsent(){
gtag('consent', 'update', CONSENT_GRANTED);
setCookie('consent', JSON.stringify(CONSENT_GRANTED), 180);
}
// Ewentualnie handler odmowy
function denyConsent(){
gtag('consent', 'update', CONSENT_DENIED);
setCookie('consent', JSON.stringify(CONSENT_DENIED), 180);
}
</script>
Jak to działa:
Pierwsza wizyta
- Na starcie ustawiasz default = denied.
- Dopiero po świadomej akceptacji wywołujesz grantConsent(), co ustawia granted. Bez akcji użytkownika pozostaje denied.
Ta sama wizyta po kliknięciu
- Po kliknięciu „Akceptuję” wywołujesz grantConsent() i od razu masz granted.
Kolejne wizyty
- Skrypt na początku ustawia default = denied, a następnie funkcja odtwarzająca wybór z ciasteczka natychmiast robi
gtag('consent','update', ...)
zgodnie z zapisanym wyborem. Jeśli w ciastku było granted, to praktycznie od razu po starcie masz granted.
Przykład podpięcia pod przyciski w banerze:
<button onclick="grantConsent()">Akceptuję</button>
<button onclick="denyConsent()">Odmawiam</button>
Kompletna implementacja
<!-- Baner zgody (przykład) -->
<div id="cookie-banner" style="position:fixed;bottom:0;left:0;right:0;padding:12px;background:#f3f3f3;border-top:1px solid #ddd;">
Używamy plików cookie do analityki. Zgadzasz się?
<button data-consent="accept">Akceptuję</button>
<button data-consent="reject">Odrzucam</button>
</div>
<script>
// Opcjonalnie: Twój identyfikator GA4. Jeśli nie chcesz autoładować GA po zgodzie, usuń GA_MEASUREMENT_ID i loadGA.
const GA_MEASUREMENT_ID = "G-XXXXXXXXXX";
// --- utils: cookies ---
function setCookie(name, value, days) {
var expires = "";
if (typeof days === "number") {
var d = new Date(); d.setTime(d.getTime() + days * 864e5);
expires = "; expires=" + d.toUTCString();
}
var secure = location.protocol === "https:" ? "; Secure" : "";
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) +
expires + "; path=/; SameSite=Lax" + secure;
}
function getCookie(name) {
var n = encodeURIComponent(name) + "=";
var parts = document.cookie.split("; ");
for (var i = 0; i < parts.length; i++) if (parts[i].indexOf(n) === 0)
return decodeURIComponent(parts[i].slice(n.length));
return "";
}
// --- gtag shim + domyślna zgoda: DENIED ---
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
var CONSENT_DENIED = {
analytics_storage: 'denied',
display_features: 'denied',
personalization_storage: 'denied',
security_storage: 'denied',
functionality_storage: 'denied',
ad_personalization: 'denied',
ad_storage: 'denied',
ad_personalization_signals: 'denied',
ad_user_data: 'denied'
};
var CONSENT_GRANTED = {
analytics_storage: 'granted',
display_features: 'granted',
personalization_storage: 'granted',
security_storage: 'granted',
functionality_storage: 'granted',
ad_personalization: 'granted',
ad_storage: 'granted',
ad_personalization_signals: 'granted',
ad_user_data: 'granted'
};
gtag('consent', 'default', CONSENT_DENIED);
setCookie('consent', JSON.stringify(CONSENT_DENIED), 180);
// Opcjonalnie: ładuj GA dopiero po zgodzie
function loadGA(id) {
if (!id || window.__gaLoaded) return;
var s = document.createElement('script');
s.async = true; s.src = 'https://www.googletagmanager.com/gtag/js?id=' + id;
s.onload = function() {
gtag('js', new Date());
gtag('config', id);
window.__gaLoaded = true;
};
document.head.appendChild(s);
}
// Funkcje publiczne
function grantConsent(){
gtag('consent', 'update', CONSENT_GRANTED);
setCookie('consent', JSON.stringify(CONSENT_GRANTED), 180);
loadGA(GA_MEASUREMENT_ID); // usuń tę linię, jeśli GA ma być ładowane zawsze
hideBanner();
}
function denyConsent(){
gtag('consent', 'update', CONSENT_DENIED);
setCookie('consent', JSON.stringify(CONSENT_DENIED), 180);
hideBanner();
}
function hideBanner(){
var b = document.getElementById('cookie-banner');
if (b && b.parentNode) b.parentNode.removeChild(b);
}
// Odtwórz wybór z poprzedniej wizyty
(function restoreSavedConsent(){
try {
var saved = getCookie('consent');
if (saved) {
var obj = JSON.parse(saved);
gtag('consent', 'update', obj);
if (obj.analytics_storage === 'granted') loadGA(GA_MEASUREMENT_ID);
// Jeśli zgoda była już udzielona, możesz od razu schować baner:
if (obj.analytics_storage === 'granted') hideBanner();
}
} catch(e) {}
})();
// >>> TU DODAJEMY WYWOŁANIE grantConsent() PO KLIKNIĘCIU <<<
// Obsługa przycisków w banerze
document.querySelectorAll('[data-consent="accept"]').forEach(function (btn) {
btn.addEventListener('click', grantConsent); // <-- wywołanie grantConsent()
});
document.querySelectorAll('[data-consent="reject"]').forEach(function (btn) {
btn.addEventListener('click', denyConsent);
});
// Opcja alternatywna: wywołaj z inline HTML, bo funkcje są w globalnym scope:
// <button onclick="grantConsent()">Akceptuję</button>
</script>
Przykład użycia - Najważniejsze elementy:
grantConsent()
wywoływane jest bezpośrednio w handlerze kliknięcia „Akceptuję”.- Domyślna polityka to denied i pozostaje taka, dopóki użytkownik nie kliknie.
- Zapisujemy wybór w cookie i odtwarzamy go przy kolejnych wizytach.
- GA4 może ładować się dopiero po zgodzie. Jeśli chcesz ładować GA zawsze, usuń
loadGA(...)
i wstaw standardowy<script src="https://www.googletagmanager.com/gtag/js?...">
w<head>
.
Jak dodać do GTM (kolejne kroki)
-
Włącz zgodność i tryb zgody
W GTM wejdź: Admin → Container settings → zaznacz Enable consent overview.
-
Tag 1: Consent defaults (DENIED)
Utwórz Tag → Custom HTML.
Tag type: Consent Initialization
Trigger: Consent Initialization – All Pages
Wklej:
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('consent', 'default', {
ad_storage: 'denied',
analytics_storage: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied',
security_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied'
});
// prosty setCookie (opcjonalnie)
function setCookie(n, v, d){
var e = "";
if (typeof d === "number") {
var dt = new Date(); dt.setTime(dt.getTime() + d*864e5);
e = "; expires=" + dt.toUTCString();
}
var s = location.protocol === "https:" ? "; Secure" : "";
document.cookie = encodeURIComponent(n) + "=" + encodeURIComponent(v) + e + "; path=/; SameSite=Lax" + s;
}
// zapisz domyślną decyzję
setCookie('consent', JSON.stringify({
ad_storage:'denied', analytics_storage:'denied',
functionality_storage:'denied', personalization_storage:'denied',
security_storage:'denied', ad_user_data:'denied', ad_personalization:'denied'
}), 180);
</script>
1. Tag 2: Consent update (GRANTED po zgodzie)
Utwórz Tag → Custom HTML.
Trigger: Custom Event o nazwie `consent_granted` (stwórz nowy trigger Custom Event: Event name = `consent_granted`).
Kod:
<script>
function gtag(){ dataLayer.push(arguments); }
gtag('consent', 'update', {
ad_storage: 'granted',
analytics_storage: 'granted',
functionality_storage: 'granted',
personalization_storage: 'granted',
security_storage: 'granted',
ad_user_data: 'granted',
ad_personalization: 'granted'
});
// spójnie z tagiem default: zapisz wybór
(function setCookie(n, v, d){
var e = "";
if (typeof d === "number") {
var dt = new Date(); dt.setTime(dt.getTime() + d*864e5);
e = "; expires=" + dt.toUTCString();
}
var s = location.protocol === "https:" ? "; Secure" : "";
document.cookie = encodeURIComponent(n) + "=" + encodeURIComponent(v) + e + "; path=/; SameSite=Lax" + s;
})('consent', JSON.stringify({
ad_storage:'granted', analytics_storage:'granted',
functionality_storage:'granted', personalization_storage:'granted',
security_storage:'granted', ad_user_data:'granted', ad_personalization:'granted'
}), 180);
</script>
1. Powiąż baner z GTM
Masz dwie proste opcje. Wybierz jedną.
A) Z poziomu kodu banera (najprościej): po kliknięciu „Akceptuję” wyślij event do dataLayer:
<script>
// w Twoim kodzie banera (po kliknięciu Akceptuję):
dataLayer = window.dataLayer || [];
dataLayer.push({ event: 'consent_granted' });
</script>
To odpali Tag 2 i ustawi granted.
B) Z poziomu GTM (nasłuch klików): jeśli przycisk ma id consent-accept
, zrób Trigger → Click → Just Links lub All Elements z warunkiem Click ID equals consent-accept
, a potem w Tagu (Custom HTML) uruchamianym tym triggerem wstaw:
<script>
dataLayer.push({ event: 'consent_granted' });
</script>
Dzięki temu Tag 2 wstrzyknie po kliknięciu.
- GA4 w GTM
- GA4 Configuration Tag może ładować się od razu, ale dzięki Consent Mode dane będą ograniczone przy denied.
- Upewnij się w GA4 tagu: Advanced Settings → Consent Settings → Use consent settings to improve tag delivery.
- Jeśli chcesz ładować GA4 dopiero po zgodzie, ustaw trigger GA4 na Custom Event
consent_granted
zamiast All Pages. To bardziej restrykcyjne podejście.
Szybkie podsumowanie
- Tag Consent Initialization na All Pages ustawia default = denied.
- Po akceptacji baner robi
dataLayer.push({event:'consent_granted'})
. - Tag Consent update, odpalany tym eventem, ustawia granted i zapisuje cookie.
- GA4 albo startuje od razu i respektuje zgodę, albo odpalasz go dopiero po
consent_granted
(bardziej „privacy-first”).