WooCommerce Sepete Ekle Butonunun Üzerine İçerik Ekleme

E-ticaret sitelerinde dönüşüm oranlarını artırmanın en etkili yollarından biri, kullanıcıya satın alma kararı vermeden önce doğru bilgiyi doğru yerde sunmaktır. WooCommerce’de “Sepete Ekle” butonunun hemen üstü, bu açıdan altın değerinde bir alan. Müşteri zaten o noktaya kadar gelmiş, ürünü incelemiş ve butona basmaya hazırlanıyor. İşte tam bu anda bir güven mesajı, kargo bilgisi ya da promosyon notu görmek satın alma kararını pekiştirebilir. Bu yazıda woocommerce_before_add_to_cart_button hook’unu kullanarak bu alana nasıl içerik ekleyeceğini, bunu nasıl özelleştireceğini ve gerçek dünya senaryolarında nasıl uygulayacağını detaylı şekilde ele alacağız.

Hook Nedir ve Neden Bu Hook Kullanılır

WooCommerce, kendi şablon yapısı içinde yüzlerce action ve filter hook sunuyor. Bu hook’lar sayesinde çekirdek dosyalara dokunmadan, tema güncellemelerinden etkilenmeden işlevsellik ekleyebiliyorsun.

woocommerce_before_add_to_cart_button hook’u tam adından da anlaşılacağı üzere, sepete ekle butonunun hemen öncesinde tetikleniyor. Bu hook bir action hook olduğu için add_action() fonksiyonuyla kullanıyorsun.

Alternatif olarak şu hook’lar da işine yarayabilir:

  • woocommerce_after_add_to_cart_button: Butonun hemen altına içerik ekler
  • woocommerce_before_add_to_cart_form: Formun en başına, miktar alanının da üstüne ekler
  • woocommerce_after_add_to_cart_form: Tüm formun bitiminden sonra ekler
  • woocommerce_single_product_summary: Genel ürün özeti alanına ekler

Biz bu yazıda woocommerce_before_add_to_cart_button üzerine odaklanacağız çünkü bu alan psikolojik olarak en etkili noktadır.

Temel Kullanım: functions.php’ye Kod Ekleme

Her şey functions.php dosyasına kod eklemekle başlıyor. Eğer çocuk tema (child theme) kullanmıyorsan şu an durmalısın çünkü ana tema güncellendiğinde functions.php değişikliklerini kaybedersin. Çocuk tema oluşturma konusunu ayrı bir yazıda ele aldım, şimdilik çocuk temanın functions.php dosyasına aşağıdaki örnekleri eklediğini varsayıyorum.

En Basit Kullanım

add_action( 'woocommerce_before_add_to_cart_button', 'ozel_sepet_oncesi_mesaj' );

function ozel_sepet_oncesi_mesaj() {
    echo '<p class="sepet-oncesi-mesaj">Bugün sipariş ver, yarın kargoda!</p>';
}

Bu kadar. Ama bu yaklaşım tüm ürünlerde aynı mesajı gösterir ve stil de yok. Gerçek dünyada buna biraz daha et giydirmen gerekiyor.

Gerçek Dünya Senaryosu 1: Kargo Bilgisi Gösterme

Bir e-ticaret sitesi yönetiyorsun ve belirli bir tutarın üzerindeki siparişlerde ücretsiz kargo sunuyorsun. Bunu butona yakın bir yerde göstermek dönüşüm oranını ciddi şekilde artırır.

add_action( 'woocommerce_before_add_to_cart_button', 'kargo_bilgisi_goster', 10 );

function kargo_bilgisi_goster() {
    $ucretsiz_kargo_siniri = 500; // TL cinsinden
    global $product;
    
    if ( ! $product ) {
        return;
    }
    
    $urun_fiyati = $product->get_price();
    
    if ( $urun_fiyati >= $ucretsiz_kargo_siniri ) {
        echo '<div class="kargo-bilgi kargo-ucretsiz">';
        echo '<span class="kargo-icon">🚚</span>';
        echo '<strong>Bu ürün ücretsiz kargo ile gelir!</strong>';
        echo '</div>';
    } else {
        $eksik_tutar = $ucretsiz_kargo_siniri - $urun_fiyati;
        echo '<div class="kargo-bilgi kargo-ucretli">';
        echo '<span class="kargo-icon">📦</span>';
        echo sprintf(
            '<p>Ücretsiz kargo için %s TL daha harcayın.</p>',
            number_format( $eksik_tutar, 2, ',', '.' )
        );
        echo '</div>';
    }
}

Bu örnekte global $product ile mevcut ürün nesnesine erişiyoruz ve fiyata göre koşullu içerik üretiyoruz. number_format() fonksiyonu Türkçe para biçimlendirmesi için kullanılıyor.

Gerçek Dünya Senaryosu 2: Kategori Bazlı Mesaj Gösterme

Her ürün kategorisinde farklı mesajlar göstermek isteyebilirsin. Mesela elektronik ürünler için garanti bilgisi, gıda ürünleri için son kullanma tarihi uyarısı gibi.

add_action( 'woocommerce_before_add_to_cart_button', 'kategori_bazli_mesaj', 10 );

function kategori_bazli_mesaj() {
    global $product;
    
    if ( ! $product ) {
        return;
    }
    
    $kategoriler = wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'slugs' ) );
    
    if ( is_wp_error( $kategoriler ) || empty( $kategoriler ) ) {
        return;
    }
    
    $mesajlar = array(
        'elektronik'   => '✅ 2 yıl resmi garanti dahildir.',
        'gida'         => '⚠️ Soğuk zincir korunarak gönderilir.',
        'kozmetik'     => '🌿 Doğal içeriklidir, test edilmiştir.',
        'kitap'        => '📚 Orijinal baskı, faturalı gönderim.',
    );
    
    foreach ( $kategoriler as $slug ) {
        if ( isset( $mesajlar[ $slug ] ) ) {
            echo '<div class="kategori-mesaj">';
            echo esc_html( $mesajlar[ $slug ] );
            echo '</div>';
            break; // İlk eşleşen kategori için çık
        }
    }
}

Bu yaklaşımda wp_get_post_terms() fonksiyonu ile ürünün kategorilerini çekiyoruz, sonra bir dizi içinde tanımladığımız mesajlarla eşleştiriyoruz. esc_html() kullanmayı unutmuyoruz çünkü güvenlik her zaman önce gelir.

Gerçek Dünya Senaryosu 3: Stok Durumuna Göre Uyarı Mesajı

Az kalan stokta aciliyet hissi yaratmak satışları artırabilir. Ama bu konuda dürüst olmak gerekiyor, yapay stok baskısı oluşturmak uzun vadede güveni zedeliyor.

add_action( 'woocommerce_before_add_to_cart_button', 'stok_uyarisi_goster', 10 );

function stok_uyarisi_goster() {
    global $product;
    
    if ( ! $product || ! $product->managing_stock() ) {
        return;
    }
    
    $stok_miktari = $product->get_stock_quantity();
    
    if ( null === $stok_miktari ) {
        return;
    }
    
    if ( $stok_miktari > 0 && $stok_miktari <= 5 ) {
        echo '<div class="stok-uyari dusuk-stok">';
        echo '<span class="stok-icon">⚡</span>';
        echo sprintf(
            '<strong>Son %d ürün kaldı!</strong> Hemen sipariş ver.',
            (int) $stok_miktari
        );
        echo '</div>';
    } elseif ( $stok_miktari > 5 && $stok_miktari <= 20 ) {
        echo '<div class="stok-uyari orta-stok">';
        echo '<span class="stok-icon">🔔</span>';
        echo '<p>Sınırlı stok, kaçırma!</p>';
        echo '</div>';
    }
    // 20 üzerindeyse hiçbir şey gösterme
}

Burada managing_stock() kontrolü önemli. Eğer ürün stok yönetimi açık değilse bu kodu çalıştırmanın anlamı yok.

Gerçek Dünya Senaryosu 4: Belirli Kullanıcı Rollerine Özel Mesaj

B2B bir mağaza işletiyorsan toptan müşterilere, perakende müşterilere veya üyesi olmayanlara farklı mesajlar göstermek isteyebilirsin.

add_action( 'woocommerce_before_add_to_cart_button', 'rol_bazli_mesaj', 10 );

function rol_bazli_mesaj() {
    if ( ! is_user_logged_in() ) {
        echo '<div class="uye-mesaj">';
        echo '<p>🔐 <a href="' . esc_url( wp_login_url( get_permalink() ) ) . '">Giriş yap</a> ';
        echo 've üye fiyatlarından yararlan!</p>';
        echo '</div>';
        return;
    }
    
    $kullanici    = wp_get_current_user();
    $roller       = (array) $kullanici->roles;
    
    if ( in_array( 'wholesale_customer', $roller, true ) ) {
        echo '<div class="toptan-mesaj">';
        echo '<p>🏭 Toptan fiyat uygulanmaktadır. Minimum sipariş: 10 adet.</p>';
        echo '</div>';
    } elseif ( in_array( 'subscriber', $roller, true ) ) {
        echo '<div class="abone-mesaj">';
        echo '<p>⭐ Abone indiriminiz sepette otomatik uygulanacak.</p>';
        echo '</div>';
    }
}

Bu senaryoda wp_login_url() fonksiyonu ile kullanıcıyı giriş sonrası aynı ürün sayfasına yönlendiren bir link oluşturuyoruz. get_permalink() ile mevcut sayfanın URL’ini alıyoruz.

CSS ile Stil Ekleme

Kod bloklarını ekledin fakat görünüm henüz çirkin. Stilleri functions.php üzerinden wp_enqueue_scripts hook’u ile eklemelisin. Ama küçük projeler için inline stil de kabul edilebilir bir yöntem.

add_action( 'wp_enqueue_scripts', 'sepet_oncesi_stiller' );

function sepet_oncesi_stiller() {
    if ( ! is_product() ) {
        return; // Sadece ürün sayfalarında yükle
    }
    
    $css = '
        .sepet-oncesi-mesaj,
        .kargo-bilgi,
        .kategori-mesaj,
        .stok-uyari,
        .uye-mesaj,
        .toptan-mesaj {
            padding: 10px 15px;
            margin-bottom: 15px;
            border-radius: 6px;
            font-size: 14px;
            line-height: 1.5;
        }
        .kargo-ucretsiz {
            background-color: #d4edda;
            border: 1px solid #c3e6cb;
            color: #155724;
        }
        .kargo-ucretli {
            background-color: #fff3cd;
            border: 1px solid #ffeeba;
            color: #856404;
        }
        .dusuk-stok {
            background-color: #f8d7da;
            border: 1px solid #f5c6cb;
            color: #721c24;
        }
        .orta-stok {
            background-color: #fff3cd;
            border: 1px solid #ffeeba;
            color: #856404;
        }
        .uye-mesaj,
        .abone-mesaj {
            background-color: #e8f4fd;
            border: 1px solid #bee5eb;
            color: #0c5460;
        }
    ';
    
    wp_add_inline_style( 'woocommerce-general', $css );
}

is_product() kontrolüyle bu stillerin yalnızca ürün sayfalarında yüklenmesini sağlıyoruz. Gereksiz yükleme performansı etkiler.

Gerçek Dünya Senaryosu 5: Özel Ürün Meta Verisi ile Dinamik Mesaj

Ürün bazında özelleştirme yapmak istiyorsan WooCommerce’in özel alan (custom field) yapısını kullanabilirsin. Ürün düzenleme sayfasına özel bir alan ekleyip, o alana göre mesaj gösterirsin.

// Ürün meta kutusunu ekle
add_action( 'woocommerce_product_options_general_product_data', 'ozel_mesaj_alani_ekle' );

function ozel_mesaj_alani_ekle() {
    woocommerce_wp_textarea_input( array(
        'id'          => '_sepet_oncesi_ozel_mesaj',
        'label'       => 'Sepet Öncesi Özel Mesaj',
        'placeholder' => 'Bu ürün için özel bir mesaj girin...',
        'desc_tip'    => true,
        'description' => 'Sepete ekle butonunun üstünde gösterilir.',
        'rows'        => 3,
    ) );
}

// Meta veriyi kaydet
add_action( 'woocommerce_process_product_meta', 'ozel_mesaj_alani_kaydet' );

function ozel_mesaj_alani_kaydet( $post_id ) {
    $ozel_mesaj = isset( $_POST['_sepet_oncesi_ozel_mesaj'] )
        ? sanitize_textarea_field( $_POST['_sepet_oncesi_ozel_mesaj'] )
        : '';
    
    update_post_meta( $post_id, '_sepet_oncesi_ozel_mesaj', $ozel_mesaj );
}

// Frontend'de göster
add_action( 'woocommerce_before_add_to_cart_button', 'ozel_mesaj_goster', 10 );

function ozel_mesaj_goster() {
    global $product;
    
    if ( ! $product ) {
        return;
    }
    
    $ozel_mesaj = get_post_meta( $product->get_id(), '_sepet_oncesi_ozel_mesaj', true );
    
    if ( ! empty( $ozel_mesaj ) ) {
        echo '<div class="urun-ozel-mesaj">';
        echo wp_kses_post( $ozel_mesaj );
        echo '</div>';
    }
}

Bu senaryo çok güçlü çünkü her ürün için farklı mesajlar girebiliyorsun. Editör arayüzünden kolayca yönetilebilir. wp_kses_post() kullandık çünkü içeriğin basit HTML barındırmasına izin vermek istiyoruz ama script gibi tehlikeli etiketlere değil.

Gerçek Dünya Senaryosu 6: Geri Sayım Sayacı ile Kampanya Mesajı

Kampanya bitiş tarihine geri sayım eklemek istiyorsan JavaScript devreye giriyor. Ama temel yapıyı yine functions.php üzerinden kuruyorsun.

add_action( 'woocommerce_before_add_to_cart_button', 'kampanya_geri_sayim', 10 );

function kampanya_geri_sayim() {
    // Kampanya bitiş tarihini belirle (WordPress zaman dilimine göre)
    $kampanya_bitis = '2024-12-31 23:59:59';
    $bitis_timestamp = strtotime( $kampanya_bitis );
    $simdi          = current_time( 'timestamp' );
    
    if ( $simdi >= $bitis_timestamp ) {
        return; // Kampanya bitti, hiçbir şey gösterme
    }
    
    $kalan_sure = $bitis_timestamp - $simdi;
    
    // Kampanya geçerliyse sayacı göster
    echo '<div class="kampanya-sayac-wrap">';
    echo '<p class="kampanya-baslik">🔥 <strong>Flaş İndirim Bitiyor!</strong></p>';
    echo '<div id="kampanya-sayac" data-bitis="' . esc_attr( $bitis_timestamp ) . '"></div>';
    echo '</div>';
    
    // Inline JavaScript
    ?>
    <script type="text/javascript">
    (function() {
        var sayacEl = document.getElementById('kampanya-sayac');
        if (!sayacEl) return;
        
        var bitis = parseInt(sayacEl.getAttribute('data-bitis'), 10) * 1000;
        
        function sayaciGuncelle() {
            var simdi = new Date().getTime();
            var fark  = bitis - simdi;
            
            if (fark <= 0) {
                sayacEl.innerHTML = 'Kampanya sona erdi.';
                return;
            }
            
            var saat   = Math.floor((fark % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            var dakika = Math.floor((fark % (1000 * 60 * 60)) / (1000 * 60));
            var saniye = Math.floor((fark % (1000 * 60)) / 1000);
            
            sayacEl.innerHTML = 
                '<span class="s-blok">' + ('0' + saat).slice(-2) + '<small>saat</small></span> : ' +
                '<span class="s-blok">' + ('0' + dakika).slice(-2) + '<small>dk</small></span> : ' +
                '<span class="s-blok">' + ('0' + saniye).slice(-2) + '<small>sn</small></span>';
        }
        
        sayaciGuncelle();
        setInterval(sayaciGuncelle, 1000);
    })();
    </script>
    <?php
}

Bu kodda current_time('timestamp') WordPress’in ayarlarındaki zaman dilimini dikkate alır, PHP’nin time() fonksiyonundan daha güvenilirdir.

Priority (Öncelik) Parametresinin Önemi

add_action() fonksiyonunun üçüncü parametresi olan priority değeri, aynı hook’a bağlı birden fazla fonksiyon varsa hangisinin önce çalışacağını belirler. Varsayılan değer 10’dur.

// Önce çalışacak - priority 5
add_action( 'woocommerce_before_add_to_cart_button', 'kargo_bilgisi_goster', 5 );

// Sonra çalışacak - priority 10 (varsayılan)
add_action( 'woocommerce_before_add_to_cart_button', 'stok_uyarisi_goster', 10 );

// En son çalışacak - priority 20
add_action( 'woocommerce_before_add_to_cart_button', 'kampanya_geri_sayim', 20 );

Küçük sayı önce çalışır, büyük sayı sonra. Bunu kullanarak içeriklerin sıralamasını kontrol edebilirsin.

Hata Ayıklama İpuçları

Bu hook’ları kullanırken karşılaşabileceğin sorunlar ve çözümleri:

  • İçerik görünmüyor: is_product() ile doğru sayfada olup olmadığını kontrol et. Hook ismini yanlış yazmış olabilirsin.
  • Global $product boş geliyor: WooCommerce tam yüklenmeden önce hook tetiklenmiş olabilir. woocommerce_init hook’undan sonra eklendiğinden emin ol.
  • Stil çalışmıyor: Tarayıcı önbelleğini temizle ve wp_add_inline_style() için doğru handle kullandığından emin ol.
  • Çocuk temada çalışmıyor: functions.php dosyasını doğru temaya (çocuk tema) eklendiğini doğrula.
  • PHP hatası: WP_DEBUG açıkken hataları gör. wp-config.php dosyasında define('WP_DEBUG', true); satırını aktifleştir.

Hata ayıklama için basit bir test fonksiyonu:

add_action( 'woocommerce_before_add_to_cart_button', 'hook_test', 10 );

function hook_test() {
    if ( defined('WP_DEBUG') && WP_DEBUG ) {
        echo '<pre style="background:#f0f0f0;padding:10px;">';
        echo 'Hook çalışıyor! Ürün ID: ';
        global $product;
        echo $product ? $product->get_id() : 'Ürün bulunamadı';
        echo '</pre>';
    }
}

Geliştirme tamamlandıktan sonra bu test fonksiyonunu kaldırmayı unutma.

Tema Uyumluluğu Hakkında Önemli Not

Bazı premium temalar WooCommerce şablonlarını kendi dosyalarıyla override eder. Bu durumda hook’ların beklendiği gibi çalışmayabileceği durumlar olabilir. Örneğin tema, single-product/add-to-cart/simple.php şablonunu kendi klasörüne kopyalamışsa ve bu hook’u içermiyorsa içeriğin görünmez.

Bu durumda temanın WooCommerce şablon dosyalarına bakman gerekiyor. Temanda yourtheme/woocommerce/single-product/add-to-cart/simple.php dosyası varsa, bu dosya içinde do_action('woocommerce_before_add_to_cart_button') satırının bulunup bulunmadığını kontrol et. Yoksa eklemenin tek yolu bu şablonu çocuk temana kopyalayıp içine hook çağrısını eklemektir.

Performans Değerlendirmesi

Bu hook her ürün sayfası yüklenişinde çalışır. Eğer içerik fonksiyonları içinde veritabanı sorgusu yapıyorsan (örneğin get_post_meta(), wp_get_post_terms()) bu sorguların maliyetini göz önünde bulundurman gerekiyor.

Yoğun trafikli sitelerde caching kullanmak önemlidir. Örneğin stok durumu sorgusunu transient ile önbelleğe alabilirsin:

function stok_miktarini_al_cached( $urun_id ) {
    $cache_key = 'stok_miktari_' . $urun_id;
    $stok      = get_transient( $cache_key );
    
    if ( false === $stok ) {
        $urun = wc_get_product( $urun_id );
        $stok = $urun ? $urun->get_stock_quantity() : null;
        set_transient( $cache_key, $stok, 5 * MINUTE_IN_SECONDS );
    }
    
    return $stok;
}

5 dakikalık önbellek süresi stok bilgisi için makul bir denge. Çok kısa tutarsan önbelleğin faydası olmaz, çok uzun tutarsan stok bilgisi güncel kalmaz.

Sonuç

woocommerce_before_add_to_cart_button hook’u, WooCommerce’de kullanıcı deneyimini ve dönüşüm oranlarını artırmak için en stratejik noktalardan biri. Bu yazıda ele aldığımız senaryolar, kargo bilgisi gösterme, kategori bazlı mesaj, stok uyarısı, kullanıcı rolüne özel içerik, ürün meta verisi ile dinamik mesaj ve kampanya sayacı gibi gerçek ihtiyaçların tamamını karşılıyor.

Bu örneklerdeki ortak prensipleri şöyle özetleyebiliriz:

  • Her zaman global $product kontrolü yap, null kontrolünü atlatma
  • Çıktılarda esc_html() veya wp_kses_post() kullanarak güvenliği sağla
  • Stilleri wp_enqueue_scripts hook’u ile ve is_product() koşuluyla ekle
  • Veritabanı sorgularını mümkünse önbellekle
  • Priority parametresiyle içerik sırasını kontrol et
  • Her zaman çocuk tema üzerinde çalış

Bu teknikleri birbirleriyle kombinleyebilirsin. Bir fonksiyon içinde hem kategori kontrolü, hem stok kontrolü, hem de kullanıcı rolü kontrolü yaparak tek bir hook’tan maksimum verim alabilirsin. Kod büyüdükçe bu fonksiyonları ayrı bir dosyaya (inc/woocommerce-custom.php gibi) taşımayı ve functions.php‘den require_once ile dahil etmeyi düşünebilirsin. Bu hem okunabilirliği artırır hem de yönetimi kolaylaştırır.

Bir yanıt yazın

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