WooCommerce Sepete Ekle butonunu gizlemek: dört kapıyı da kapatın
Butonu kaldıran iki satırlık PHP döngüyü ve ürün sayfasını halleder, ama doğrudan sepete ekleme adresini ve Store API uç noktasını açık bırakır. Kontrolü gizlemekle satışı reddetmek arasındaki farkı ve dört kapının hepsini nasıl kapatacağınızı anlatıyoruz.
Sepete Ekle butonunun gitmesini istiyorsunuz. Belki mağaza bir katalog ve her satış bir temsilci üzerinden yürüyor. Belki tek bir ürün grubu yalnızca toptana açık ve halka satılmaması gerekiyor. hide add to cart button woocommerce diye arattığınızda site site dolaşan aynı iki satırlık PHP’yi bulursunuz. Yaptıkları iş kadarıyla çalışırlar da. Bir kontrolü kaldırırlar; oysa kontrol, problemin en önemsiz parçasıdır.
WooCommerce siparişleri en az dört kapıdan kabul eder: az önce düzenlediğiniz şablon, JavaScript’in varyasyonlu ürünlerde kurduğu varyasyon formu, /?add-to-cart=123 adresine yapılan düz bir GET isteği ve blok temalarla headless ön yüzlerin POST ettiği Store API uç noktası. Bir butonu kaldırmak bunlardan yalnızca birini kapatır. Bu yazı dördünü de tek tek geziyor, hangi çözümün hangi duruma ait olduğunu gösteriyor ve hiçbirinin çözmediği şeyler konusunda açık konuşuyor.
Herkesin verdiği iki kod parçası#
Klasik bir temada döngü butonunu ve tekil ürün butonunu, birer hook’a bağlı birer çekirdek fonksiyon basar. Bunları hook’tan çıkardığınızda işaretleme HTML’den gerçekten kalkar, yalnızca gizlenmiş olmaz.
// Classic templates: remove the button from the shop loop
// and from the single product summary.
add_action( 'init', function () {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
} );Temanız döngü butonunu farklı bir hook’a veya önceliğe taşıdıysa remove_action sessizce hiçbir şey yapmaz, çünkü argümanların birebir eşleşmesi gerekir. Döngü için daha kaba yöntem, bağlantının kendisini boşaltmaktır; çekirdek bağlantıyı nerede kuruyorsa orada işe yarar:
add_filter( 'woocommerce_loop_add_to_cart_link', '__return_empty_string', 20 );Yapmamanız gereken şey CSS’e sarılmaktır. Bir display: none kuralı butonu yalnızca stil dosyanızı yükleyen bir tarayıcıdan gizler, başka hiçbir şeyden değil. Bağlantı hâlâ HTML’in içindedir, sepete ekleme adresi hâlâ href içindedir ve geliştirici araçlarını, bir okuma modu uzantısını veya bir kazıyıcıyı kullanan hiç kimse bundan etkilenmez. Sayfa kurucularındaki “Gizle” anahtarı için de aynısı geçerli: genellikle işaretlemeyi sayfaya gönderir ve istemci tarafında gizler.
Çoğu hide add to cart button woocommerce rehberinin açık bıraktıkları#
Kabaca insanların fark etme sırasına göre dört boşluk.
Varyasyonlu ürünler ve varyasyon formu#
Klasik bir temada woocommerce_template_single_add_to_cart fonksiyonunu kaldırmak varyasyon formunu da beraberinde götürür, çünkü formu basan woocommerce_variable_add_to_cart aksiyonunu tetikleyen o fonksiyondur. Sıkıntı, bir temanın veya sayfa kurucunun ürün özetini woocommerce_single_product_summary yerine kendi şablon çağrısıyla render etmesiyle başlar. O zaman remove_action çağrınızın kaldıracak bir şeyi kalmaz ve form ayakta kalır.
Burada bir ikinci katman var. Varyasyon formunu, varyasyon başına bir kayıt tutan ve fiyatı, stok durumu metnini ve satın alınabilirlik bayrağını taşıyan bir JSON yığını sürer. AJAX eşiğine kadar WooCommerce bu yığını doğrudan sayfaya basar; eşiğin üstünde aynı veri bunun yerine AJAX üzerinden gelir. Eşik varsayılan olarak otuz varyasyondur ve woocommerce_ajax_variation_threshold ile filtrelenebilir. Her iki durumda da betik veriyi okur ve nitelikler seçildikçe kendi butonunu etkinleştirir veya devre dışı bırakır. Formu PHP tarafında gizleyip veriye dokunmamak, veriyi erişilebilir bırakır. Görünen fiyat halledilmiş gibi dursa bile varyasyonlu ürünlerde fiyat aralığının bu kadar sık sızmasının nedeni de yine bu JSON’dur.
Blok temalar ve ürün blokları#
Blok temalar butonu iki ayrı şeye böler. Tekil ürün şablonunda, klasik Seçeneklerle Sepete Ekle bloğu (woocommerce/add-to-cart-form) içeride woocommerce_template_single_add_to_cart() fonksiyonunu çağırır, dolayısıyla yukarıdaki remove_action hâlâ iş görür. Yine de WooCommerce bunun blok tabanlı bir muadilini yayına almakta olduğu için varsaymak yerine kendi sürümünüzde doğrulayın. Ürün Koleksiyonu içindeyse buton woocommerce/product-button bloğudur; kendi işaretlemesini ürün nesnesinden üretir ve woocommerce_after_shop_loop_item üzerinden hiç geçmez. Döngü için verilen kod orada hiçbir şey yapmaz. Ya bloğu Site Düzenleyici’de şablondan silersiniz ya da bir sonraki bölümün konusu olan ürün seviyesinde çalışırsınız.
Doğrudan sepete ekleme adresi#
WooCommerce sepete eklemeyi en başından beri bir sorgu dizesiyle destekler: sitenin herhangi bir sayfasında /?add-to-cart=123&quantity=5. Bu isteği wp_loaded üzerindeki form işleyicisi karşılar, hem de tek bir şablon bile çalışmadan çok önce. Ne kadar şablon düzenlerseniz düzenleyin bu yola dokunamazsınız. Ürün kimlikleri de gizli değildir: tekil ürün sayfasında body sınıflarında, herkese açık Store API ürün listesinde ve tam da kaldırmaya çalıştığınız varyasyon formunun JSON’unda görünürler.
# Does the URL still work? Watch the cart, not the status code.
curl -s -c jar.txt -b jar.txt "https://example.com/?add-to-cart=123" -o /dev/null
curl -s -b jar.txt "https://example.com/cart/" | grep -c "cart_item"Store API sepet uç noktası#
Blok temalar, Sepet ve Ödeme blokları ve her türlü headless ön yüz wc/store/v1 ile konuşur. Bir ürün eklemek, bir ürün kimliği ve bir adetle /wp-json/wc/store/v1/cart/add-item adresine yapılan bir POST isteğidir. Oturum açmak gerekmez. Sepet rotaları bir nonce başlığını kontrol eder, ama bu bir siteler arası istek koruması, erişim denetimi değil: her ziyaretçinin tarayıcısına geçerli bir tane verilir. Uç noktayı herkesin erişebileceği bir yer sayın. Şablondan bir butonu kaldırıp orada durduysanız burası ardına kadar açık duran bir yan kapıdır.
# A bare POST answers with a nonce error, which proves nothing.
# Take a real nonce from the response headers first, then replay it.
curl -s -D - -o /dev/null https://example.com/wp-json/wc/store/v1/cart
curl -s -X POST https://example.com/wp-json/wc/store/v1/cart/add-item
-H "Content-Type: application/json"
-H "Nonce: PASTE_THE_NONCE_HERE"
-d '{"id":123,"quantity":1}'Kontrolü gizlemek yerine eylemi reddetmek#
Dört kapının dördü de WooCommerce’in her ürün için sorduğu tek bir soruda birleşir: bu ürün satın alınabilir mi? WC_Cart::add_to_cart() bunu kontrol eder ve cevap hayırsa “Sorry, this product cannot be purchased.” hatasını fırlatır; Store API sepet denetleyicisi de bir ürünü kabul etmeden önce aynı doğrulamayı çalıştırır. Bu soruyu bir filtreyle cevaplayın, aynı iki satırla hem adresi hem uç noktayı kapatmış olursunuz.
add_filter( 'woocommerce_is_purchasable', '__return_false', 99 );
add_filter( 'woocommerce_variation_is_purchasable', '__return_false', 99 );İki faydalı yan etkisi var. Basit ürünler için klasik tekil ürün şablonu, ürün satın alınabilir değilse baştan erken dönüşle çıkar; böylece buton remove_action olmadan ürün sayfasından kaybolur. Ayrıca add_to_cart_url() sepete ekleme sorgu dizesini döndürmeyi bırakır, dolayısıyla ondan bağlantı üreten her şey artık ürün sayfasını gösterir.
Temiz halletmediği bir şey var: mağaza döngüsünde çekirdek, buton metnini “Devamını oku” ile değiştirip ürüne bağlar. Bu, stokta olmayan ürünler için makul bir varsayılan ama bir katalogda tuhaf durur; döngünün boş kalmasını istiyorsanız woocommerce_loop_add_to_cart_link filtresini de elinizde tutun. Bunu bir kategoriyle veya bir ürün kümesiyle sınırlamak, aynı filtreye bir koşul eklemekten ibarettir; bir varyasyonun kendi kimliğinin ebeveyninkinden farklı olduğunu unutmayın:
add_filter( 'woocommerce_is_purchasable', 'shop_block_wholesale', 99, 2 );
add_filter( 'woocommerce_variation_is_purchasable', 'shop_block_wholesale', 99, 2 );
function shop_block_wholesale( $purchasable, $product ) {
$id = $product->get_parent_id() ? $product->get_parent_id() : $product->get_id();
if ( has_term( 'wholesale', 'product_cat', $id ) ) {
return false;
}
return $purchasable;
}Etki alanı konusunda bilinçli olun. Bu ürünü sepete ekleyen her kod yolu artık başarısız olur; Hesabım’daki “Yeniden sipariş ver”, paket eklentileri ve geri dönen bir müşteri için sepeti yeniden kuran her şey buna dahil. Bu genelde tam da istediğiniz şeydir, ama o akışları bir destek talebinden öğrenmek yerine test edin. Aynı koşullu mantığın satın alınabilirlik yerine fiyatlara uygulanmış hâli belirli ürün veya kategorilerde fiyat gizleme yazısında ele alınıyor.
Yaklaşımların karşılaştırması#
Önce son iki sütunu okuyun. Kontrolü gizlemeyi satışı reddetmekten ayıran şey onlardır ve çoğu hide add to cart button woocommerce tavsiyesinin hiç ulaşamadığı kısım da orasıdır.
| Yaklaşım | Butonu kaldırır mı | ?add-to-cart= adresini durdurur mu | Store API add-item isteğini durdurur mu |
|---|---|---|---|
CSS display: none | Yalnızca görsel olarak | Hayır | Hayır |
Döngü ve özette remove_action | Klasik şablonlarda | Hayır | Hayır |
woocommerce_loop_add_to_cart_link boşaltılır | Yalnızca klasik döngüde | Hayır | Hayır |
| Site Düzenleyici’de Ürün Butonu bloğunu silmek | Yalnızca blok döngüde | Hayır | Hayır |
| Stok durumunu Stokta yok yapmak | Evet, her yerde | Evet, ön siparişe izin verilmiyorsa | Evet, ön siparişe izin verilmiyorsa |
woocommerce_is_purchasable false | Tekil üründe; döngü için ek filtre gerekir | Evet | Evet |
Gizlemek mi reddetmek mi: niyete göre seçin#
İki teknik arasında bir üstünlük sıralaması yok. Farklı anlamlara gelirler ve yanlış olanı kullanmak kendi kendisiyle çelişen bir mağaza üretir.
- Ürün geçici olarak yok. Hiçbir şeyi filtrelemeyin. Stok durumunu Stokta yok yapın, ön siparişi kapatın ve işi WooCommerce’e bırakın: butonu kaldırır, stok durumu bildirimini basar ve yapılandırılmış veride
OutOfStockbildirir; böylece arama motorları satın alınabilir bir sonuç kartı göstermeyi bırakır. Bunun yerine butonu bir satın alınabilirlik filtresiyle zorla kaldırırsanız JSON-LD hâlâInStockder, çünkü stok durumu satın alınabilirlikten değil stoktan okunur. Search Console’un er ya da geç şikâyet ettiği türden bir tutarsızlıktır bu. - Katalog yalnızca teklif usulü çalışıyor. Eylemi reddedin ve butonun yerine bir şey koyun. Fiyatı, butonu ve bir sonraki adımı olmayan bir ürün sayfası davet gibi değil, bozuk gibi okunur. Düzgün bir teklif isteme akışının yeri burasıdır ve PriceVeil tam da bu iş için yapıldı: katalog modu sepete eklemeyi varyasyon formu dahil klasik ve blok şablonlardan söker, Store API üzerinden gelen sepet yazma isteği sunucu tarafında reddedilir ve boşalan yeri bir teklif butonu doldurur.
- Yalnızca oturum açmış müşteriler satın alabilir. Misafirler için reddedin, üyeler için izin verin ve butonla birlikte fiyatı da gizleyin; üzerine bir işlem yapılamayan görünür bir fiyat, tam da kaçınmaya çalıştığınız e-postayı davet eder. Müşteriler oturum açana kadar fiyatları gizlemeye bakın.
- Gezilebilir bir broşür sitesi istiyorsunuz. Her yerde reddedin, ayrıca yönlendirmeler dahil sepet ve ödeme sayfalarını da kapatın. Adım adım anlatımı eklentisiz WooCommerce katalog modu yazısında.
Bunların hiçbirinin çözmediği şeyler#
Sınır durumlar konusunda dürüst olmak, daha uzun bir kod parçasından daha faydalıdır.
- Fiyatlar görünür kalır. WooCommerce’te satın alınabilirlik ile fiyat gösterimi ayrı meselelerdir. Butonu kaldırmak; fiyatı, fiyat aralığını, Store API fiyat alanlarını ve JSON-LD teklifini tam olarak oldukları yerde bırakır.
- Ürün akışları dışa aktarmayı sürdürür. Akış eklentileri ürün nesnesini doğrudan okur ve fiyatla sepete ekleme adreslerini, Google’ın, Meta’nın veya bir pazar yerinin belirli aralıklarla çektiği bir dosyaya yazar. Ön yüzde yaptığınız hiçbir şey o dosyayı değiştirmez. Akışı devre dışı bırakın veya ürünleri akışın kendi ayarlarından hariç tutun.
- Özel tema kodu kendi bildiğini okur. Kendi işaretlemesini
$product->add_to_cart_url()üzerinden basan bir tema ya da butonu içine gömülü gelen bir sayfa kurucu ürün bileşeni onu basmayı sürdürür. Filtreler, hiçbir soru sormayan koda ulaşamaz. - Hızlı ödeme butonları ayrı bir konu. PayPal, Apple Pay ve benzeri ödeme geçidi eklentileri kendi butonlarını kendi hook’larına enjekte eder. Genellikle satın alınabilirliğe bağlıdırlar, ama varsaymak yerine doğrulayın.
- Yönetim paneli ve kimlik doğrulamalı REST engellenmez. Bir API anahtarıyla oluşturulan
wc/v3siparişi sepetten geçmez, dolayısıyla satın alınabilirlik kontrolünü çalıştırmaz. Bu normalde doğru davranıştır, ama böyle olduğunu bilin. - Önbellekler eski sayfayı sunar. Değişikliği yayına almadan önce önbelleğe alınmış bir sayfada buton hâlâ durur. Hem sunucuda hem CDN’de bir kez temizleyin ve gizli pencerede yeniden kontrol edin.
Bundan sonra ne yapmalı#
Önce bir kontrolü mü gizlediğinize yoksa bir satışı mı reddettiğinize karar verin, çünkü yukarıdaki her şeyi belirleyen tek seçim budur. Cevap reddetmekse iki satın alınabilirlik filtresini ekleyin, düzen olsun diye döngü bağlantısı filtresini de bırakın, sonra güvenmek yerine doğrulayın: varyasyonlu bir ürünü açıp sayfa kaynağında varyasyon JSON’unu okuyun, curl komutlarını doğrudan adrese ve Store API uç noktasına karşı çalıştırın ve bir sonraki tema veya WooCommerce güncellemesinden sonra ikisini de tekrarlayın. Testin tamamı bu.
Aynı problemin fiyat tarafı da aynı biçime sahip ve PriceVeil’in üstlendiği taraf orası: her ürünü tek tek gezen ve bir fiyat yüzeyi sızdığında sıfırdan farklı bir kodla çıkan bir wp priceveil selftest komutuyla gelir. Söz konusu yüzeyler şunlar: fiyat HTML’i, yapılandırılmış veri, Store API ürün yanıtı ve koleksiyon fiyat aralığı. Belgeleri, hangi yüzeylerin otomatik olarak kapsandığını ve hangilerinin kontrolünün size kaldığını listeler. Her hâlükârda kendinize koymanız gereken ölçüt aynı: soru butonun sayfada olup olmadığı değil, ürünün hâlâ satın alınıp alınamadığıdır.
