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.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir