Kullanıcı Onayına Göre Script Yükleme: GDPR Uyumlu WordPress Çözümü
GDPR uyumluluğu, özellikle Avrupa’daki kullanıcılara hizmet veren site sahipleri için artık bir seçenek değil, zorunluluk. WordPress sitenizde Google Analytics, Facebook Pixel, Hotjar gibi üçüncü taraf scriptleri kullanıyorsanız, bu scriptleri kullanıcı onayı olmadan yüklemek ciddi para cezalarına yol açabilir. Peki bu işi düzgün yapmak için mutlaka pahalı bir eklenti mi kullanmanız gerekiyor? Hayır. functions.php dosyasına birkaç fonksiyon ekleyerek, kullanıcı onayına göre script yükleme sistemini kendiniz kurabilirsiniz.
GDPR ve Script Yükleme: Temel Mantık
GDPR’ın özü şu: Kullanıcıdan kişisel veri toplayan her şey için önceden açık rıza alınmalı. Üçüncü taraf scriptler, özellikle tracking ve analytics araçları, bu kategoriye giriyor.
Teknik olarak yapmanız gereken şey oldukça net:
- Kullanıcı siteye ilk girdiğinde bir onay banner’ı göster
- Kullanıcı “Kabul Et” derse, ilgili scriptleri yükle ve bu tercihi cookie’ye kaydet
- Kullanıcı “Reddet” derse, scriptleri yükleme ve bunu da kaydet
- Sonraki ziyaretlerde cookie’yi kontrol et, tercihine göre davran
Bu akışı WordPress üzerinde functions.php ile nasıl inşa edeceğimize bakalım.
Cookie Yönetimi: Tercih Kaydetme ve Okuma
Her şeyin temeli cookie yönetimi. Kullanıcının tercihini hem JavaScript hem de PHP tarafında okuyabilmemiz gerekiyor.
JavaScript ile Cookie Yazma ve Okuma
// functions.php'ye ekleyin - GDPR Cookie Helper fonksiyonları
function gdpr_enqueue_cookie_helper() {
?>
<script type="text/javascript">
// Cookie yazma fonksiyonu
function gdprSetCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/; SameSite=Lax";
}
// Cookie okuma fonksiyonu
function gdprGetCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// Cookie silme fonksiyonu
function gdprDeleteCookie(name) {
document.cookie = name + '=; Max-Age=-99999999; path=/';
}
</script>
<?php
}
add_action('wp_head', 'gdpr_enqueue_cookie_helper', 1);
PHP Tarafında Cookie Kontrolü
// PHP ile kullanıcı tercihini kontrol etme
function gdpr_get_user_consent($category = 'analytics') {
$cookie_name = 'gdpr_consent_' . sanitize_key($category);
if (isset($_COOKIE[$cookie_name])) {
return $_COOKIE[$cookie_name] === 'accepted' ? true : false;
}
// Cookie yoksa henüz tercih yapılmamış demektir
return null;
}
// Belirli bir kategori için script yüklenip yüklenmeyeceğini kontrol et
function gdpr_can_load_script($category = 'analytics') {
$consent = gdpr_get_user_consent($category);
// null = henüz tercih yapılmamış, false döndür (güvenli taraf)
if ($consent === null || $consent === false) {
return false;
}
return true;
}
Consent Banner HTML ve CSS
Şimdi kullanıcıya gösterilecek onay banner’ını oluşturalım. Bu banner sadece cookie tercih edilmemişse görünmeli.
// GDPR Banner HTML çıktısı
function gdpr_consent_banner() {
// Eğer kullanıcı zaten tercih yapmışsa banner gösterme
if (isset($_COOKIE['gdpr_consent_analytics']) || isset($_COOKIE['gdpr_consent_marketing'])) {
return;
}
?>
<div id="gdpr-consent-banner" style="display:none;">
<div class="gdpr-banner-inner">
<div class="gdpr-banner-text">
<strong>Çerez Politikamız</strong>
<p>
Sitemizi daha iyi hale getirmek için analitik ve pazarlama çerezleri kullanıyoruz.
Tercihlerinizi yönetebilir veya tüm çerezleri kabul edebilirsiniz.
<a href="/cerez-politikasi" target="_blank">Daha fazla bilgi</a>
</p>
</div>
<div class="gdpr-banner-actions">
<button id="gdpr-accept-all" class="gdpr-btn gdpr-btn-accept">Tümünü Kabul Et</button>
<button id="gdpr-accept-necessary" class="gdpr-btn gdpr-btn-reject">Sadece Zorunlular</button>
<button id="gdpr-manage-preferences" class="gdpr-btn gdpr-btn-manage">Tercihleri Yönet</button>
</div>
</div>
<!-- Gelişmiş tercih paneli -->
<div id="gdpr-preferences-panel" style="display:none;">
<h3>Çerez Tercihleriniz</h3>
<div class="gdpr-preference-item">
<label>
<input type="checkbox" id="gdpr-analytics-toggle" value="analytics">
<strong>Analitik Çerezler</strong>
<span>Google Analytics gibi araçların ziyaretçi verisi toplamasına izin verir.</span>
</label>
</div>
<div class="gdpr-preference-item">
<label>
<input type="checkbox" id="gdpr-marketing-toggle" value="marketing">
<strong>Pazarlama Çerezleri</strong>
<span>Facebook Pixel gibi araçların reklam hedeflemesi yapmasına izin verir.</span>
</label>
</div>
<button id="gdpr-save-preferences" class="gdpr-btn gdpr-btn-save">Tercihleri Kaydet</button>
</div>
</div>
<style>
#gdpr-consent-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #1a1a1a;
color: #fff;
padding: 20px;
z-index: 99999;
box-shadow: 0 -4px 20px rgba(0,0,0,0.3);
}
.gdpr-banner-inner {
max-width: 1200px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 20px;
flex-wrap: wrap;
}
.gdpr-banner-text { flex: 1; min-width: 300px; }
.gdpr-banner-text p { margin: 5px 0 0; font-size: 14px; color: #ccc; }
.gdpr-banner-text a { color: #4CAF50; }
.gdpr-banner-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.gdpr-btn { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; }
.gdpr-btn-accept { background: #4CAF50; color: #fff; }
.gdpr-btn-reject { background: #555; color: #fff; }
.gdpr-btn-manage { background: transparent; color: #ccc; border: 1px solid #555; }
.gdpr-btn-save { background: #2196F3; color: #fff; margin-top: 15px; }
#gdpr-preferences-panel { padding: 20px 0 0; border-top: 1px solid #333; margin-top: 15px; }
.gdpr-preference-item { margin: 10px 0; }
.gdpr-preference-item label { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.gdpr-preference-item span { font-size: 13px; color: #999; display: block; }
</style>
<?php
}
add_action('wp_footer', 'gdpr_consent_banner', 99);
JavaScript ile Onay Yönetimi
Banner’ın işlevselliği için JavaScript kodunu yazalım. Bu kod, kullanıcı tercihlerini cookie’ye yazıyor ve scriptleri dinamik olarak yüklüyor.
function gdpr_consent_javascript() {
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var banner = document.getElementById('gdpr-consent-banner');
// Banner gösterim kontrolü
if (banner && !gdprGetCookie('gdpr_consent_analytics') && !gdprGetCookie('gdpr_consent_marketing')) {
// Küçük bir gecikme ile göster (sayfa yüklensin)
setTimeout(function() {
banner.style.display = 'block';
}, 500);
}
// Tümünü Kabul Et butonu
var acceptAllBtn = document.getElementById('gdpr-accept-all');
if (acceptAllBtn) {
acceptAllBtn.addEventListener('click', function() {
gdprSetCookie('gdpr_consent_analytics', 'accepted', 365);
gdprSetCookie('gdpr_consent_marketing', 'accepted', 365);
banner.style.display = 'none';
// Kabul sonrası scriptleri yükle
gdprLoadAnalyticsScripts();
gdprLoadMarketingScripts();
});
}
// Sadece Zorunlular butonu
var rejectBtn = document.getElementById('gdpr-accept-necessary');
if (rejectBtn) {
rejectBtn.addEventListener('click', function() {
gdprSetCookie('gdpr_consent_analytics', 'rejected', 365);
gdprSetCookie('gdpr_consent_marketing', 'rejected', 365);
banner.style.display = 'none';
});
}
// Tercihleri Yönet butonu
var manageBtn = document.getElementById('gdpr-manage-preferences');
if (manageBtn) {
manageBtn.addEventListener('click', function() {
var panel = document.getElementById('gdpr-preferences-panel');
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
// Mevcut durumu toggle'lara yansıt
var analyticsToggle = document.getElementById('gdpr-analytics-toggle');
var marketingToggle = document.getElementById('gdpr-marketing-toggle');
if (analyticsToggle) analyticsToggle.checked = gdprGetCookie('gdpr_consent_analytics') === 'accepted';
if (marketingToggle) marketingToggle.checked = gdprGetCookie('gdpr_consent_marketing') === 'accepted';
});
}
// Tercihleri Kaydet butonu
var saveBtn = document.getElementById('gdpr-save-preferences');
if (saveBtn) {
saveBtn.addEventListener('click', function() {
var analyticsChecked = document.getElementById('gdpr-analytics-toggle').checked;
var marketingChecked = document.getElementById('gdpr-marketing-toggle').checked;
gdprSetCookie('gdpr_consent_analytics', analyticsChecked ? 'accepted' : 'rejected', 365);
gdprSetCookie('gdpr_consent_marketing', marketingChecked ? 'accepted' : 'rejected', 365);
banner.style.display = 'none';
// Tercih edilen scriptleri yükle
if (analyticsChecked) gdprLoadAnalyticsScripts();
if (marketingChecked) gdprLoadMarketingScripts();
});
}
});
// Analitik scriptleri dinamik yükleme
function gdprLoadAnalyticsScripts() {
// Google Analytics 4
var gaScript = document.createElement('script');
gaScript.async = true;
gaScript.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX';
document.head.appendChild(gaScript);
gaScript.onload = function() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
};
}
// Pazarlama scriptleri dinamik yükleme
function gdprLoadMarketingScripts() {
// Facebook Pixel
!function(f,b,e,v,n,t,s){
if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)
}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
}
</script>
<?php
}
add_action('wp_footer', 'gdpr_consent_javascript', 100);
PHP Tarafında Onay Bazlı Script Yükleme
Bazı scriptler, sayfa yüklenmeden önce içinde olması gerekiyor. Bu durumda PHP cookie kontrolünü kullanıyoruz.
// PHP ile onay kontrolü yaparak script yükleme
function gdpr_conditional_scripts() {
// Analitik scriptleri - sadece onay verilmişse yükle
if (gdpr_can_load_script('analytics')) {
// Google Tag Manager
$gtm_id = 'GTM-XXXXXXX'; // Kendi GTM ID'nizi buraya yazın
?>
<!-- Google Tag Manager - GDPR Onaylı -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<?php echo esc_js($gtm_id); ?>');</script>
<!-- End Google Tag Manager -->
<?php
}
// Pazarlama scriptleri - sadece onay verilmişse yükle
if (gdpr_can_load_script('marketing')) {
?>
<!-- Hotjar - GDPR Onaylı -->
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:YOUR_HOTJAR_ID,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script>
<?php
}
}
add_action('wp_head', 'gdpr_conditional_scripts', 5);
WooCommerce İçin Özel Senaryo
WooCommerce siteniz varsa, konversion tracking özellikle önemli. Ödeme tamamlama sayfasında script yüklemek çok yaygın bir ihtiyaç.
// WooCommerce sipariş onay sayfasında koşullu tracking
function gdpr_woocommerce_conversion_tracking() {
// Sadece order-received sayfasında çalıştır
if (!is_order_received_page()) {
return;
}
// Analitik onayı yoksa çıkart
if (!gdpr_can_load_script('analytics')) {
return;
}
// Sipariş bilgilerini al
$order_id = get_query_var('order');
if (!$order_id) {
return;
}
$order = wc_get_order($order_id);
if (!$order) {
return;
}
$order_total = $order->get_total();
$order_currency = $order->get_currency();
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = array(
'id' => $product ? $product->get_id() : '',
'name' => $item->get_name(),
'price' => $item->get_subtotal() / $item->get_quantity(),
'quantity' => $item->get_quantity()
);
}
?>
<script>
// GA4 Purchase Event - GDPR Onaylı
if (typeof gtag !== 'undefined') {
gtag('event', 'purchase', {
'transaction_id': '<?php echo esc_js($order->get_order_number()); ?>',
'value': <?php echo floatval($order_total); ?>,
'currency': '<?php echo esc_js($order_currency); ?>',
'items': <?php echo json_encode($items); ?>
});
}
// Facebook Pixel Purchase Event - GDPR Onaylı
if (typeof fbq !== 'undefined') {
fbq('track', 'Purchase', {
value: <?php echo floatval($order_total); ?>,
currency: '<?php echo esc_js($order_currency); ?>'
});
}
</script>
<?php
}
add_action('wp_footer', 'gdpr_woocommerce_conversion_tracking', 20);
Tercih Sıfırlama: Kullanıcıya Kontrol Ver
GDPR gereği, kullanıcıların verdikleri onayı istedikleri zaman geri çekebilmeleri gerekiyor. Footer’a veya çerez politikası sayfasına ekleyebileceğiniz bir sıfırlama fonksiyonu:
// Kullanıcının tercihlerini sıfırlamasına izin veren shortcode
function gdpr_reset_preferences_shortcode($atts) {
$atts = shortcode_atts(array(
'text' => 'Çerez tercihlerimi sıfırla',
'class' => 'gdpr-reset-btn'
), $atts);
$output = '<button class="' . esc_attr($atts['class']) . '" onclick="gdprResetPreferences()">';
$output .= esc_html($atts['text']);
$output .= '</button>';
$output .= '<script>
function gdprResetPreferences() {
gdprDeleteCookie("gdpr_consent_analytics");
gdprDeleteCookie("gdpr_consent_marketing");
// Sayfayı yenile, banner tekrar çıkacak
if (confirm("Çerez tercihleriniz sıfırlandı. Sayfa yenilenecek.")) {
location.reload();
}
}
</script>';
return $output;
}
add_shortcode('gdpr_reset', 'gdpr_reset_preferences_shortcode');
// Kullanım: Sayfa içinde [gdpr_reset] veya [gdpr_reset text="Çerezleri Yönet"] yazmanız yeterli
Bu shortcode’u çerez politikası sayfanıza veya site footer’ınıza ekleyebilirsiniz. [gdpr_reset] ile sade, [gdpr_reset text="Çerezleri Yönet" class="ozel-class"] ile özelleştirilmiş kullanım mümkün.
WordPress Admin Panelinde Test
Geliştirme yaparken kendiniz admin olduğunuzda scriptlerin yüklenmesini istemeyebilirsiniz. Bunu da filtreleyebiliriz:
// Admin kullanıcılar için GDPR script yüklemeyi devre dışı bırak
function gdpr_disable_for_admin($can_load) {
if (current_user_can('manage_options') && is_admin_bar_showing()) {
// Admin bar görünüyorsa (yani admin giriş yapmışsa) scriptleri yükleme
return false;
}
return $can_load;
}
// gdpr_can_load_script fonksiyonunu güncellenmiş hali
function gdpr_can_load_script($category = 'analytics') {
// Admin kontrolü
if (current_user_can('manage_options') && is_admin_bar_showing()) {
return false; // Admin için scriptleri yükleme
}
$consent = gdpr_get_user_consent($category);
if ($consent === null || $consent === false) {
return false;
}
return true;
}
Gerçek Dünya Senaryosu: E-ticaret Sitesi
Diyelim ki hem Google Analytics hem de Facebook Pixel kullanan, Almanya ve diğer AB ülkelerine de satış yapan bir WooCommerce siteniz var. Bu durumda dikkat etmeniz gerekenler:
- Coğrafi hedefleme: AB ülkelerinden gelen ziyaretçiler için banner mutlaka gösterilmeli. CloudFlare veya bir IP geolocation API kullanarak bunu filtreleyebilirsiniz. Türkiye içindeki kullanıcılar için KVKK kuralları geçerli, ancak benzer prensipleri uygulamak iyi pratik.
- Cookie süreleri: GDPR kapsamında bazı ülke düzenleyicileri 6 ay ile 12 ay arasında süre öneriyor. Biz örnekte 365 gün kullandık, bunu sitenizin hukuki danışmanıyla değerlendirin.
- Kategori ayrımı: Analytics ve marketing’i ayrı tutmak önemli. Kullanıcı analytics’i kabul edip marketing’i reddedebilmeli.
- Kayıt tutma: İleride denetim olursa, kimin ne zaman ne onayladığını kanıtlamanız gerekebilir. Prodüksiyon ortamında consent log’larını bir veritabanı tablosuna kaydetmeyi düşünün.
- Çocuk kullanıcılar: Siteniz 16 yaşın altındakilere hitap ediyorsa, ebeveyn onayı gerekliliği devreye giriyor. Bu senaryo için çok daha kapsamlı bir çözüm gerekli.
Dikkat Edilmesi Gereken Noktalar
Cookie olmadan çalışan alternatifler: Server-side tracking, cookieless analytics (Plausible, Fathom gibi) araçları GDPR süreçlerini çok kolaylaştırıyor. Projeniz buysa bu alternatifleri de değerlendirin.
wp_head önceliği: gdpr_conditional_scripts fonksiyonunu priority 5 ile eklediğinize dikkat edin. Eğer başka scriptler wp_head üzerinden priority 10 ile yükleniyorsa, onlardan önce cookie kontrolünü yapmış olursunuz.
Cache sorunları: WP Rocket, W3 Total Cache gibi caching eklentileri PHP cookie kontrolünü atlayabilir. Bu durumda sadece JavaScript tarafındaki dinamik yükleme yöntemini kullanmanız daha güvenilir.
Consent Mode v2: Google, Ekim 2024 itibarıyla Consent Mode v2’yi zorunlu kıldı. Analytics’i Google ürünleriyle kullananlar için gtag('consent', 'default', {...}) çağrısını da eklemeniz gerekiyor. Bu, scriptleri yüklemeden önce wp_head‘e priority 1 ile eklenmeli.
Eklenti alternatifi: Complianz, CookieYes veya GDPR Cookie Consent eklentileri bu işi çok daha kapsamlı hallediyor. Yazdığımız kod temel kullanım için yeterli, ancak ciddi bir e-ticaret veya büyük ölçekli site için test edilmiş bir eklentiye yatırım yapmak mantıklı.
Sonuç
functions.php üzerinden GDPR uyumlu script yönetimi yazmak göründüğü kadar karmaşık değil. Temel akış şu üç adıma dayanıyor: kullanıcı tercihini cookie’ye kaydet, PHP veya JavaScript ile bu cookie’yi kontrol et, sonucuna göre scriptleri yükle ya da yükleme. Yazdığımız kodla kullanıcı banner’dan tercihini seçiyor, tercih cookie’ye yazılıyor, sonraki sayfa yüklemelerinde PHP bu cookie’yi okuyor ve scriptleri buna göre enqueue ediyor.
Bu yapıyı kendi sitenize adapte ederken mutlaka test edin: önce tüm cookie’leri temizleyip siteye girin, banner çıkıyor mu? Kabul ettikten sonra scriptler yükleniyor mu? Reddet dedikten sonra network sekmesinde tracking scriptleri görünüyor mu? Bu testleri her deploy sonrasında yapmak iyi bir alışkanlık.
Son olarak, bu yazıdaki kod örnekleri bir başlangıç noktası. Prodüksiyon ortamı için mutlaka bir hukukçuyla sitenizin spesifik durumunu değerlendirin. GDPR teknik bir mesele olduğu kadar hukuki bir meseledir de.
