Sunucu Taraflı Render

İçeriği HTML içinde yayınlama, arama motoru görünürlüğü

Zenginleştirme içeriğini tarayıcıda değil, kendi sunucunuzda oluşturabilirsiniz. İçerik o zaman sayfanın HTML'inin içinde doğar; widget onu tanır, bir daha basmaz ve yalnızca gösterim ile tıklama ölçümünü devralır.

Bu sayfa neyin ne olduğunu, ne zaman kullanılacağını, mimariyi ve panel ayarını anlatır. HTTP ayrıntısı için Sunucu Taraflı Render API, kopyalanıp yapıştırılacak kod için Sunucu Taraflı Render Örnekleri sayfalarına bakın.

Panelde nerede

Sol menüde Kişiselleştirme → Ürün Zenginleştirme (Personalization → Product Enrichment) → bir kuralı açın (ya da New rule) → Rules (Kurallar) adımı → Where it goes (Nereye yerleşir) bölümü. Orada Where it renders (Nerede oluşturulur) seçimi ve seçime bağlı Slot name (Yuva adı) alanı bulunur. Türkçe arayüzde Nerede oluşturulur ve Yuva adı. Yuva adı alanının altında, şablonunuza yazacağınız satır hazır gösterilir.

Bu ayar yalnızca web kanalında vardır: bir uygulama kanalı sayfa şablonu taşımaz ve onun karşılığı Mobil Uygulamada Zenginleştirme'dir.

Ne zaman kullanılır

Selwise'in normal yolu şudur: sayfa yüklenir, widget yapılandırmayı çeker, zenginleştirme parçasını indirir, içeriği ister, sonra sayfaya yazar. Dört ardışık ağ adımı. Bir alışverişçi bunu fark etmez, yer önceden rezerve edildiği için sayfa da kaymaz. Bir tarayıcı botu için tablo farklıdır:

İstemciJavaScript çalıştırır mıİçeriği görür mü
GooglebotEvet, ama ikinci bir geçişteGenelde evet, gecikmeli
Bingbot, YandexKısıtlıGüvenilmez
GPTBot, ClaudeBot, PerplexityBotHayırHayır
WhatsApp, Slack, Facebook önizlemeHayırHayır

Zenginleştirmenin ürünü tam olarak ürün sayfasındaki okunabilir metin. O metnin JavaScript arkasında kalması, alt üç satırdaki istemciler için hiç var olmaması demek; ve ürün bilgisinin yapay zekâ cevaplarına girmesi organik trafikle yarışan bir kanal hâline geldi. İkinci, daha küçük kazanç: içerik ilk boyamada geldiği için blok içindeki görsel de daha erken istenir.

Kullanmayın:

  • Sayfa şablonunuza sunucu kodu yazamıyorsanız (hosted bir platformun kapalı tema alanı): bu yol bir uygulama sunucusu ister. Yalnızca tarayıcı ile devam edin.
  • İçeriği kişiye göre değişiyorsa (segment hedefli): bir ziyaretçinin segmenti sayfa önbelleğiyle herkese yapışır, bkz. Kişiye bağlı içerik sunucuda basılmaz.
  • Sayfanız tek sayfa uygulamasıysa ve ürün sayfasına tam sayfa yüklemesiyle girilmiyorsa: bkz. Tek sayfa uygulamalarında.

Mimari

Sunucu taraflı render'da üç taraf vardır ve kimin kimi çağırdığı önemlidir:

 Tarayıcı / bot                 Sizin uygulama sunucunuz                     Selwise
 ─────────────                  ────────────────────────                     ───────
 GET /urun/abc-1  ───────────▶  şablon yuvayı çağırır
                                  GET .../ssr/enrichments?code=…&slots=…  ──▶  kuralı çözer,
                                  x-selwise-api-key: swpk_live_…                temizler, kapsamlar
                                  (400 ms zaman aşımı, hata = boş)         ◀──  { slots, css, v }
                                şablon css + html'i basar
 HTML (içerik içinde) ◀───────
 client.js yüklenir ────────────────────────────────────────────────────────▶  GET .../config
                                                                           ◀──  enrichment.v
 widget: kök etiketinde data-selwise-ssr-v == v ?
   evet  → kuralı "çizilmiş" say, ölçümü bağla, bir daha basma
   hayır → kural "tarayıcı yedekli" ise tarayıcıdan taze çiz, bayat kökü sonra kaldır;
           "yalnızca sunucu" ise bayat kökü koru

Anahtar noktalar:

  • API çağrısını sizin sunucunuz yapar, tarayıcı değil. Çağrı site API anahtarı taşır ve anahtar sunucudan çıkmaz.
  • Selwise'in önbelleği ve sizin önbelleğiniz ayrıdır. Sizin sayfa önbelleğinize (CDN, Varnish, Next.js veri önbelleği) Selwise dokunamaz; panelde bir kuralı düzenlediğinizde o önbelleğe yazılmış sayfa eski içeriği taşımaya devam eder. Bunu kapatan şey damga mekanizmasıdır (aşağıda).
  • Çıktı ziyaretçiye göre değişmez (mode: anonymous): bu, sayfanın herkese aynı önbellekten verilebilmesinin ön koşuludur.

Nerede oluşturulur: üç seçenek

SeçenekNe yaparNe zaman
Browser only (Yalnızca tarayıcı)Bugünkü davranış. Varsayılan ve mevcut tüm kurallar böyleSunucu tarafında geliştirme yapamıyorsanız ya da kural segment hedefliyse
Server, with browser fallback (Sunucu, tarayıcı yedekli)Şablonunuz isterse sunucuda, istemezse tarayıcıdaÖnerilen. Sunucu çağrısı başarısız olsa bile içerik yine görünür
Server only (Yalnızca sunucu)Kural widget açılış paketinden tamamen çıkarYalnızca widget script'ini hiç yüklemeyen bir kurulumda

Sunucu, tarayıcı yedekli ile başlayın

Bu seçenek bir güvenlik ağı bırakır: sunucu çağrınız zaman aşımına uğrarsa, hata verirse veya şablonunuz o yuvayı henüz basmıyorsa widget yuvayı eskisi gibi doldurur. Yalnızca sunucu seçeneğinde böyle bir yedek yoktur; şablonunuz basmazsa içerik hiçbir yerde görünmez.

Yuva adı

Sunucu tarafında hedef bir CSS seçici değil, sizin verdiğiniz bir addır. Sunucunuzun bir DOM'u yok, bir seçiciyi çözemez; şablonu siz yazıyorsunuz, yuvayı siz koyuyorsunuz ve orada isim seçiciden hem daha sağlam hem daha okunur. Tema güncellemesi bir sınıf adını değiştirdiğinde yuva adı yerinde kalır.

Ad kuralı: küçük harf, rakam ve tek tire; en çok 64 karakter; tireyle başlayıp bitemez. urun-aciklama-alti, sepet-ustu, beden-tablosu-alani. Büyük harf, boşluk veya alt çizgi yazarsanız panel bunları katlar ve Saved as (Kaydedilecek hâli) satırında kaydedeceği hâli size gösterir; şablonunuza yazacağınız ad o katlanmış hâldir.

Kural iki adres taşır

Sunucu tarafı açık bir kural CSS seçicisini de korur. Seçici tarayıcı yolunun adresi, yuva adı sunucu yolunun adresi. İkisi aynı kuralın iki adresidir; biri diğerinin yerine geçmez. Aynı yuva adını birden çok kurala verirseniz kurallar o yuva için yarışır: önce Priority (Öncelik) yüksek olan, eşitlikte eski olan gelir; When rules collide (Kurallar çakıştığında) ayarı tek bloğa ayarlıysa kazanan yuvayı tek başına alır.

Kurulum

  1. Kuralı hazırlayın. Rules adımında Where it renders için Server, with browser fallback'ı seçin ve bir Slot name verin.
  2. API anahtarı alın. Channels ekranında kanalınızın satırındaki ⋮ menüsünden API keys'i açın, Purpose olarak Server-side rendering seçin ve anahtarı oluşturun. Anahtar swpk_live_ ile başlar ve yalnızca bir kez gösterilir. Bkz. API Anahtarları.
  3. Sunucu ortamınıza ekleyin. SELWISE_SITE_KEY ve SELWISE_SSR_API_KEY iki ortam değişkeni; ikisi de tarayıcıya açılmaz (NEXT_PUBLIC_ önekli bir değişken olmaz).
  4. Şablonunuza ekleyin. PHP, Node, Next.js ve Django örnekleri: Sunucu Taraflı Render Örnekleri. Akinon için hazır parçalar: Akinon. Ham HTTP sözleşmesi: Sunucu Taraflı Render API.
  5. Doğrulayın. Aşağıdaki Doğrulama bölümü.

API anahtarı tarayıcıya çıkmaz

Bu çağrı sunucudan sunucuya yapılır. Anahtarı bir şablona, bir script bloğuna veya NEXT_PUBLIC_ önekli bir değişkene yazmayın. Sızan bir anahtarı aynı ekrandan döndürebilirsiniz (Rotate); eski anahtar anında geçersiz olur. ssr_read salt okunurdur: sızması hiçbir şey yazamaz, ama sizin adınıza istek yapılabilir ve hız sınırınızı tüketebilir.

Hangi içerik sunucuya gelir

Sunucu yanıtı yalnızca ziyaretçiye göre değişmeyen kuralları taşır. Bir kural şu koşulların hepsini sağlamıyorsa sunucuda görünmez (ama Server, with browser fallback ise tarayıcıda yine görünür):

  • Where it renders ayarı Browser only değil, ve bir Slot name dolu.
  • Etkin (Active), başlangıç ve bitiş penceresinin içinde.
  • Test mode kapalı.
  • Segment hedefli değil (tüm ziyaretçileri hedefliyor).
  • Ürüne eşleşiyor: kod listesinde, ya da katalog koşuluna uyuyor, ya da All products.

Kişiye bağlı içerik sunucuda basılmaz

Bir segmentle hedeflenmiş kural, kişiye göre değişen bir cevaptır. Sunucuda oluşturulmuş sayfa ise genelde bir önbelleğe girer ve o önbellek herkese servis edilir; yani bir ziyaretçinin segmenti bütün ziyaretçilere yapıştırılır. Satın alma geçmişine dayalı bir segmentte bu yalnızca hata değil veri sızıntısıdır. Bu yüzden panel, segment hedefli bir kuralda sunucu seçeneklerini kabul etmez. Aynı şekilde test modundaki kurallar sunucu yanıtına girmez: önbelleğe donan test içeriği herkese gider ve mağazadaki test bayrağı hiç sorulmaz. Bir test kuralını denemek için Browser only ya da Server, with browser fallback seçip test modunu tarayıcıda açın: Önizleme ve Test Modu.

Aynı sebeple geri sayım, sepet sayacı ve ziyaretçi sayacı gibi zamana ve kişiye göre değişen kampanyalar ve widget'lar hiçbir zaman sunucuda basılmaz.

Widget sayfayı nasıl devralır

Sunucuda basılmış içeriği widget sayfada bulduğunda şunu yapar, bu sırayla:

  1. Bayat kökü yeniler. Her sunucu kökü, oluşturulduğu andaki içerik sürümünü taşır (data-selwise-ssr-v). Widget bunu config yanıtından aldığı güncel sürümle karşılaştırır; uyuşmuyorsa kural Server, with browser fallback ise içeriği tarayıcıdan taze olarak basar ve ancak o zaman bayat kökü kaldırır. Kural Server only ise tarayıcı yolu olmadığından bayat kök sayfada kalır ve ölçümü bağlanır; içerik, sayfa önbelleğiniz yenilenince güncellenir.
  2. Kalanını sahiplenir. Kökteki kural kimliği (data-selwise-entity-id) "çizilmiş kurallar" listesine yazılır: o kural bir daha getirilmez, çizilmez, yerleştirilmez. İçerik hiçbir zaman iki kez görünmez.
  3. Yer ayırmaz. İçerik ilk boyamada yerinde durduğu için yanına yükseklik rezerve etmek ikinci bir boşluk açardı.
  4. Ölçümü bağlar. Görünürlük gözlemcisi ve tıklama dinleyicisi köke bağlanır; gösterim ve tıklama sayıları tarayıcıda çizilen blokla aynı akar.

Widget script'i yüklenmemişse (ya da config isteği başarısızsa) hiçbir şey kaldırılmaz: eksik bir sürümü "bayat" saymak, kendi isteğimizin başarısızlığı yüzünden sizin içeriğinizi silmek olurdu.

Sürüm damgası tüm site içindir

Damga sitedeki herhangi bir kuralın ya da bloğun değişmesiyle değişir; yalnızca sayfadaki kuralın değil. Önbelleğinizdeki bir ürün sayfası, siteniz başka bir ürün için yapılan bir düzenlemeden sonra widget'a "bayat" görünür. Server, with browser fallback kuralında bu sorun değildir: tarayıcı içeriği taze çizer ve bayat kopyayı kaldırır. Server only kuralında ise tarayıcı yolu yoktur; içerik kaybolmaz ama sayfa önbelleğiniz yenilenene kadar önbellekteki hâliyle görünür. Sayfa önbelleğinizin ömrünü kısa tutun (en çok birkaç saat).

Tarayıcı botları widget'ı çalıştırmadığı için bu düzeltmeyi görmez: bot, sayfa önbelleğinizde ne varsa onu okur. Bu yüzden önbelleğinizi makul tutmak yine sizin sorumluluğunuzdadır.

Tek sayfa uygulamalarında (SPA)

Mağazanız sayfa yenilemeden gezinen bir uygulamaysa (PZ Next gibi), widget her URL değişiminde önceki ürünün içeriğini sayfadan temizler; çünkü sunucuda oluşturulmuş blok o eski ürüne aittir. Ardından yeni ürünün içeriğini normal yoldan basar.

Server, with browser fallback seçeneğinde bu görünmez: içerik tarayıcı yolundan gelir. Server only seçeneğinde ise kuralın tarayıcı yolu yoktur, dolayısıyla içerik bir sonraki tam sayfa yüklemesine kadar görünmez. Arama motoru tarafında kayıp yoktur: tarayıcı botları uygulama içi gezinme yapmaz, her adresi baştan yükler. Yine de bir SPA'da Server only seçeneğini kullanmayın.

Ölçüm

Gösterim ve tıklama sayıları değişmez. Widget sunucuda oluşturulmuş bloğu tanır, yeniden basmaz ama görünürlük gözlemcisini ve tıklama dinleyicisini ona bağlar; rapor eskisi gibi akar. Tek istisna widget script'ini hiç yüklemeyen bir kurulumdur: orada tarayıcıda çalışan hiçbir şey olmadığı için gösterim de gelmez. İçerik canlıdır, panel 0 gösterir.

Doğrulama

JavaScript çalıştırmayan bir istemciyle sayfayı çekin; içerik HTML'in içinde olmalı:

# 1. İçerik ilk bayttaki HTML'de mi? (kök sayısı sıfırdan büyük olmalı)
curl -s https://magazaniz.com/urun/abc-1 | grep -o 'data-selwise-ssr="1"' | wc -l

# 2. Kökün sürüm damgası ve yuvası
curl -s https://magazaniz.com/urun/abc-1 | grep -o 'data-selwise-ssr-v="[^"]*" data-selwise-ssr-slot="[^"]*"'

# 3. Bir yapay zekâ botu gibi: kullanıcı aracısını değiştirin, içerikten bir cümle arayın
curl -s -A "GPTBot/1.0" https://magazaniz.com/urun/abc-1 | grep -c "kumaş bakım"

Sonuç sıfırdan büyükse içerik HTML'in içinde. Tarayıcıda şunları da kontrol edin:

  1. Sayfa kaynağını görüntüleyin (view-source:; DevTools'taki Elements değil, çünkü o JavaScript sonrası görünümdür). Kök öğeler orada olmalı.
  2. DevTools Elements içinde [data-selwise-ssr="1"] aratın: yuva başına bir kök olmalı. İki kök varsa içerik iki kez basılmıştır (aşağıda "İçerik iki kez görünüyor").
  3. Kökün data-selwise-ssr-v değeri, Network sekmesindeki config yanıtının enrichment.v değeriyle aynı olmalı. Farklıysa sayfanız önbellekte bayat; widget kural tarayıcı yedekliyse taze içeriği basıp bayat kökü kaldırır, yalnızca sunucu kuralında kökü korur.
  4. SSR çağrısının kendisi sunucudan yapıldığı için tarayıcı Network sekmesinde görünmez. Anahtarı ve yanıtı kendi makinenizden deneyin:
curl -i "https://api.selwise.com/api/v1/public/sites/SITE_KEY/ssr/enrichments?code=ABC-1&slots=urun-aciklama-alti" \
  -H "x-selwise-api-key: swpk_live_..."

200, Cache-Control: public, max-age=60, stale-while-revalidate=600, bir ETag ve slots.urun-aciklama-alti.html dolu olmalı. html boşsa: kural segment hedefli, test modunda, Browser only, yuva adı farklı, ürün koduna eşleşmiyor ya da kural etkin değil.

Sorun giderme

BelirtiSebep
curl çıktısında data-selwise-ssr yokŞablon yuvayı basmıyor, ad uyuşmuyor, anahtar yok/yanlış, ürün kodu kuralla eşleşmiyor ya da çağrı zaman aşımına uğruyor. Parçalar fail-open yazıldığı için hata sayfayı bozmaz, sessizce boş döner; sunucu günlüğünüzde SSR çağrısının durum kodunu arayın
API doğrudan 403Anahtarın amacı yanlış (yalnızca Mobile app anahtarı bu uca girmez), anahtar iptal edilmiş ya da kanal bir uygulama kanalı
API 401x-selwise-api-key başlığı gitmiyor (proxy sildi, ortam değişkeni boş)
İçerik iki kez görünüyorDönen HTML'i kendi sanitizer'ınızdan geçirmiş olabilirsiniz: genel amaçlı bir sanitizer data-selwise nitelikleri siler, widget bloğu tanıyamaz ve ikinci bir kopya basar. Ya da şablonda yuva iki kez çağrılıyor
Sunucuda hiç, tarayıcıda varKural segment hedefli veya test modunda. İkisi de sunucu yanıtına bilinçli olarak girmez
Sunucuda var, sonra kayboluyorSayfa önbelleğinizdeki damga bayat ve kural Server only: widget kökü sildi, geri çizecek tarayıcı yolu yok. Kuralı Server, with browser fallback yapın
Stil uygulanmamışYanıtın CSS'i ayrı bir alanda gelir ve sayfaya bir kez basılması gerekir. Hazır parçalar bunu kendisi yapar
İçerik eski kalıyorÖnbellek zinciri: sizin sayfa önbelleğiniz (bizim 60 saniyemizden uzun) ya da kendi süreç önbelleğiniz. Önbelleğin ömrünü kısaltın
Sayfa yavaşladıZaman aşımı çok uzun ya da çağrı önbelleksiz. 400 ms zaman aşımı koyun ve yanıtı 60 saniye tutun

Güvenlik

  • Anahtar yalnızca sunucuda. Şablona, istemci paketine, tarayıcıya sızdırmayın.
  • İçeriği kendiniz temizlemeyin ve değiştirmeyin. Yanıt zaten yer tutucuları HTML kaçışıyla doldurulmuş, izin listesine göre temizlenmiş ve CSS'i kapsamlanmış hâlde gelir. Genel amaçlı bir temizleyici ya da "güzelleştirici" data-selwise-* niteliklerini siler. Şablon motorunuzun kaçışını yalnızca bu çıktı için kapatın (|safe, <%-, dangerouslySetInnerHTML) ve sayfanın başka hiçbir veri parçası için kapatmayın.
  • Ziyaretçi verisi göndermeyin. İstekte çerez, oturum kimliği, e-posta ya da başka kişisel veri taşımayın; çağrı yalnızca ürün kodu ve yuva adı taşır. Yanıt zaten ziyaretçiye göre değişmez.
  • Çıktıyı kişiye özel bir sayfanın içine gömüyorsanız (sepetiniz, hesabınız) sayfayı yine herkesle paylaşılan bir önbelleğe yazmayın.

Uygulamada karşılığı

Mobil uygulama kanalında SSR yoktur ve olamaz (bir uygulamayı tarayıcı botu okumaz). Aynı kurallar, aynı bloklar uygulamada yuva adıyla yerleştirilir ve SelwiseEnrichment bileşeni ya da app/enrichments ucu içeriği hazır HTML olarak verir: Mobil Uygulamada Zenginleştirme, Zenginleştirme API'si.

Sırada ne var

Son güncelleme: 22 Ekim 2026