Nodus Works olarak checkout extension geliştirdiğimiz projelerde yıllardır standart kabul edilen bir yöntem, 2 Temmuz 2026'da resmen tarihe karıştı: Shopify, checkout UI extension'larının en çok kullanılan API'lerinden biri olan useBuyerJourneyIntercept'i (ve altındaki buyerJourney.intercept mekanizmasını) deprecated ilan etti. Bu küçük bir API değişikliği değil; checkout validasyonunun çalıştığı yerin tarayıcıdan Shopify'ın kendi sunucu altyapısına taşınması anlamına geliyor. Türkiye'deki mağazalar için bu özellikle kritik, çünkü mesafeli satış sözleşmesi onayı, TC kimlik/vergi numarası doğrulaması ve il-ilçe seçimi gibi yerel zorunluluklar neredeyse her zaman bu API ile yazılıyordu. Aşağıda hem eski mimarinin neden çöktüğünü hem de geçişi üretimde sorunsuz yapmanın kod düzeyindeki adımlarını satır satır ele alıyoruz.
Kısaca Ne Oldu?
Shopify, 2 Temmuz 2026'da useBuyerJourneyIntercept'i deprecated ilan etti; yerine önerilen çözüm, sunucu tarafında çalışan Cart & Checkout Validation Function'lar. Eski yöntemde validasyon mantığı müşterinin tarayıcısında çalışıyordu; yeni yöntemde bu mantık Shopify'ın kendi sunucu altyapısında, WebAssembly üzerinde çalışıyor.
Eski Yöntem: Interceptor'lar Nasıl Çalışıyordu?
Interceptor mantığı basitti: extension, müşteri "Öde" butonuna bastığında araya girer, koşul sağlanmıyorsa ilerlemeyi bloklar ve alanın yanında bir hata gösterirdi.
// Eski yaklaşım (artık deprecated)
useBuyerJourneyIntercept(({ canBlockProgress }) => {
if (canBlockProgress && !isChecked) {
return {
behavior: "block",
reason: "Sözleşme onaylanmalı",
perform: (result) => {
if (result.behavior === "block") {
setError("Mesafeli Satış Sözleşmesi'ni onaylamalısınız.");
}
},
};
}
return { behavior: "allow" };
});
Kağıt üzerinde zarif bir tasarım. Pratikte ise Shopify'ın bu API'yi emekliye ayırmasının somut, yapısal sebepleri var.
Neden Kaldırılıyor? Interceptor Mimarisinin Yapısal Sorunları
1. Interceptor'lar Sadece "Öde" Butonunda Çalışmıyor
En az bilinen ve en kritik detay bu: interceptor'lar yalnızca ödeme denemesinde değil, checkout içindeki her negotiation'da (adres güncellemesi, pazarlama onayı kutucuğu, teslimat yöntemi değişikliği) tetiklenebiliyor. Yani "ödeme öncesi son kontrol" sandığınız kod, aslında checkout oturumu boyunca defalarca, öngörülemeyen anlarda çalışıyor. Interceptor içinde bir yazma işlemi (applyMetafieldsChange, applyAttributeChange vb.) yapıyorsanız, bu yazmalar Shopify'ın kendi aksiyonlarıyla yarışa girip checkout akışını yavaşlatabiliyor, uç senaryolarda kilitleyebiliyor.
2. İstemci Tarafı, Güvenilir Bir Sınır Değil
Interceptor tarayıcıda çalışır. Tarayıcıda çalışan her şey gibi: eski bir WebKit sürümünde render sorunu yaşayabilir, in-app browser'larda (Instagram, Facebook) farklı davranabilir, JavaScript hatasıyla sessizce devre dışı kalabilir. Extension yüklenmezse validasyon da yok demektir; bu, ancak eksik bilgiyle gelen siparişlerden fark edilir.
3. Ölçeklenme ve Performans
Her extension kendi interceptor'ını kaydettiğinde, Shopify her checkout etkileşiminde hepsini sırayla çalıştırıp sonuçları birleştirmek zorunda kalır. Extension sayısı arttıkça bu zincir uzar. Shopify'ın çözümü net: kuralları tek bir yerde, sunucuda, WebAssembly ile milisaniyeler içinde çalıştırmak.
Kritik Not: Bu üç sorunun ortak paydası, interceptor mimarisinin "yerel/istemci" bir yaklaşım olmasıdır. Validation Function'lara geçiş, yalnızca yeni bir API öğrenmek değil, checkout validasyonunu "sunucuda yaşayan bir iş kuralı" olarak yeniden düşünmek anlamına gelir.
useBuyerJourneyIntercept ile Validation Function Karşılaştırması
İki mimari arasındaki fark tek bir satırda özetlenemeyecek kadar temel: çalışma yeri, hata kaynağı ve devreye alma adımları baştan aşağı değişiyor.
Yeni Yöntem: Cart & Checkout Validation Function Nedir?
Validation Function'lar, Shopify Functions altyapısında çalışan küçük, saf fonksiyonlardır. Sepetin durumunu girdi olarak alır, hata listesi döndürür. Müşterinin tarayıcısında tek satır kod çalışmaz; kural ihlal edilmişse Shopify ödemeyi sunucuda durdurur. Hedef alan cart.validations.generate.run'dır.
// shopify.extension.toml
[[extensions]]
name = "t:name"
handle = "checkout-validation"
type = "function"
[[extensions.targeting]]
target = "cart.validations.generate.run"
input_query = "src/cart_validations_generate_run.graphql"
Fonksiyonun kendisi de bir o kadar sadedir:
export function cartValidationsGenerateRun(input) {
const errors = [];
if (input.buyerJourney?.step !== "CHECKOUT_COMPLETION") {
return { operations: [] };
}
const onay = input.cart.sozlesme?.value;
if (onay !== "1") {
errors.push({
message: "Devam edebilmek için sözleşmeleri onaylamanız gerekmektedir.",
target: "$.cart",
});
}
return { operations: [{ validationAdd: { errors } }] };
}
UI'daki Form Verisi Sunucuya Nasıl Ulaşır?
Kritik soru bu: Validation Function tarayıcıya erişemez, yalnızca sepetin kendisini görür. Üretimde iyi çalışan desen şudur: UI extension, validasyon durumunu sepete bir attribute olarak yazar; function bu attribute'u okur.
// UI extension tarafı: durum değiştikçe attribute güncelle
const lastValidation = useRef("");
useEffect(() => {
const status = isChecked
? "1"
: "Mesafeli Satış Sözleşmesi'ni onaylamalısınız.";
if (lastValidation.current === status) return;
lastValidation.current = status;
applyAttributeChange({
key: "_sozlesme_onay_ok",
value: status,
type: "updateAttribute",
});
}, [isChecked, applyAttributeChange]);
Function tarafında ise input query ile yalnızca ihtiyacınız olan attribute'ları çekersiniz:
query CartValidationsGenerateRunInput {
cart {
sozlesme: attribute(key: "_sozlesme_onay_ok") {
value
}
}
buyerJourney {
step
}
}
Bu desenin zarif bir yan etkisi var: attribute değeri "1" değilse, içindeki metin doğrudan müşteriye gösterilecek hata mesajıdır. Hata metinlerini UI extension'da tek yerden yönetirsiniz; function yalnızca taşıyıcıdır.
Üretim Ortamından Beş Kritik Ders
Bu geçişi gerçek trafiği olan mağazalarda uygulamış biri olarak, dokümantasyonda yeterince vurgulanmayan beş noktayı paylaşıyoruz.
1. Sadece CHECKOUT_COMPLETION Adımında Doğrulayın
Function'ı CHECKOUT_INTERACTION adımında da çalıştırırsanız, müşteri daha sayfayı açar açmaz, henüz hiçbir alana dokunmadan, ekranın tepesinde kırmızı hata banner'ları belirir. Dönüşüm oranı için bu bir felakettir; yukarıdaki step kontrolü süs değil, zorunluluktur.
2. Attribute Yazımını Debounce Edin ve Tekrarları Eleyin
Her tuş vuruşunda applyAttributeChange çağırmak, Shopify'ın değişiklik limitine takılmanın en garantili yoludur. Limit aşıldığında sonraki yazımlar sessizce düşer; siparişler eksik veriyle gelmeye başlar. 300-500ms debounce ve "aynı değeri tekrar yazma" kontrolü şarttır.
useEffect(() => {
const timer = setTimeout(() => {
if (lastWritten.current === status) return;
lastWritten.current = status;
applyAttributeChange({ key, value: status, type: "updateAttribute" });
}, 400);
return () => clearTimeout(timer);
}, [status]);
3. Attribute Yoksa Kuralı Atlayın (Fail-Open)
Function'ınız, attribute hiç yazılmamışsa kuralı atlamalıdır. Aksi halde ilgili extension'ın checkout'a eklenmediği bir mağaza konfigürasyonunda kimse ödeme yapamaz. Function, tek başına hiçbir şeyi bozamayacak şekilde tasarlanmalıdır.
4. Deploy Yetmez: Admin'den Aktifleştirmeniz Gerekiyor
En çok atlanan adım budur: shopify app deploy sonrası function kendiliğinden devreye girmez. Mağaza yöneticisinin Ayarlar → Ödeme → Checkout kuralları bölümünden kuralı ekleyip aktifleştirmesi gerekir. Bunu yapmadan yapılan tüm testler "her şey çalışıyor" yanılgısı verir. Deploy sonrası aktivasyon adımının atlanıp atlanmadığını düzenli kontrol etmek isteyen mağazalar için Shopify teknik destek ve bakım hizmetimiz bu tür checkout kurallarını periyodik olarak denetler.
5. Hata Gösterimi Değişiyor: Müşteri Deneyimini Buna Göre Tasarlayın
Interceptor'lar hatayı ilgili alanın hemen yanında gösterebiliyordu. Sunucu validasyonunda $.cart hedefli hatalar sayfa düzeyinde banner olarak görünür. Format hatalarını (örneğin 11 haneden kısa kimlik numarası) hâlâ istemcide, alanın yanında anlık göstermek; "zorunlu alan boş" kontrolünü ise sunucuya bırakmak en dengeli kombinasyondur.
Uzak Durulması Gereken Risk: Deploy ettiğiniz bir Validation Function'ın admin panelinden aktifleştirilmediğini fark etmeden "geçiş tamamlandı" dememeye dikkat edin. Bu, Shopify Inbox veya tam sayfa UI extension'larda da tekrar eden bir örüntü: deploy ve aktivasyon her zaman iki ayrı adımdır.
Geçiş Kontrol Listesi
- Mevcut tüm useBuyerJourneyIntercept kullanımlarını ve toml dosyalarındaki block_progress yetkilerini envanterleyin.
- Her kural için: hangi veriye ihtiyaç var, bu veri sepette attribute olarak nasıl temsil edilir?
- cart.validations.generate.run hedefli tek bir function yazın; kuralları tek yerde toplayın.
- Fixture tabanlı testler ekleyin (Shopify'ın shopify-function-test-helpers paketi bunun için var): geçerli sepet, eksik veri, sepet aşamasında atlama senaryoları.
- Deploy edin, admin'den kuralı aktifleştirin, gerçek cihazlarda uçtan uca test edin.
- Interceptor kodunu ancak bundan sonra silin.
Hangi Türkiye'ye Özgü Kural, Hangi Attribute'a Taşınır?
Türkiye'deki mağazalarda interceptor'la yazılmış üç yaygın kural, aşağıdaki gibi ayrı attribute'lara bölünüp tek bir function içinde toplanabilir.
Sıkça Sorulan Sorular
useBuyerJourneyIntercept ne zaman deprecated oldu?
2 Temmuz 2026'da. Yerine önerilen çözüm, sunucu tarafında çalışan Cart & Checkout Validation Function'lardır.
Validation Function ile interceptor arasındaki temel fark nedir?
Interceptor müşterinin tarayıcısında çalışır ve tarayıcı kısıtlamalarına (eski WebKit, in-app browser, JS hatası) açıktır. Validation Function Shopify'ın sunucusunda çalışır; müşteri tarafında hiçbir kod çalışmadan kural ihlali sunucuda engellenir.
Validation Function, UI extension'daki form verisine nasıl erişir?
Doğrudan erişemez. UI extension, durumu sepete bir attribute olarak yazar; Validation Function bu attribute'u input query üzerinden okur.
Function'ı deploy ettikten sonra otomatik aktif olur mu?
Hayır. Deploy ile aktivasyon iki ayrı adımdır; mağaza yöneticisinin Ayarlar → Ödeme → Checkout kuralları bölümünden kuralı ayrıca eklemesi ve aktifleştirmesi gerekir.
Türkiye'deki mağazalar için bu değişiklik neden özellikle önemli?
Mesafeli satış sözleşmesi onayı, TC kimlik/vergi numarası doğrulaması ve il-ilçe seçimi gibi yerel zorunluluklar yaygın olarak useBuyerJourneyIntercept ile yazılıyordu. Bu kuralların Validation Function'a taşınmadığı mağazalarda, deprecation sonrası bu doğrulamalar çalışmayı durdurabilir.
Interceptor kodunu ne zaman silmeliyim?
Yalnızca Validation Function'ı deploy edip admin'den aktifleştirdikten ve gerçek cihazlarda uçtan uca test ettikten sonra. Bu sıralamayı atlamak, geçiş sırasında validasyonun hiç çalışmadığı bir ara dönem yaratabilir.
Sonuç
useBuyerJourneyIntercept'in emekliliği ilk bakışta angarya gibi görünse de, doğru yapılan bir geçişin sonucu net biçimde daha iyidir: validasyon artık cihazdan, tarayıcıdan, in-app browser tuhaflıklarından bağımsız; kurallar tek bir yerde, test edilebilir ve müşteri tarafında manipüle edilemez durumdadır. Checkout gibi paranın el değiştirdiği bir yüzeyde "iş kuralları sunucuda yaşar" ilkesine dönmek, ertelenmiş bir borcun kapanması aslında. Temmuz 2026 geldi; interceptor'larınız hâlâ üretimdeyse, bu geçişi sprint planına almanın tam zamanı.
Checkout validasyon kurallarınızı Validation Function'lara taşımak veya mevcut extension'larınızı bu geçişe hazırlamak için Shopify entegrasyon çözümleri hizmetimiz hakkında ekibimizle iletişime geçebilirsiniz.
.jpg)




