Consent Mode v2 ile KVKK ve GDPR uyumlu çerez bandı kurmak
Google etiketlerinden önce çalışan varsayılan ret, sürümlü tercih kaydı ve geri alınabilir onay: çerez bandını adım adım kurmak.
Bir siteye Google Analytics ya da AdSense eklemek birkaç satırlık iş gibi görünür. Asıl emek, bu etiketlerin ziyaretçinin onayına uygun davranmasını sağlamaktır: onay yokken çerez yazmamak, ziyaretçi fikrini değiştirdiğinde bunu hemen uygulamak ve bütün bunları sayfanın her açılışında, gecikmesiz yapmak. Google'ın Consent Mode v2 (İzin Modu) yapısı bu davranışı etiketlere bildirmenin standart yolu; çerez bandı ise ziyaretçinin kararını topladığımız arayüz.
Bu yazıda, bu sitede kullandığımız düzeni adım adım anlatıyoruz: sayfanın en başında çalışan varsayılan ret, sürümlü olarak saklanan tercih, kabul kadar kolay ret düğmesi ve istenildiği an geri alınabilen onay. Bir uyarıyla başlayalım: burada anlatılanlar teknik bir uygulama örneğidir, hukuki tavsiye değildir. KVKK ve GDPR yükümlülükleri sitenin ne topladığına ve kimlere aktardığına göre değişir; metinlerinizi bir hukukçuyla birlikte değerlendirmeniz gerekir.
Consent Mode v2'nin dört sinyali
Consent Mode, Google etiketlerine ziyaretçinin hangi kullanımlara izin verdiğini anlatan bir dizi anahtar kullanır. Sürüm 2 ile birlikte reklam tarafında iki yeni sinyal eklendi; bugün temel olarak dört sinyalle çalışıyoruz:
analytics_storage: analitik amaçlı çerez ve benzeri depolamaya (örneğin Google Analytics'in_gaçerezleri) izin verilip verilmediği.ad_storage: reklamla ilgili çerezlerin yazılıp okunabilmesi.ad_user_data: kullanıcıya ait verinin reklam amaçlı Google'a gönderilmesine onay.ad_personalization: kişiselleştirilmiş reklam (yeniden pazarlama gibi) için onay.
Her sinyal 'granted' ya da 'denied' değerini alır. Bizim bantta ziyaretçiye iki kategori sunuyoruz, "Analitik" ve "Reklam". Analitik kutusu analytics_storage sinyalini, Reklam kutusu ise üç reklam sinyalini birlikte yönetiyor. Ziyaretçiye dört ayrı teknik terim göstermek yerine anlaşılır iki seçenek sunmak, onayın gerçekten bilerek verilmesine de yardım eder.
Varsayılan ret: her şeyden önce
Sıralama bu yapının en önemli parçası. Google etiketleri yüklenmeden önce bütün sinyallerin varsayılan değeri 'denied' olarak bildirilmelidir. Aksi hâlde etiket, varsayılan gelmeden kısa bir an için onay varmış gibi davranabilir. Bu yüzden varsayılanı ayrı bir dosyada değil, <head> içinde satır içi bir betik olarak, bütün Google kodlarından önce basıyoruz:
window.dataLayer = window.dataLayer || [];
function gtag(){ dataLayer.push(arguments); }
gtag('consent', 'default', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'denied',
wait_for_update: 500
});
gtag('set', 'ads_data_redaction', true);
Buradaki iki ayar ayrıca açıklamaya değer. wait_for_update: 500, etiketlere "bir güncelleme gelebilir, göndermeden önce en fazla 500 milisaniye bekle" der. Kayıtlı bir tercih varsa bunu hemen sonraki betikte uyguladığımız için bu süre çoğu zaman kullanılmaz bile; ama sıralama beklenmedik biçimde değişirse güvenlik payı sağlar. ads_data_redaction ise ad_storage reddedildiğinde reklam isteklerindeki tıklama tanımlayıcısı gibi bilgilerin ayıklanmasını ister.
Satır içi betik kullanmak, Content Security Policy açısından bir soru doğurur: 'unsafe-inline' açmadan bu betiğe nasıl izin verilir? Bunun cevabını, betiğin SHA-256 özetini başlığa eklediğimiz CSP yazımızda ayrıntılı anlattık.
Kayıtlı tercihi hemen uygulamak
Varsayılandan hemen sonra, eşzamanlı (async ya da defer olmadan) yüklenen küçük bir dosya ziyaretçinin daha önce verdiği kararı okur ve gtag('consent', 'update', …) ile uygular. Ancak bu işlem tamamlandıktan sonra ölçüm etiketinin kendisi sayfaya eklenir. Tercihi tarayıcının localStorage alanında küçük bir JSON nesnesi olarak tutuyoruz:
var ANAHTAR = 'cerez_tercihi';
var OMUR_MS = 365 * 24 * 60 * 60 * 1000; // tercih 12 ay geçerli
var SURUM = '2026-09-29'; // çerez politikasının sürümü
function tercihOku() {
try {
var v = JSON.parse(localStorage.getItem(ANAHTAR) || 'null');
if (!v || v.s !== SURUM || typeof v.t !== 'number') return null;
if (Date.now() - v.t > OMUR_MS) return null;
return v; // {s: sürüm, a: analitik, r: reklam, t: zaman}
} catch (e) { return null; }
}
function izinler(t) {
var a = t && t.a ? 'granted' : 'denied';
var r = t && t.r ? 'granted' : 'denied';
return { analytics_storage: a, ad_storage: r, ad_user_data: r, ad_personalization: r };
}
var kayitli = tercihOku();
if (kayitli) gtag('consent', 'update', izinler(kayitli));
Tercihi çerez yerine localStorage içinde tutmak, bu bilginin her HTTP isteğiyle sunucuya gitmemesini sağlar; tercih yalnız tarayıcıda kalır. Özel pencerede ya da depolamanın kapalı olduğu tarayıcılarda localStorage hata verebileceği için okuma ve yazma try blokları içinde. Depolama yoksa tercih okunamaz ve bant yeniden gösterilir; bu, onaysız ölçüm yapmaktan her zaman daha güvenli bir hatadır.
Tercih sürümü ve on iki aylık ömür
Kaydedilen nesnede iki alan özellikle önemli. Birincisi s, yani çerez politikasının sürümü. Politika metni özünden değiştiğinde, örneğin siteye reklam çerezleri eklendiğinde, sunucu tarafındaki sürüm sabitini artırıyoruz. Bant ve etiket dosyası bu sürümü sayfadan okuyor; kayıtlı tercihin sürümü güncel sürümle eşleşmezse tercih yok sayılıyor ve bant ziyaretçiye yeniden soruyor. Böylece eski metne verilmiş bir onay, kapsamı genişlemiş yeni bir kullanım için geçerli sayılmıyor.
İkincisi t, tercihin kaydedildiği an. On iki aydan eski tercihler de yok sayılıyor ve soru yeniden soruluyor. Bu süre bir yasa maddesinden değil, ziyaretçiye makul aralıklarla kararını hatırlatma isteğimizden geliyor; kendi siteniz için süreyi hukukçunuzla birlikte belirleyin.
Reddetmek kabul etmek kadar kolay olmalı
Onayın özgür iradeye dayanması için ret yolunun gizlenmemesi gerekir. Bantta "Tümünü reddet" ve "Tümünü kabul et" düğmeleri aynı boyutta, aynı görsel ağırlıkta ve yan yana duruyor. Ayrıntılı seçim isteyen ziyaretçi için "Tercihler" düğmesi bir panel açıyor; bu paneldeki Analitik ve Reklam kutuları ön işaretsiz geliyor. Zorunlu çerezler satırı ise işaretli ve değiştirilemez; çünkü dil tercihi ya da form sonrası mesaj gibi işlevler onları gerektiriyor ve ziyaretçiye bunu açıkça gösteriyoruz.
Kaydetme işlevi, seçimi saklayıp Google tarafına bildiren tek bir fonksiyonda toplanıyor:
function kaydet(analitik, reklam) {
var onceki = tercihOku();
var t = { s: SURUM, a: !!analitik, r: !!reklam, t: Date.now() };
try { localStorage.setItem(ANAHTAR, JSON.stringify(t)); } catch (e) {}
gtag('consent', 'update', izinler(t));
if (!t.a && (!onceki || onceki.a)) analitikCerezleriniSil();
bandiKapat();
}
Bant HTML'i sunucuda basılıyor ve başlangıçta hidden durumda. Betik yalnız davranışı yönetiyor: geçerli bir tercih yoksa bandı gösteriyor ve klavyeyle gezinen ziyaretçi için odağı ilk görünür düğmeye taşıyor. Bandın ekran okuyucularda bir iletişim kutusu olarak duyurulması için role="dialog" ve başlık-açıklama eşleştirmesi kullanıyoruz.
Onayı geri almak
Onay, verildiği kadar kolay geri alınabilmelidir. Sitenin her sayfasının alt bilgisinde "Çerez tercihleri" bağlantısı var; bu bağlantı bandı tercih paneli açık hâlde yeniden gösteriyor. Ziyaretçi analitik onayını geri çektiğinde Consent Mode güncellemesi hemen gönderiliyor, ayrıca tarayıcıda kalmış Google Analytics çerezleri (_ga, _ga_*, _gid, _gat) siliniyor. Silme işlemi, çerezin hangi alan adı düzeyinde yazılmış olabileceğini bilmediğimiz için alan adının her üst düzeyi için tekrarlanıyor:
function analitikCerezleriniSil() {
var parca = location.hostname.split('.');
var alanlar = [location.hostname, ''];
for (var i = 0; i < parca.length - 1; i++) alanlar.push('.' + parca.slice(i).join('.'));
document.cookie.split(';').forEach(function (c) {
var ad = c.split('=')[0].trim();
if (ad === '_ga' || ad.indexOf('_ga_') === 0 || ad === '_gid' || ad === '_gat') {
alanlar.forEach(function (d) {
document.cookie = ad + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/' + (d ? '; domain=' + d : '');
});
}
});
}
Temel ve gelişmiş uygulama farkı
Google, Consent Mode için iki uygulama biçimi tarif eder. Temel (basic) uygulamada Google etiketleri, ziyaretçi onay verene kadar hiç yüklenmez; onay yoksa Google'a hiçbir istek gitmez. Gelişmiş (advanced) uygulamada etiketler sayfa açılışında varsayılan ret durumuyla yüklenir; izin reddedilmişken çerez yazmazlar, ancak Google'ın belgelerinde "çerezsiz ping" olarak geçen, tanımlayıcı taşımayan sinyaller gönderebilirler. Google bu sinyallerle ölçüm boşluklarını modelleme yoluyla tahmin etmeye çalışır.
Bizim kurulumumuz, etiketleri varsayılan retle yükleyen gelişmiş biçime karşılık gelir ve gizlilik metnimiz de bunu açıkça söyler: onay verilmezse analitik çerez yazılmaz, yalnız çerezsiz sinyaller gidebilir. Hangisinin size uygun olduğu, ölçüm ihtiyacınıza ve hukukçunuzun onaysız çerezsiz sinyaller hakkındaki değerlendirmesine bağlıdır. Temel uygulamayı seçerseniz yapılacak değişiklik basit: ölçüm etiketini sayfaya ekleyen kodu, kayıtlı tercihte izin varsa çalışacak şekilde koşula bağlamak.
KVKK ve GDPR açısından dikkat edilecekler
Teknik düzenin yanında metinlerin de tutarlı olması gerekir. Bizim dikkat ettiğimiz noktalar şunlar:
- Çerez bandındaki kısa metin ile gizlilik ve çerez politikası sayfası aynı şeyi söylemeli; bantta "yalnız analitik" denip politikada reklam çerezleri anlatılıyorsa bu bir çelişkidir.
- Politikada her çerezin adı, amacı, türü (birinci taraf ya da üçüncü taraf) ve süresi bir tabloda yer almalı.
- Zorunlu çerezler gerçekten zorunlu olmalı. "Zorunlu" başlığı altına analitik çerez koymak, onay mekanizmasını anlamsız kılar.
- Avrupa Ekonomik Alanı, Birleşik Krallık ve İsviçre'den gelen ziyaretçilere reklam gösteriliyorsa Google, Google tarafından sertifikalandırılmış bir rıza yönetim platformu kullanılmasını ister. Bizim bandımız, Google'ın kendi rıza mesajı sayfada göründüğünde kendini gizliyor; böylece ziyaretçi aynı soruyla iki kez karşılaşmıyor.
Bu maddeler bir kontrol listesidir, hukuki görüş değildir. Kişisel verinin yurt dışına aktarımı gibi konularda KVKK'nın kendine özgü kuralları vardır ve metinlerin son hâli mutlaka bir hukukçu tarafından okunmalıdır.
Sonuç
İyi bir çerez bandı, görünen yüzünden çok sıralamasıyla ilgilidir: önce varsayılan ret, hemen ardından kayıtlı tercih, en son ölçüm etiketi. Tercihi sürümlü ve süreli saklamak, politika değiştiğinde ya da zaman geçtiğinde soruyu yeniden sormayı otomatik hâle getirir. Kabul ve reddi eşit ağırlıkta sunmak, ön işaretsiz kutular ve her sayfadan erişilebilen geri alma bağlantısı ise onayın gerçekten ziyaretçinin kararı olmasını sağlar. Bu parçaların her birini küçük, okunabilir fonksiyonlarda tutmak, denetim sırasında neyin neden yapıldığını göstermeyi de kolaylaştırır.
Benzer bir sistem mi kuruyorsunuz?
İhtiyacınızı birkaç cümleyle yazın; uygun bir yol varsa birlikte netleştirelim.
Bize yazın