WooCommerce Ürün Listesinde Her Ürünün Üzerine İçerik Ekleme
WooCommerce mağazanızda ürün listesi sayfaları, müşterilerinizin ilk izlenimini oluşturan en kritik noktalardandır. Bazen varsayılan WooCommerce çıktısı yetmez; her ürün kartının üzerine bir kampanya etiketi, stok uyarısı, özel bir badge ya da promosyon mesajı eklemek istersiniz. İşte tam bu noktada functions.php devreye giriyor ve bize inanılmaz esneklik sunuyor.
WooCommerce Hook Sistemi Neden Bu Kadar Güçlü?
WooCommerce, WordPress’in hook sistemini son derece kapsamlı biçimde kullanır. Ürün listelerinde, ürün detay sayfalarında, sepette ve ödeme adımlarında onlarca action ve filter hook bulunur. Bu sayede core dosyalara hiç dokunmadan, sadece functions.php üzerinden istediğimiz yere istediğimiz içeriği enjekte edebiliriz.
Ürün listeleme sayfalarında en çok kullanılan hook’lar şunlardır:
- woocommerce_before_shop_loop_item: Ürün kartı sarmalayıcısının hemen içinde, içerik başlamadan önce
- woocommerce_before_shop_loop_item_title: Ürün görseli ile başlık arasında
- woocommerce_shop_loop_item_title: Başlığın kendisi
- woocommerce_after_shop_loop_item_title: Başlıktan hemen sonra, fiyat öncesi
- woocommerce_after_shop_loop_item: Sepete ekle butonundan sonra
- woocommerce_before_shop_loop: Ürün listesi tamamen başlamadan önce
Her hook’un bir de priority değeri vardır. WooCommerce’in kendi fonksiyonları genellikle 10 veya 20 priority ile çalışır. Biz 5 veya 15 gibi değerler kullanarak içeriğimizi doğru konuma yerleştirebiliriz.
Temel Yapı: Her Ürünün Üstüne Sabit Metin Eklemek
En basit senaryodan başlayalım. Diyelim ki mağazanızdaki her ürün kartının üstüne “Ücretsiz Kargo” yazısı eklemek istiyorsunuz.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_urun_listesi_ust_icerik', 5 );
function custom_urun_listesi_ust_icerik() {
echo '<div class="custom-urun-badge">';
echo '<span class="ucretsiz-kargo-badge">🚚 Ücretsiz Kargo</span>';
echo '</div>';
}
Bu kod parçası, her ürünün görselinin hemen altında, başlığın üstünde çalışır. Priority değerini 5 verdik çünkü WooCommerce’in kendi görseli bu hook’ta 10 priority ile çalışır. Yani biz görselden önce değil, görselden hemen sonra ve başlıktan önce yerleşmek istiyoruz. Eğer görselin üstüne koymak isteseydiniz woocommerce_before_shop_loop_item_title yerine woocommerce_before_shop_loop_item kullanıp görselin template’ini override etmeniz gerekirdi.
Gerçek Dünya Senaryosu 1: Stok Durumuna Göre Dinamik Badge
Büyük bir outdoor ekipman mağazası yönettiğinizi düşünün. Stoğu kritik seviyeye düşmüş ürünler için aciliyet hissi yaratmak istiyorsunuz. Bunun için her ürünün stok miktarını kontrol edip dinamik bir uyarı mesajı gösterebilirsiniz.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_stok_uyarisi_badge', 15 );
function custom_stok_uyarisi_badge() {
global $product;
if ( ! $product ) {
return;
}
$stok_miktari = $product->get_stock_quantity();
$stok_durumu = $product->get_stock_status();
if ( $product->managing_stock() && $stok_miktari !== null ) {
if ( $stok_miktari <= 0 ) {
echo '<div class="stok-badge stok-bitti">❌ Stok Tükendi</div>';
} elseif ( $stok_miktari <= 5 ) {
echo '<div class="stok-badge kritik-stok">⚠️ Son ' . intval( $stok_miktari ) . ' Ürün!</div>';
} elseif ( $stok_miktari <= 20 ) {
echo '<div class="stok-badge az-stok">📦 Sınırlı Stok</div>';
}
}
if ( $stok_durumu === 'instock' && $stok_miktari > 50 ) {
echo '<div class="stok-badge yeterli-stok">✅ Stokta Hazır</div>';
}
}
Bu kod global $product ile mevcut ürün nesnesine erişir. WooCommerce, döngü içinde bu global değişkeni her ürün için otomatik olarak günceller. get_stock_quantity() metodu sayısal stok değerini, get_stock_status() ise “instock”, “outofstock” veya “onbackorder” değerini döndürür.
Gerçek Dünya Senaryosu 2: Kategori Bazlı İçerik Enjeksiyonu
Farklı kategorilerdeki ürünler için farklı mesajlar göstermek istediğinizi varsayın. Elektronik kategorisindeki ürünlere “2 Yıl Garanti” yazısı, giyim kategorisindeki ürünlere “30 Gün İade” mesajı eklemek makul bir istek.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_kategori_bazli_badge', 12 );
function custom_kategori_bazli_badge() {
global $product;
if ( ! $product ) {
return;
}
$urun_id = $product->get_id();
$kategoriler = get_the_terms( $urun_id, 'product_cat' );
$kategori_slugs = array();
if ( $kategoriler && ! is_wp_error( $kategoriler ) ) {
foreach ( $kategoriler as $kategori ) {
$kategori_slugs[] = $kategori->slug;
}
}
$mesaj_haritasi = array(
'elektronik' => array( 'icon' => '🔧', 'metin' => '2 Yıl Garanti', 'class' => 'badge-garanti' ),
'giyim' => array( 'icon' => '↩️', 'metin' => '30 Gün İade', 'class' => 'badge-iade' ),
'kozmetik' => array( 'icon' => '🌿', 'metin' => 'Doğal İçerik', 'class' => 'badge-dogal' ),
'kitap' => array( 'icon' => '📚', 'metin' => 'Dijital Kopi Hediye', 'class' => 'badge-hediye' ),
);
foreach ( $mesaj_haritasi as $slug => $bilgi ) {
if ( in_array( $slug, $kategori_slugs ) ) {
printf(
'<div class="kategori-badge %s">%s %s</div>',
esc_attr( $bilgi['class'] ),
$bilgi['icon'],
esc_html( $bilgi['metin'] )
);
break;
}
}
}
Burada break kullanmamızın sebebi şu: Bir ürün birden fazla kategoride olabilir. Genellikle ilk eşleşen kategorinin mesajını göstermek yeterlidir. İsterseniz break kaldırarak tüm kategori etiketlerini gösterebilirsiniz.
Gerçek Dünya Senaryosu 3: Özel Ürün Meta Verisi ile Badge
WooCommerce’de her ürüne özel meta veriler ekleyebilirsiniz. Bu meta verileri ACF (Advanced Custom Fields) ile ya da doğrudan update_post_meta() ile yönetebilirsiniz. Diyelim ki ürünlerinizde “ozel_kampanya_metni” adlı bir meta alanı var.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_meta_bazli_icerik', 8 );
function custom_meta_bazli_icerik() {
global $product;
if ( ! $product ) {
return;
}
$urun_id = $product->get_id();
$kampanya_metni = get_post_meta( $urun_id, 'ozel_kampanya_metni', true );
$kampanya_rengi = get_post_meta( $urun_id, 'kampanya_renk_kodu', true );
if ( ! empty( $kampanya_metni ) ) {
$renk_stili = '';
if ( ! empty( $kampanya_rengi ) ) {
$temiz_renk = sanitize_hex_color( $kampanya_rengi );
if ( $temiz_renk ) {
$renk_stili = 'style="background-color: ' . esc_attr( $temiz_renk ) . ';"';
}
}
printf(
'<div class="ozel-kampanya-badge" %s>🎯 %s</div>',
$renk_stili,
esc_html( $kampanya_metni )
);
}
}
Bu yaklaşım çok güçlüdür çünkü her ürün yöneticisi, ürün düzenleme sayfasından kampanya metnini ve rengini özelleştirebilir. Büyük kataloglarda ürün bazlı yönetim kolaylığı sağlar.
Gerçek Dünya Senaryosu 4: Satış Yüzdesini Gösterme
WooCommerce’in varsayılan “İndirimde” yazısı çoğu zaman yeterince dikkat çekmez. Bunun yerine yüzde indirim miktarını hesaplayıp göstermek çok daha etkili olabilir.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_indirim_yuzdesi_badge', 6 );
function custom_indirim_yuzdesi_badge() {
global $product;
if ( ! $product || ! $product->is_on_sale() ) {
return;
}
$normal_fiyat = (float) $product->get_regular_price();
$satis_fiyati = (float) $product->get_sale_price();
if ( $normal_fiyat <= 0 || $satis_fiyati <= 0 ) {
return;
}
if ( $product->is_type( 'variable' ) ) {
$fiyat_aralik = $product->get_variation_prices();
$min_satis = min( $fiyat_aralik['sale_price'] );
$max_normal = max( $fiyat_aralik['regular_price'] );
if ( $max_normal > 0 && $min_satis > 0 ) {
$yuzde = round( ( ( $max_normal - $min_satis ) / $max_normal ) * 100 );
echo '<div class="indirim-badge">%' . intval( $yuzde ) . ' İndirim!</div>';
}
return;
}
$yuzde = round( ( ( $normal_fiyat - $satis_fiyati ) / $normal_fiyat ) * 100 );
if ( $yuzde > 0 ) {
echo '<div class="indirim-badge">%' . intval( $yuzde ) . ' İndirim!</div>';
}
}
Variable (varyasyonlu) ürünlerde fiyat hesaplama biraz farklıdır. get_variation_prices() methodu tüm varyasyon fiyatlarını bir dizi halinde döndürür. Bu sayede en düşük satış fiyatı ile en yüksek normal fiyat arasındaki farktan maksimum indirim yüzdesini hesaplayabiliriz.
Stil Eklemek: wp_head ile CSS Enjeksiyonu
Eklediğiniz badge’lerin görünür ve güzel olması için CSS de eklemeniz gerekir. Bunu da functions.php üzerinden yapabilirsiniz.
add_action( 'wp_head', 'custom_urun_badge_stilleri' );
function custom_urun_badge_stilleri() {
if ( ! is_shop() && ! is_product_category() && ! is_product_tag() ) {
return;
}
?>
<style type="text/css">
.custom-urun-badge,
.stok-badge,
.kategori-badge,
.indirim-badge,
.ozel-kampanya-badge {
display: inline-block;
padding: 4px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 700;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.stok-badge.kritik-stok { background: #ff4444; color: #fff; }
.stok-badge.az-stok { background: #ff8c00; color: #fff; }
.stok-badge.stok-bitti { background: #888; color: #fff; }
.stok-badge.yeterli-stok{ background: #28a745; color: #fff; }
.indirim-badge { background: #e74c3c; color: #fff; }
.badge-garanti { background: #3498db; color: #fff; }
.badge-iade { background: #9b59b6; color: #fff; }
.badge-dogal { background: #27ae60; color: #fff; }
.badge-hediye { background: #f39c12; color: #fff; }
.ozel-kampanya-badge { background: #2c3e50; color: #fff; }
</style>
<?php
}
Burada is_shop(), is_product_category() ve is_product_tag() kontrolü yaparak bu stilleri sadece gerekli sayfalarda yüklüyoruz. Bu küçük ama önemli bir performans optimizasyonu.
Gelişmiş Senaryo: Satın Alma Sayısına Göre “Popüler Ürün” Etiketi
WooCommerce her ürün için toplam satış sayısını total_sales meta olarak saklar. Bu veriye dayanarak en çok satan ürünlere özel bir “Popüler” etiketi ekleyebilirsiniz.
add_action( 'woocommerce_before_shop_loop_item_title', 'custom_populer_urun_badge', 9 );
function custom_populer_urun_badge() {
global $product;
if ( ! $product ) {
return;
}
$urun_id = $product->get_id();
$toplam_satis = (int) get_post_meta( $urun_id, 'total_sales', true );
$esik_deger = apply_filters( 'custom_populer_urun_esigi', 50 );
if ( $toplam_satis >= $esik_deger ) {
printf(
'<div class="populer-badge">🔥 %d+ Satıldı</div>',
intval( $toplam_satis )
);
}
}
Burada apply_filters() kullanmamız önemli. Bu sayede başka bir plugin ya da kodun, popülerlik eşik değerini override etmesi mümkün olur. Örneğin farklı kategoriler için farklı eşikler belirleyebilirsiniz. Bu yaklaşım kodunuzu daha modüler yapar.
Performans İpuçları ve Dikkat Edilmesi Gereken Noktalar
WooCommerce ürün listelerinde çok sayıda ürün olabilir. Her hook callback’i her ürün için çalıştığı için performans kritik bir konu haline gelir.
Veritabanı sorgularını minimize edin:
get_post_meta()doğrudan çağrılar genellikle WordPress’in object cache mekanizması sayesinde ikinci sorguda cache’den gelir$productnesnesinin metodlarını kullanın,get_post_meta()yerine$product->get_meta('alan_adi')daha temizdir- Aynı sayfa yüklemesinde aynı ürün için aynı metayı birden fazla kez sorgulamaktan kaçının
Güvenlik kontrollerini unutmayın:
- Kullanıcıdan gelen veya veritabanından çekilen her veriyi
esc_html(),esc_attr()ya dawp_kses_post()ile sanitize edin - Meta verilerini doğrudan echo etmeyin
Koşullu kontroller yapın:
- Fonksiyonun başında
global $product; if (!$product) return;kontrolü her zaman yapın - Hook çok farklı template’lerde tetiklenebilir, $product her zaman set olmayabilir
Hook priority değerlerini planlayın:
- Birden fazla fonksiyon aynı hook’ta çalışıyorsa priority çakışmalarını kontrol edin
- WooCommerce’in kendi fonksiyonlarının priority değerlerini bilmek önemlidir
// Mevcut hook'ların priority değerlerini debug etmek için:
add_action( 'woocommerce_before_shop_loop_item_title', 'debug_hook_priority', 1 );
function debug_hook_priority() {
if ( current_user_can( 'administrator' ) && isset( $_GET['debug_hooks'] ) ) {
global $wp_filter;
$hook_adi = 'woocommerce_before_shop_loop_item_title';
if ( isset( $wp_filter[ $hook_adi ] ) ) {
echo '<pre style="font-size:10px;">';
print_r( array_keys( $wp_filter[ $hook_adi ]->callbacks ) );
echo '</pre>';
}
}
}
Bu debug fonksiyonunu geliştirme ortamında URL’ye ?debug_hooks=1 ekleyerek çalıştırabilirsiniz. Üretim ortamında kesinlikle kaldırın ya da WP_DEBUG kontrolü ekleyin.
Child Theme mi Yoksa Plugin mi?
Bu kodları nereye koyacağınız konusunda da bilinçli olmanız gerekir. Üç seçeneğiniz var:
Child theme functions.php: Tema bağımlı değişiklikler için uygun. Tema değiştirildiğinde kaybolabilir. Küçük projeler için makul.
Site spesifik plugin: wp-content/plugins/site-ozel-fonksiyonlar/ altında küçük bir plugin oluşturmak en temiz yoldur. Tema değişikliklerinden etkilenmez. Uzun vadeli projelerde tercih edilmeli.
Mu-plugins (Must Use Plugins): wp-content/mu-plugins/ dizinine konan PHP dosyaları otomatik yüklenir. Deaktive edilemez. Kritik işlevler için ideal.
Sonuç
WooCommerce’in hook sistemi, mağazanızı özelleştirmek için son derece güçlü ve güvenli bir yol sunar. Ürün listelerinde her ürünün üzerine içerik eklemek, birkaç satır kodla stok uyarılarından indirim badge’lerine, kategori bazlı mesajlardan satış istatistiklerine kadar pek çok farklı senaryoyu kapsayabilir.
En önemli nokta şu: Her zaman $product nesnesinin metodlarını tercih edin, güvenlik sanitizasyonunu ihmal etmeyin, ve performans için gereksiz veritabanı sorgularından kaçının. CSS stillerinizi sadece gerekli sayfalarda yükleyin ve debug kodlarını üretim ortamında bırakmayın.
Bu örnekleri temel alarak kendi iş mantığınıza uygun badge sistemleri, promosyon etiketleri ve dinamik içerikler oluşturabilirsiniz. WooCommerce’in dokümantasyonunda action hook listesini incelediğinizde, ürün listesini tamamen şekillendirebileceğinizi göreceksiniz.
