Sunucu Taraflı Render API

Basmaya hazır HTML döndüren sunucudan sunucuya endpoint

Sunucu taraflı render ucu, panelde hazırladığınız zenginleştirme içeriğini basmaya hazır HTML olarak döndürür. Kendi uygulama sunucunuzdan çağırır, çıktıyı şablonunuza olduğu gibi yazarsınız. Bu sayfa HTTP sözleşmesidir: kimlik, parametreler, yanıt, önbellek, sınırlar, hatalar.

Neden hazır HTML

Diğer public uçlar ham veri döndürür ve işlemeyi widget yapar: yer tutucu doldurma, HTML temizleme, CSS kapsamlama. Sunucu tarafında bu üç adımı size yaptırmak üç ayrı güvenlik açığı davetiyesi olurdu: şablonda |safe, temizlenmemiş markup, kapsamlanmamış CSS. Bu yüzden uç son hâli döndürür: yer tutucular yerleşmiş, izin listesine göre temizlenmiş, CSS blok kapsamına alınmış. Widget'ın tarayıcıda, panel önizlemesinin ve bu ucun kullandığı işleme hattı aynıdır; panelde onayladığınız blok sayfada onayladığınız hâliyle çıkar.

Dönen HTML'i ikinci bir sanitizer'dan geçirmeyin

İçerik zaten temizlendi. Genel amaçlı bir sanitizer data-selwise-* niteliklerini siler; widget bloğu tanıyamaz, sayfada olduğunu bilmez ve ikinci bir kopyasını basar. Alışverişçi içeriği iki kez görür, arama motoru kopya içerik görür.

Uç nokta

get/api/v1/public/sites/{siteKey}/ssr/enrichments

Kimlik: x-selwise-api-key, her istekte (ssr_read kapsamı)

Parametreler

siteKeystring · yolzorunlu

Kanal anahtarı (Kanallar → Kanal Özeti → Kanal Anahtarı). Kanalı adlandırır; sır değildir.

codestring · sorgu

Ürün kodu: sku, item_code ya da sepet kodu; büyük/küçük harf duyarsız, en çok 100 karakter. Boş ya da uzunsa hata değil boş yanıt döner.

slotsstring · sorgu

Yuva adları: virgülle ayrılmış (a,b) ya da tekrarlı parametre (slots=a&slots=b). Küçük harf, rakam ve tek tire; en çok 10, fazlası atılır. Verilmezse boş yanıt.

langstring · sorgu

Ziyaretçinin ya da sayfanın dili (tr, en-GB…). Hesabın dillerinden en yakını seçilir; yoksa varsayılan dil. Tek dilli hesapta etkisi yoktur.

GET /api/v1/public/sites/SITE_KEY/ssr/enrichments?code=ABC-1&slots=urun-aciklama-alti
x-selwise-api-key: swpk_live_...

Kimlik doğrulama

Diğer public uçlar güvenliği doğrulanmış alan adından alır. Sunucudan gelen bir isteğin Origin başlığı yoktur ve bir tarayıcı da bu ucu kimliksiz çağıramasın diye, bu uç her istekte, başlığın varlığından bağımsız olarak site API anahtarı ister.

Anahtarı Channels ekranında kanalın satırındaki ⋮ menüsünden API keys'i açıp Purpose (Kullanım amacı) olarak Server-side rendering (Sunucu taraflı render) seçerek oluşturun. Anahtar swpk_live_ ile başlar ve yalnızca bir kez gösterilir. Ayrıntı: API Anahtarları.

ssr_read kapsamı mobil SDK'nın mobile_read/mobile_write çiftiyle aynı torbada değildir: SSR anahtarı sizin uygulama sunucunuzda yaşar, dağıtım hattınızdan, CI günlüklerinizden ve imajlarınızdan geçer; sızan bir SSR anahtarı hiçbir şey yazamaz ve iptali mobil uygulamayı durdurmaz. ssr_read bu uç dışında hiçbir ucu açmaz.

SSR yalnızca web kanalı içindir: bir uygulama kanalının sayfa şablonu yoktur. Uygulama kanalında bir ssr_read anahtarı 403 alır; uygulamanın karşılığı app/enrichments ucudur.

YanıtAnlamı
401x-selwise-api-key başlığı yok. Bir şey sunmadınız
403Anahtar geçersiz, iptal edilmiş ya da ssr_read kapsamı yok; ya da kanal bir web kanalı değil; ya da hesabın teslimatı kapalı
404siteKey bulunamadı
429Anahtar başına hız sınırı; Retry-After saniyedir

Hız sınırı

Anahtar başına, IP başına değil: varsayılan 6000 istek/dakika. Sınır, anahtar doğrulanmadan önce sayılır; yanlış anahtarla yapılan deneme de sayaca girer (anahtar deneme saldırısının veritabanına ulaşmasını sınırlamak için).

Sebebi doğrudan sizinle ilgili: diğer public uçları alışverişçilerin tarayıcıları çağırır, yani bir IP kabaca bir ziyaretçidir. SSR çağrısını sizin sunucularınız yapar; bütün mağaza trafiği birkaç adresten çıkar. IP başına sayılsaydı yoğun bir mağaza paylaşılan public kovayı saniyeler içinde tüketir ve widget'ınızı, olay akışınızı ve aramanızı da durdururdu.

Yanıt X-RateLimit-Limit ve X-RateLimit-Remaining başlıklarını taşır. Selwise'in kendi sınırlayıcı deposu erişilemezse sınır açık bırakılır (istek reddedilmez): ürün sayfanız bizim sınırlayıcımızın arızası yüzünden render olmamalıdır.

İstek

Bir blok birden çok dilde yazılmışsa lang hangisinin basılacağını seçer; her dil ayrı önbelleğe yazılır. Hazır Akinon yardımcıları dili kendisi gönderir: PZ Classic Django'nun etkin dilini okur, PZ Next yardımcısının son parametresi dildir.

İki yazım da kabul edilir, çünkü ikisi de doğal olarak yazılan biçimdir: Django'nun urlencode çıktısı tekrarlı, elle kurulan bir Next.js adresi virgüllü olur.

Yuva adları kural gibi katlanır: küçük harf, boşluk ve alt çizgi tire olur (Urun_Aciklama → urun-aciklama); katlandıktan sonra geçerli olmayan ad (64 karakter, harf-rakam-tire, uçlarda tire yok) atılır. Şablonunuza panelin Saved as (Kaydedilecek hâli) satırındaki adı yazın.

Hata yerine boş yanıt. code boş, 100 karakterden uzun ya da slots boşsa uç 400 vermez: her istenen yuvayı boş bırakan bir 200 ve Cache-Control: no-store döner. Çağıran şablon, kendi sayfa modelinde ne varsa onu yeni okumuştur; bir veri sorunu yüzünden ürün sayfasının 400 ile kırılması istenmez, çünkü render hata durumunda sessizce boş kalacak şekilde tasarlanmıştır.

Yanıt

{
  "v": "m3k1p.4",
  "mode": "anonymous",
  "slots": {
    "urun-aciklama-alti": {
      "html": "<div data-selwise-root=\"true\" data-selwise-entity-type=\"enrichment\" data-selwise-entity-id=\"8f3a2b7c-...\" data-selwise-ssr=\"1\" data-selwise-ssr-v=\"m3k1p.4\" data-selwise-ssr-slot=\"urun-aciklama-alti\"><div data-selwise-enrichment=\"5d1e9c0a...\">...</div></div>",
      "assignmentIds": ["8f3a2b7c-..."]
    },
    "sepet-ustu": { "html": "", "assignmentIds": [] }
  },
  "css": "[data-selwise-enrichment=\"5d1e9c0a...\"] .spec-table{...}",
  "meta": {
    "code": "ABC-1",
    "resolved": true,
    "renderedAt": "2026-10-09T09:12:00.000Z"
  }
}

Alanların tablosu yukarıdaki uç kutusundadır. Bir şablon yazarken bilmeniz gerekenler:

  • İstenen her yuva (katlanmış adıyla) slots içinde bulunur; içeriği olmayan yuva boş dize ve boş dizi taşır. Anahtar hiç eksilmez, şablon null denetimi yazmaz.
  • Bir yuvada birden çok kural varsa HTML'leri sırayla art arda gelir; assignmentIds çizim sırasıdır.
  • meta.resolved false ise içerik yine gelir; yalnızca ürün yer tutucuları (${title}, ${price} ...) boş kalır.
  • meta.renderedAt yanıtın üretildiği andır; önbellekten dönen yanıtta eski bir an olabilir.

css alanının ayrı olması zorunlu: zenginleştirme izin listesi style etiketini yasaklar, yani markup'ın içine gömülü CSS zaten silinir. Stil blok kapsamına alınmış olduğu için head erişiminiz yoksa içeriğin yanına da basabilirsiniz.

Kök öğenin imzası

Her kuralın HTML'i tek bir kök öğeyle sarılır ve widget onu şu niteliklerden tanır; bunları değiştirmeyin ve silmeyin:

NitelikAnlamı
data-selwise-root="true"Widget'ın kendi çizdiği her öğede bulunan kök işareti
data-selwise-entity-type="enrichment"Varlığın türü
data-selwise-entity-idKuralın kimliği: widget bu kuralı bir daha çizmez
data-selwise-ssr="1"Bu kökü sunucunun yazdığını bildirir; widget çizmek yerine ölçümü devralır
data-selwise-ssr-vSunucunun yanıt aldığı sürüm damgası
data-selwise-ssr-slotKöklerin hangi yuvaya yazıldığı

İçeride her blok bir data-selwise-enrichment="<blokKimliği>" sarmalayıcısındadır; css alanındaki kurallar bu niteliğe göre kapsamlanmıştır.

Hangi kurallar döner

Yalnızca sunucuda basılabilecek ve ziyaretçiye göre değişmeyen kurallar:

DönerDönmezNeden
Nerede oluşturulur alanı Sunucu, tarayıcı yedekli (auto) ya da Yalnızca sunucu (server) olan, yuva adı dolu, etkin (başlangıç ve bitiş penceresinde) kurallarTest modundaki kurallarÖnbelleğe donan test içeriği herkese gider ve mağazadaki test bayrağı hiç sorulmaz
Tüm ziyaretçileri hedefleyen kurallar (segmentsiz, ya da segment listesi boş)Segment hedefli kurallarKişiye göre değişen bir cevaptır; paylaşılan bir önbellekte bir ziyaretçinin segmenti herkese yapıştırılır
Ürüne kod listesiyle ya da katalog koşuluyla eşleşen kurallarYalnızca tarayıcı (client) kuralları, yuva adı olmayan kurallarAdresi yoktur; yalnızca tarayıcıda yaşar

Aynı yuvaya birden çok kural düşerse sıra: Priority (Öncelik) yüksek olan önce, eşitlikte eski olan önce. When rules collide (Kurallar çakıştığında) ayarı Render only the highest-priority block olan bir kural yuvayı tek başına alır. Bu sıra, widget'ın tarayıcıda kullandığıyla aynıdır; sunucuda ve tarayıcıda aynı içerik görünür.

Önbellekleme

İki ayrı katman var ve ikisi de anlamlı:

Selwise tarafında. Yanıt (ürün kodu, yuva kümesi ve sürüm damgası anahtarlı) 5 dakika tutulur; içeriği olmayan yanıt 1 dakika, çünkü bir ürünün kural listesine yeni eklenmesi çabuk görünmelidir. Sürüm damgası anahtarın parçası olduğu için bir kuralı panelden düzenlediğinizde yeni istekler yeni içeriği alır.

Sizin tarafınızda. Yanıt şu başlıklarla gelir:

Cache-Control: public, max-age=60, stale-while-revalidate=600
ETag: W/"..."
Vary: x-selwise-api-key

ETag'i saklarsanız tekrar render bir gövde yerine 304 maliyetine iner (If-None-Match gönderin). ETag içerikten (sürüm, yuvalar, css) türetilir, renderedAt'ten değil: bayt bayt aynı içerik için yeni bir doğrulayıcı çıkmaz. max-age kasten kısa: bu HTML sizin sayfanızın içine girdiği anda bizim önbelleğimizin ulaşamayacağı bir yere geçer ve panelde yapılan bir düzenleme oraya yetişemez. Vary: x-selwise-api-key paylaşılan bir önbelleğin bir merchant'ın içeriğini başkasının anahtarına sunmasını engeller.

Bir ürün başına bir upstream çağrısı yeter: sayfa önbelleğiniz ya da süreç içi önbellek 60 saniye tutarsa yoğun bir ürün sayfası dakikada bir Selwise çağrısına iner.

Zaman aşımı ve yedek davranışı

Çağrıyı kısa bir zaman aşımıyla yapın (önerilen 400 ms; sağlıklı bir çağrının kat kat üstü, alışverişçinin fark etmeyeceği kadar kısa) ve hatayı yutun. Ürün sayfanız bizim yüzümüzden beklememeli.

Bozulma merdiveni şu sırayla iner ve hiçbir basamak diğerini beklemez:

SSR başarılı        → içerik ilk baytta, tarayıcı botu görür, widget ölçümü devralır
SSR başarısız       → şablon hiçbir şey basmaz → kural "Sunucu, tarayıcı yedekli" ise widget tarayıcıda basar
widget de yoksa     → sayfa mağazanın kendi hâliyle çıkar, hiçbir şey kırılmaz

Yani istemcinizi şöyle yazın: zaman aşımı, ağ hatası, 4xx, 5xx ve bozuk JSON hepsi boş dize döner. 404 ve 403 kalıcı hatalardır (yanlış anahtar, yanlış siteKey, SSR'ı olmayan kanal); onları günlüğe uyarı olarak yazın ve alarm kurun, çünkü bu durumda içerik hiç gelmez ve sayfa yine de başarılı görünür.

Boyut sınırı

Bir yanıtın markup'ı en çok 256 KB taşır. Sınıra ulaşıldığında yanıt kural sınırında kesilir: ilk kurallar gelir, sınırı aşan kural (parçası değil, tamamı) atlanır; sunucu günlüğüne bir uyarı düşer. Bu HTML sizin sayfanızın içinde her ürün görüntülemesinde taşındığı için sınır bir formalite değildir.

Hatalar

DurumNe zaman
200Her durumda içerik yoksa bile; slots.*.html boş olabilir
304If-None-Match ETag ile eşleşti, gövde yok
401Başlık yok
403Anahtar geçersiz/iptal/kapsam yok, web kanalı değil, hesap teslimatı kapalı
404siteKey yok
429Anahtar başına dakikada 6000 aşıldı
5xxSelwise tarafında geçici hata; boş dize basın, bir sonraki ziyarette yeniden deneyin

Hiçbir 400 yoktur: geçersiz parametreler boş yanıt verir.

Arama ve öneriler

Arama ve öneri uçları da sunucudan çağrılabilir; ikisi de JSON döndürür ve markup üretmez: liste şablonu sizin tasarımınızdır, bizim basacağımız markup orada yabancı durur. Bkz. Arama API'si, Öneri API'si. Öneri şeritlerinin sunucuda HTML olarak oluşturulması bugün yoktur; kampanya ve widget'lar da sunucuda basılmaz (geri sayım, sepet ve ziyaretçi sayısı gibi içerikler zamana ve ziyaretçiye göre değişir ve bir sayfa önbelleği tek bir cevabı herkese donduracağından bilerek dışarıda).

Son güncelleme: 21 Ekim 2026