WordPress

    WooCommerce Her Sayfada Yavaş Açılıyor: Cart Fragments İsteğini Kapatma

    WooCommerce sepet parçacıkları isteğinin sayfa önbelleğini neden atladığını ölçme ve mini sepeti bozmadan kapatma rehberi.

    11 dk okuma Güncellendi: 18 Ağustos 2026

    Mağazanız için yapılabilecek her şeyi yaptınız. Önbellek eklentisi kurulu, görseller WebP'ye çevrildi, PHP 8.3'te çalışıyorsunuz. GTmetrix raporu da bunu doğruluyor: TTFB 120 ms, skorlar yeşil. Ama siteyi kendi telefonunuzdan gezdiğinizde bir tuhaflık var — sayfa açılıyor, içerik geliyor, sonra bir yarım saniye daha "tam oturmamış" gibi duruyor. Üstelik sunucu paneli, ziyaretçi sayısıyla açıklanamayacak kadar yüksek bir PHP isteği trafiği gösteriyor.

    Tarayıcıda F12 ile geliştirici araçlarını açıp Network sekmesinin filtre kutusuna wc-ajax yazın. Karşınıza büyük ihtimalle şu satır çıkacak:

    GET https://magaza.com/?wc-ajax=get_refreshed_fragments — 200 — 640 ms

    Bu istek, sayfanın HTML'i önbellekten 90 ms'de gelirken hemen arkasından fırlayan, PHP'yi ve WooCommerce'i baştan çalıştıran ayrı bir istektir. Önbellek eklentiniz bunu bilerek atlar; dolayısıyla ne kadar önbellek katmanı eklerseniz ekleyin bu satır aynı süreyi harcamaya devam eder. Genel mağaza hızlandırma adımlarını WooCommerce performans rehberinde topladık; burada yalnızca bu tek isteğin ne olduğunu, gerçekten ne sıklıkta çalıştığını, kapatmaya değip değmeyeceğini ve kapatırken neyi bozma riskiniz olduğunu ele alacağız.

    wc-ajax=get_refreshed_fragments Nedir, Ne İşe Yarar?#

    WooCommerce'in çözmeye çalıştığı problem gerçek bir problemdir. Tam sayfa önbelleği herkese aynı HTML'i verir. Ama üst menüdeki mini sepette "2 ürün — 349,90 TL" yazması gerekir ve bu bilgi kişiye özeldir. Aynı önbelleklenmiş HTML'i alan iki farklı ziyaretçiye farklı bir sepet göstermek gerekir.

    WooCommerce bunu cart fragments (sepet parçacıkları) API'siyle çözer. Mantık şudur: sayfanın tamamı önbellekten gelsin, ama sepetle ilgili küçük HTML parçaları sonradan bir AJAX isteğiyle getirilip yerine yazılsın. Bu parçaları üreten uç nokta ?wc-ajax=get_refreshed_fragments, isteği atan betik ise wc-cart-fragments handle'ıyla kaydedilen cart-fragments.js dosyasıdır. Sunucu tarafında WC_AJAX::get_refreshed_fragments() çalışır; hangi HTML parçalarının döneceğini woocommerce_add_to_cart_fragments filtresi belirler ve varsayılan olarak mini sepet içeriği (div.widget_shopping_cart_content) bu listededir.

    Buradaki maliyet, uç noktanın kendisinden değil bedelinden gelir. ?wc-ajax= uç noktası, admin-ajax.php'ye göre biraz daha hafiftir (yönetici tarafı yüklenmez), ama yine de WordPress çekirdeğini, tüm aktif eklentileri, WooCommerce'i ve temayı baştan yükler, oturumu açar ve sepeti veritabanından okur. Yani "küçük bir parça HTML" için tam bir PHP çalıştırması yapılır. Aynı sınıftan başka bir yükü, panel tarafındaki Heartbeat trafiğini, admin-ajax.php CPU tüketimi yazımızda ele almıştık; buradaki fark, bu isteğin ziyaretçi tarafında ve oturum açmamış kullanıcılar için de çalışmasıdır.

    Sayfa Önbelleği Bu İsteği Neden Kurtaramıyor?#

    Bu, konunun en yanlış anlaşılan kısmı. Cevap basit: WooCommerce bu isteğin önbelleğe alınmasını kendisi engeller. WC_AJAX sınıfı, isteği işlemeye başlarken önbellek karşıtı başlıkları gönderir ve DOING_AJAX sabitini tanımlar. Bunun üstüne bütün ciddi önbellek eklentileri ve sunucu düzeyindeki FastCGI/Varnish yapılandırmaları wc-ajax içeren istekleri bilerek dışarıda bırakır. Bırakmasalar zaten felaket olurdu: bir müşterinin sepeti başka bir müşteriye gösterilirdi.

    Bunun ölçüm tarafındaki sonucu kafa karıştırıcıdır. Hangi aracın bu maliyeti gördüğüne dikkat edin:

    Araç / ölçümCart fragments'ı görür mü?Neden
    GTmetrix "TTFB"HayırYalnızca ana HTML belgesini ölçer, o da önbellekten gelir
    GTmetrix / WebPageTest şelale grafiğiEvetİstek listede görünür, süresi okunur
    Lighthouse performans skoruKısmenAna iş parçacığını meşgul ettiği ölçüde TBT'ye yansır
    Sunucu erişim loguEvetHam gerçek: kaç kez, hangi saatte
    Hosting paneli PHP/CPU grafiğiEvetZiyaretçi sayısıyla orantısız yük olarak
    Sayfa hızı eklentisinin "önbellek isabet oranı"HayırBu istek zaten önbellek kapsamı dışında

    Yani "sayfa hızı testim yeşil ama sunucum yanıyor" tablosunun tipik sorumlularından biri budur. TTFB kavramının bütününe hâkim değilseniz TTFB nedir, nasıl düşürülür yazımız iyi bir zemin sunar.

    Adım 1: Ölçün — Gerçekten Her Sayfada mı Çalışıyor?#

    İnternetteki çoğu yazı "cart fragments her sayfa yüklemesinde çalışır" der. Bu, doğruluğu siteye göre değişen bir genellemedir ve körlemesine müdahale etmenin bahanesi olmamalı. Betiğin gerçek davranışı şöyledir:

    cart-fragments.js aldığı parçaları tarayıcının sessionStorage alanına yazar (wc_fragments_... ve wc_cart_hash_... anahtarları). Sonraki sayfa açılışında önce oraya bakar. Depodaki sepet özeti woocommerce_cart_hash çerezindeki değerle eşleşiyorsa ve kayıt 24 saatten eski değilse, hiçbir AJAX isteği atmadan saklanan HTML'i yerine yazar.

    Buna göre istek şu durumlarda gerçekten gider:

    1. Oturumun ilk sayfa açılışında. sessionStorage henüz boştur. Reklamla gelen, çoğunluğu yeni ziyaretçi olan bir mağazada bu "neredeyse her ziyaretçide bir kez" demektir.
    2. Her yeni sekmede. sessionStorage sekme başınadır.
    3. Sepet her değiştiğinde. Ürün ekleme, çıkarma, adet güncelleme.
    4. 24 saatlik zamanlayıcı dolduğunda. Betik başarılı bir tazelemeden sonra bir gün sonrasına zamanlayıcı kurar.
    5. Gizli sekmede veya depolama kapalıysa. Önbellekleme mekanizması devre dışı kalır, her sayfada istek gider.
    6. Tema veya eklenti wc_fragment_refresh olayını tetikliyorsa. Bazı temalar bunu her sayfa yüklemesinde yapar; bu durumda genelleme gerçekten doğru olur.

    Bu yüzden varsaymayın, sayın. Sunucudaki erişim logunda tek satırlık bir sayım yeterlidir:

    cd ~/access-logs
    grep -c 'wc-ajax=get_refreshed_fragments' magaza.com
    

    Aynı logdan saat bazında dağılımı da çıkarın; ziyaretçi sayısına oranı size gerçek durumu söyler:

    grep 'wc-ajax=get_refreshed_fragments' magaza.com \
      | awk -F'[:[]' '{print $2" "$3":00"}' | sort | uniq -c | sort -k2
    

    Sonra isteğin kaç milisaniye sürdüğünü ölçün. Bu uç nokta önbelleğe girmediği için sonucu doğrudan okuyabilirsiniz:

    for i in 1 2 3; do
      curl -o /dev/null -s -w 'fragments ttfb: %{time_starttransfer}s\n' \
        'https://magaza.com/?wc-ajax=get_refreshed_fragments'
    done
    
    curl -o /dev/null -s -w 'onbellekli sayfa ttfb: %{time_starttransfer}s\n' \
      'https://magaza.com/'
    

    İki rakam arasındaki fark, kararınızın dayanağıdır. Önbellekli sayfa 90 ms, fragments isteği 700 ms geliyorsa, ziyaretçinin gerçekten yaşadığı gecikmenin büyük kısmı ikinci satırdadır. Fragments isteği 120 ms sürüyorsa kapatmanın kazancı da o kadardır; uğraşmaya değmeyebilir.

    Adım 2: Karar — Mini Sepetin Canlı Güncellenmesi Şart mı?#

    Kapatma kararı teknik değil, ürün kararıdır. Şu soruya dürüst cevap verin: ziyaretçi bir ürünü sepete eklediğinde sayfa yenilenmeden üst köşedeki sayacın değişmesi gerçekten gerekiyor mu?

    Mağaza tipiArşivde AJAX sepete eklemeÜstte canlı mini sepetÖneri
    Az sayıda ürün, ürün sayfasından satışKapalıYok / statik "Sepet" bağlantısıFragments'ı kapatın
    Kategori sayfasından hızlı ekleme yapılan mağazaAçıkVar, aktif kullanılıyorKapatmayın, sadece gereksiz sayfalarda kısıtlayın
    Blog + küçük mağaza karışımıKapalıYalnız mağaza sayfalarındaMağaza dışındaki sayfalarda kapatın
    Tek ürünlü / abonelik satışıKapalıYokKapatın

    Çoğu Türkiye pazarındaki mağazada üçüncü satır geçerlidir: sitenin büyük bölümü blog, kurumsal sayfalar ve iletişimdir; mini sepetin oralarda canlı olması hiçbir işe yaramaz ama bedeli her sayfada ödenir. Doğru yaklaşım "tamamen kapat" değil, koşullu kapattır.

    Adım 3: Resmî Yöntem — woocommerce_get_script_data ile Koşullu Kapatma#

    WooCommerce'in kendi geliştirici belgelerinde önerdiği yöntem, betiği kaldırmak yerine ona ihtiyaç duyduğu parametreleri vermemektir. cart-fragments.js dosyası ilk satırında şu kontrolü yapar: wc_cart_fragments_params tanımlı değilse hiçbir şey yapmadan çıkar. Yani parametreleri kesmek, dosyayı yüklenmiş ama tamamen sessiz bırakır — hiçbir JavaScript hatası üretmez, hiçbir istek atmaz.

    Aşağıdaki kodu çocuk temanızın functions.php dosyasına veya bir kod parçacığı eklentisine ekleyin:

    add_filter( 'woocommerce_get_script_data', function ( $params, $handle ) {
        if ( 'wc-cart-fragments' !== $handle ) {
            return $params;
        }
    
        // Sepet, odeme ve magaza arsivlerinde acik kalsin.
        if ( is_cart() || is_checkout() || is_shop() || is_product_category() || is_product_tag() ) {
            return $params;
        }
    
        // Diger tum sayfalarda parcaciklari devre disi birak.
        return null;
    }, 10, 2 );
    

    Koşulları kendi mağazanıza göre daraltıp genişletebilirsiniz. Arşivlerde AJAX sepete ekleme kullanmıyorsanız is_shop(), is_product_category() ve is_product_tag() satırlarını kaldırın; o zaman parçacıklar yalnızca sepet ve ödeme sayfalarında çalışır.

    Betiği Tamamen Kaldırmak İsterseniz#

    Dosyanın hiç yüklenmemesini istiyorsanız kuyruktan çıkarabilirsiniz. Burada tek incelik önceliktir: wc-cart-fragments varsayılan öncelikte (10) kuyruğa eklendiği için sizin kodunuzun sonra çalışması, yani en az 11 önceliğinde kayıtlı olması gerekir.

    add_action( 'wp_enqueue_scripts', function () {
        if ( is_cart() || is_checkout() ) {
            return;
        }
        wp_dequeue_script( 'wc-cart-fragments' );
    }, 11 );
    

    İki yöntemi aynı anda uygulamayın; ikisi de aynı sonucu verir ve üst üste bindiklerinde hangi kodun etkili olduğunu anlamak zorlaşır. Filtre yöntemi daha güvenlidir çünkü betiğe bağımlı başka bir kod varsa onu kırmaz.

    Bir eklentiyle (Perfmatters, WP Rocket veya LiteSpeed'in ilgili anahtarı) kapatmak da mümkündür. Kod yazmak istemiyorsanız bu geçerli bir seçenektir, ancak çoğu eklenti "tamamen kapat" mantığında çalışır ve sayfaya göre ayrım yapmaz — bu, bir sonraki bölümdeki riski doğrudan üstlenmek demektir.

    Adım 4: Alternatif Çözümler — Parçacıksız Bir Mini Sepet#

    Kapatmak yerine ihtiyacı ortadan kaldırmak daha kalıcı bir çözümdür. Üç yol var.

    Mini Cart bloğunu kullanın. WooCommerce'in blok tabanlı Mini Cart bileşeni sepet parçacıkları API'sini hiç kullanmaz; sepeti Store API üzerinden okur ve klasik parçacık isteğini üretmez. Tema yapınız blok editörüne uygunsa eski widget'ı bu blokla değiştirmek, kapatma tartışmasını tamamen bitirir.

    Sayacı sunucu tarafında basın. Sepet sayısını sayfa üretilirken doğrudan yazabilirsiniz:

    add_shortcode( 'sepet_sayaci', function () {
        if ( ! function_exists( 'WC' ) || null === WC()->cart ) {
            return '';
        }
        return esc_html( WC()->cart->get_cart_contents_count() );
    } );
    

    Burada dürüst olmak gerekir: tam sayfa önbelleği devredeyse bu sayı bayat kalır. Önbellekten dönen HTML, sepete ürün eklendiğini bilemez. Bu yüzden sunucu tarafı sayacı üç durumda anlamlıdır: sayfa önbelleği kullanmıyorsanız, ilgili başlık bölümünü önbellekten muaf tutabiliyorsanız, ya da LiteSpeed'in ESI (Edge Side Includes) özelliğiyle yalnızca o parçayı dinamik bırakabiliyorsanız. LiteSpeed kurulumu için LiteSpeed Cache WordPress yazımıza bakabilirsiniz.

    Sayıyı tamamen kaldırın. En basit ve en hızlı çözüm çoğu zaman budur: menüdeki "Sepet" bağlantısının yanında rakam göstermeyin. Ziyaretçi sepete eklediğinde WooCommerce'in kendi bildirim mesajı zaten görünür; sayacı görmek için sepet sayfasına gitmesi yeterlidir. Bir sayı uğruna her ziyaretçiye ek bir PHP isteği ödetmek, dönüşüme katkısı ölçülmemiş bir maliyettir.

    Arşivlerde AJAX sepete ekleme özelliğine ihtiyacınız yoksa onu da kapatın: WooCommerce → Ayarlar → Ürünler → Genel altında "Arşivlerde AJAX sepete ekle butonlarını etkinleştir" seçeneğini kaldırdığınızda buton normal bir bağlantıya döner ve parçacık tazelemesine gerek kalmaz.

    Adım 5: Kapattıktan Sonra Sepet Akışını Mutlaka Test Edin#

    Bu adımı atlamak, bu işin klasik hatasıdır. Parçacıkları kapatmanın en sinsi yan etkisi, sitede bir hata mesajı üretmemesi; sadece geri bildirimin sessizce kaybolmasıdır. Ziyaretçi "Sepete Ekle" butonuna basar, ürün gerçekten sepete eklenir, ama üstteki sayaç değişmez. Kullanıcı da ürünün eklenmediğini sanıp bir kez daha basar veya siteyi terk eder. Sipariş kaybı olarak geri döner ve kimse bunu bir ay önceki performans ayarıyla ilişkilendiremez.

    Değişiklikten sonra şu listeyi baştan sona, gizli sekmede ve mümkünse hem masaüstü hem mobilde uygulayın:

    1. Kategori sayfasından bir ürünü sepete ekleyin. Buton dönme animasyonunda takılı kalıyor mu, yoksa "Sepeti Görüntüle" bağlantısına dönüyor mu?
    2. Üst menüdeki mini sepet sayacı değişti mi? Değişmediyse bu, kabul ettiğiniz bir ödün mü yoksa fark etmediğiniz bir kayıp mı?
    3. Tekil ürün sayfasından ekleme yapın; aynı iki kontrolü tekrarlayın.
    4. Sepet sayfasında adet güncelleyin, ürün silin, "Sepeti güncelle" düğmesine basın. Ara toplam doğru güncelleniyor mu?
    5. Kupon kodu uygulayın ve kaldırın; toplam anında değişiyor mu?
    6. Ödeme sayfasında kargo yöntemini değiştirin; sipariş özeti güncelleniyor mu? (Bu ekran ayrı bir mekanizma kullanır ama birlikte test etmekte fayda var.)
    7. Sepeti tamamen boşaltın, sonra yeni bir ürün ekleyin.
    8. İkinci bir sekme açıp aynı mağazayı gezin; sepet içeriği tutarlı mı?

    Bir aksaklık görürseniz çözüm geri almak değil, koşulu daraltmaktır: filtreye is_shop(), is_product_category() ve is_product() koşullarını ekleyerek parçacıkları ürün gezinme sayfalarında açık bırakın, blog ve kurumsal sayfalarda kapalı tutun. Kazancın büyük kısmını yine alırsınız.

    Mağazayı yeni kuruyorsanız bu ayarları en baştan doğru yapmak en ucuz yoldur; temel kurulum adımları için WooCommerce başlangıç rehberimiz iyi bir başlangıç noktasıdır.

    Hâlâ Yavaşsa Suçlu Fragments Değildi#

    Ölçümle başlayıp ölçümle bitirin. Değişiklikten sonra erişim logunda sayımı ve curl ile süreyi tekrar alın. İstek sayısı düştüyse ama site aynı hızda kalıyorsa, fragments zaten baskın maliyet değildi. Sıradaki adaylar şunlardır: eksik object cache nedeniyle her istekte veritabanına giden sepet oturumları, panelde sürekli çalışan Heartbeat trafiği, önbelleğe hiç girmeyen arama ve filtre sayfaları, wp_options tablosunda her istekte belleğe yüklenen şişkin autoload verisi, ve tek bir yavaş eklenti.

    Kapatma kararını da bir belge hâline getirin: hangi sayfalarda kapattığınızı ve hangi testleri geçtiğinizi bir yere not edin. Altı ay sonra tema güncellemesiyle mini sepet çalışmadığında, sorunun kaynağını dakikalar içinde bulmanızı sağlayacak tek şey bu nottur.

    Sıkça Sorulan Sorular#

    Cart fragments'ı kapatmak sepetin çalışmasını bozar mı?#

    Sepetin kendisi bozulmaz. Ürün ekleme, çıkarma, kupon ve ödeme işlemleri sunucu tarafında yürür ve bu istekten bağımsızdır. Bozulan şey anlık görsel geri bildirimdir: sayfa yenilenmeden mini sepet sayacının güncellenmesi ve bazı temalarda "Sepete Ekle" butonunun "Sepeti Görüntüle" hâline dönmesi. Bu yüzden kapattıktan sonra kategori sayfasından ekleme akışını gizli sekmede mutlaka test etmelisiniz.

    Önbellek eklentim var, bu istek yine de çalışır mı?#

    Evet, hem de bilerek. WooCommerce bu uç nokta için önbellek karşıtı başlıklar gönderir ve önbellek eklentileri wc-ajax içeren istekleri kapsam dışında bırakır. Bırakmasalardı bir müşterinin sepeti başkasına gösterilebilirdi. Sonuç olarak sayfanın HTML'i önbellekten milisaniyeler içinde gelirken, hemen ardından tam bir PHP çalıştırması gerektiren ikinci bir istek gider. Önbellek katmanı eklemek bu maliyeti azaltmaz.

    Bu istek gerçekten her sayfa açılışında mı gidiyor?#

    Her zaman değil. Betik aldığı parçacıkları tarayıcının sessionStorage alanına yazar ve sepet özeti çerezle eşleşiyorsa yeni istek atmadan onları kullanır. İstek tipik olarak oturumun ilk sayfasında, her yeni sekmede, sepet her değiştiğinde ve 24 saatlik zamanlayıcı dolduğunda gider. Ancak bazı temalar her sayfada tazeleme olayını tetikler; bu yüzden varsaymak yerine erişim logunda saymak gerekir.

    wc-ajax ile admin-ajax.php arasındaki fark nedir?#

    İkisi de sunucuda tam bir WordPress yüklemesine yol açar, ama ?wc-ajax= uç noktası yönetici tarafını yüklemediği için biraz daha ucuzdur ve WooCommerce tarafından ziyaretçi istekleri için tercih edilir. Asıl fark kimin tetiklediğidir: admin-ajax.php trafiğinin büyük kısmı panelde çalışan Heartbeat ve eklenti sorgularından gelir, cart fragments ise oturum açmamış ziyaretçilerde de çalışır ve doğrudan satış akışını etkiler.

    Mini Cart bloğu bu sorunu tamamen çözer mi?#

    Blok tabanlı Mini Cart bileşeni klasik parçacık isteğini üretmez, sepet verisini Store API üzerinden okur; dolayısıyla get_refreshed_fragments trafiğini ortadan kaldırır. Ancak bu da bir istek yapar ve temanızın blok yapısına uygun olmasını gerektirir. Klasik bir temada widget alanları kullanılıyorsa geçiş her zaman sorunsuz olmaz. Geçiş öncesi bir hazırlık kopyasında denemek en doğrusudur.

    Kapatınca ne kadar hızlanma beklemeliyim?#

    Beklentiyi ölçümünüz belirler, genel bir yüzde vermek yanıltıcı olur. Fragments isteği 600-900 ms sürüyorsa ve ziyaretçilerinizin çoğu yeni oturumla geliyorsa, algılanan yüklenme süresinde belirgin bir iyileşme ve sunucuda ziyaretçi başına bir PHP çalıştırması kadar yük azalması görürsünüz. İstek 100-150 ms sürüyorsa kazanç dikkate değmez; o durumda enerjinizi başka bir darboğaza harcayın.

    WooCommercePerformansE-Ticaret

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.