Server-side rendering (SSR)
MarkdownYorumların sayfanın ilk yanıtında, arama motorlarının okuyabileceği biçimde yer alması.
Server-side rendering (SSR) kullanıldığında mağazanızın sunucusu, sayfayı oluştururken yorumların hazır HTML’ini Sayproof’tan alır ve sayfaya ekler. Tarayıcı sayfayı açtığında yorumlar sayfada zaten bulunur; script yüklendiğinde aynı içeriği yeni bir ağ isteği yapmadan devralır ve etkileşimi başlatır.
Sağladığı yararlar:
- Yorum metni sayfa kaynağında yer alır; arama motorları ve bağlantı önizlemeleri içeriği script’i beklemeden görür.
- Sayfa, ekrandaki değerlerle birebir aynı
ReviewveAggregateRatingyapılandırılmış verisini (JSON-LD) içerir. - Script yüklenene kadar yorum bölümü boş kalmaz ve sayfa düzeni kaymaz. HTML, yorum yazma alanını da içerir: alan
data-review-gate-state="pending"durumunda ve düğmesi pasif olarak gelir, script devraldığında etkinleşir. Yıldız satırları, filtreler, arama, sıralama, oy düğmeleri ve fotoğraflar da script devraldığında çalışır; “Devamını oku” düğmesi gizli gelir; script metnin yüksekliğini ölçer ve metin 4 satırı aşıyorsa düğmeyi gösterir.
Bu yöntem her programlama dilinde ve framework’te uygulanabilir; sunucunuzun bir HTTP isteği yapıp dönen HTML’i sayfaya ekleyebilmesi yeterlidir. Next.js için ayrı bir sayfa bulunur: Next.js.
Gerekenler
Bölüm başlığı “Gerekenler”- Bir sunucu anahtarı (panelde Kanallar › Anahtarlar). Sipariş gönderen sisteminizin kullandığı anahtarla aynı anahtar olabilir. Anahtar yalnızca sunucuda tutulur. Bkz. Kanal, alan adı ve anahtarlar.
- Kanal kodu; örneğin
web. - Sayfada Sayproof script’i. SSR ile hazırlanan HTML’i etkileşimli hâle getiren script’tir.
GET https://api.sayproof.example/v1/ssr?product=URUN-KODU&channel=web&lang=tr&name=Ürün%20adıAuthorization: Bearer SUNUCU-ANAHTARINIZ| Parametre | Zorunlu | Açıklama |
|---|---|---|
product |
Evet | Ürün kodu (en fazla 128 karakter); container’daki data-review-product değeriyle aynı. |
channel |
Evet | Kanal kodu. |
scope |
Hayır | variant (varsayılan) ya da group. |
lang |
Hayır | tr ya da en. Belirtilmezse ya da desteklenmiyorsa kanalın dili kullanılır. |
name |
Hayır | Ürün adı. Yapılandırılmış veride ürün adı olarak kullanılır. |
sort |
Hayır | Pazarın izin verdiği sıralamalardan biri. Belirtilmezse varsayılan sıralama (tarih) kullanılır. İzin verilmeyen bir değer 400 yanıtı alır. |
style |
Hayır | cards ya da sidebar: HTML’in hangi düzenle hazırlanacağı. Belirtilmezse kanalın panelde seçilen düzeni kullanılır. Container’da data-review-style kullanıyorsanız aynı değeri gönderin. |
theme |
Hayır | warm, trust, editorial, minimal, soft, bold, natural ya da night: HTML’in hangi hazır tasarımla hazırlanacağı. Belirtilmezse kanalın panelde seçilen tasarımı kullanılır. Container’da data-review-theme kullanıyorsanız aynı değeri gönderin. |
{ "html": "<section data-review-root data-review-ssr …>…</section>", "state": { "reviews": [], "aggregate": {}, "core": {}, "words": {} }, "state_script": "<script type=\"application/json\" data-review-state>…</script>", "components": [ { "name": "summary", "where": "server" }, { "name": "list", "where": "server" }, { "name": "form", "where": "client" } ], "json_ld": { "@type": "Product", "aggregateRating": {}, "review": [] }, "json_ld_script": "{…}", "total": 200, "version": "3", "etag": "W/\"…\"", "stylesheet": "https://api.sayproof.example/storefront/sayproof.css"}| Alan | Kullanımı |
|---|---|
html |
Container’ın içine olduğu gibi eklenecek HTML. Sunucu tarafında escape edilmiş ve stil kapsamı tanımlanmıştır. Yapısı script’in oluşturduğu bileşenle aynıdır; öğeler için: DOM attribute’ları. |
state |
Aynı içeriğin veri hâli: yorumlar, özet, sıralama, zorunlu öğeler ve arayüz metinleri. Alanlar yorum listesi yanıtıyla aynıdır. |
state_script |
Yalnızca state verisini taşıyan etiket. Headless kullanımda html yerine bu etiket kullanılır. |
components |
Bileşenler ve nerede oluşturuldukları. where değeri server olanlar (özet ve yorum listesi) html içinde hazır gelir; client olan yorum formu sunucuda oluşturulmaz, müşteri formu açtığında tarayıcıdaki script tarafından oluşturulur. Bu yüzden SSR kullanılan sayfaya da script etiketi eklenir; eklenmezse yorumlar görünür ama form açılmaz. |
json_ld |
Yapılandırılmış veri nesnesi. |
json_ld_script |
Aynı nesnenin <script> etiketi içine güvenle yazılabilecek hâli. |
stylesheet |
Bileşenin temel stillerini taşıyan CSS dosyasının adresi. html içindeki kök öğenin (data-review-root) ilk alt öğesi bu dosyaya giden bir <link rel="stylesheet" data-review-stylesheet> etiketidir; böylece yorumlar script yüklenmeden biçimli görünür. İsterseniz aynı adresi sayfanın <head> bölümüne de ekleyebilirsiniz. |
Sayfaya ekleme
Bölüm başlığı “Sayfaya ekleme”html alanını container’ın içine ekleyin ve sayfaya script’i ekleyin. Yanıt alınamadıysa container boş bırakılır:
const container = `<div data-review-mount data-review-product="URUN-KODU" data-review-product-name="Ürün adı">${reviews?.html ?? ""}</div>`;
const script = `<script type="module" src="https://cdn.sayproof.example/sayproof.js" data-review-site-key="SITE-ANAHTARINIZ" data-review-base="https://api.sayproof.example" data-review-locale="tr"></script>`;Yapılandırılmış veri (JSON-LD)
Bölüm başlığı “Yapılandırılmış veri (JSON-LD)”-
Sayfanızda ürün için bir
ProductJSON-LD’si yoksajson_ld_scriptdeğerini olduğu gibi ekleyin:<script type="application/ld+json">…json_ld_script…</script> -
Sayfanızda zaten bir
ProductJSON-LD’si varsa ikinci birProducteklemeyin.json_ld.aggregateRatingvejson_ld.reviewalanlarını kendi nesnenize ekleyin.
Nesneyi kendiniz metne dönüştürüyorsanız <, >, &, U+2028 ve U+2029 karakterlerini \uXXXX biçiminde escape edin: örneğin < karakteri \u003c olur. Yorum metinleri müşteriler tarafından yazılır; düz JSON.stringify sonucu, </script> içeren bir yorum nedeniyle sayfanızı bozabilir.
function jsonLdScript(value) { return JSON.stringify(value).replace(/[<>&\u2028\u2029]/g, (character) => `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}` );}
const product = { "@context": "https://schema.org", "@type": "Product", name, sku };if (reviews?.json_ld?.aggregateRating) { product.aggregateRating = reviews.json_ld.aggregateRating; product.review = reviews.json_ld.review ?? [];}const markup = `<script type="application/ld+json">${jsonLdScript(product)}</script>`;Arama motorları ve yapay zekâ aramaları
Bölüm başlığı “Arama motorları ve yapay zekâ aramaları”Arama motorları ve yapay zekâ arama araçları sayfanın sunucudan gelen HTML’ini okur; betikle sonradan çizilen yorumları her zaman görmez. Sunucuda hazırlanan yorumlar sayfanın ilk HTML’inde yer alır:
- Satın alması doğrulanan yorumda Doğrulanmış alıcı ibaresi görünür metindir; yalnız simge ya da renk değildir.
- JSON-LD yalnız schema.org’un
Review,RatingveAggregateRatingalanlarını kullanır. Satın alma doğrulaması gibi schema.org’da karşılığı olmayan bir bilgi yapılandırılmış veriye eklenmez, görünür metinde kalır. - Diğer pazarlardan gelen yorumlar listede kaynak pazarıyla görünür, ama
reviewdizisine veaggregateRatingdeğerine girmez.
Zaman aşımı ve hata
Bölüm başlığı “Zaman aşımı ve hata”Sayproof’a gönderilen istek sayfanızın açılmasını hiçbir zaman geciktirmemelidir.
- İsteğe kısa bir zaman aşımı verin; 1,5 saniye önerilir.
- Zaman aşımında ya da
200dışındaki yanıtlarda container’ı boş bırakın. Bu durumda script yorumları tarayıcıda kendisi getirir.
| Yanıt | Anlamı |
|---|---|
403 refused / scope_missing |
Anahtarın sayfayı sunucuda hazırlama izni yok (panelden oluşturulan sunucu anahtarlarında bu izin her zaman vardır). Panelden yeni bir sunucu anahtarı oluşturun. |
403 refused / unknown_channel |
Kanal kodu yanlış ya da kanal kapalı. |
409 refused / no_site_key |
Kanalın kullanımda bir site anahtarı yok ve kanalın yöntem beyanı için kendi sayfanız bağlı değil; yöntem beyanı bağlantısı oluşturulamadığı için yanıt verilmez. |
400 invalid / product |
Ürün kodu eksik ya da çok uzun. |
400 sort_not_allowed |
Sıralama, pazarın izin verilen listesinde değil. |
400 invalid / style |
Düzen cards ya da sidebar değil. |
400 invalid / theme |
Tasarım warm, trust, editorial, minimal, soft, bold, natural ya da night değil. |
429 rate_limited |
Anahtar başına 5 dakikada 6.000 istek sınırı aşıldı. |
Önbellek
Bölüm başlığı “Önbellek”Sunucu anahtarıyla gönderilen isteğin yanıtı Cache-Control: private, max-age=60 ve ETag header’larını taşır; aynı endpoint’e tarayıcıdan site anahtarıyla istek gönderilirse Cache-Control: public, max-age=60 döner. İsteğe son alınan etag değeriyle If-None-Match header’ı eklenirse, içerik değişmediğinde body içermeyen bir 304 yanıtı döner. Kendi tarafınızda en fazla 60 saniyelik önbellek kullanabilirsiniz; yeni yayınlanan bir yorum en geç bu süre sonunda sayfada görünür.
Örnekler
Bölüm başlığı “Örnekler”Tüm örnekler aynı işi yapar: isteği zaman aşımıyla gönderir ve hata durumunda null döndürür.
Node.js
Bölüm başlığı “Node.js”export async function sayproofReviews({ product, name, language }) { const query = new URLSearchParams({ product, name, lang: language, channel: process.env.SAYPROOF_CHANNEL, }); try { const answer = await fetch(`${process.env.SAYPROOF_BASE}/v1/ssr?${query}`, { headers: { Authorization: `Bearer ${process.env.SAYPROOF_SSR_KEY}` }, signal: AbortSignal.timeout(1500), }); return answer.ok ? await answer.json() : null; } catch { return null; }}Python (Django, Flask)
Bölüm başlığı “Python (Django, Flask)”import os
import requests
def sayproof_reviews(product, name, language): try: answer = requests.get( f"{os.environ['SAYPROOF_BASE']}/v1/ssr", params={ "product": product, "name": name, "lang": language, "channel": os.environ["SAYPROOF_CHANNEL"], }, headers={"Authorization": f"Bearer {os.environ['SAYPROOF_SSR_KEY']}"}, timeout=1.5, ) except requests.RequestException: return None return answer.json() if answer.ok else NoneJinja ya da Django template’inde HTML’i escape etmeden ekleyin:
<div data-review-mount data-review-product="{{ product.sku }}" data-review-product-name="{{ product.name }}"> {% if reviews %}{{ reviews.html|safe }}{% endif %}</div>{% if reviews %}<script type="application/ld+json">{{ reviews.json_ld_script|safe }}</script>{% endif %}function sayproof_reviews(string $product, string $name, string $language): ?array{ $query = http_build_query([ 'product' => $product, 'name' => $name, 'lang' => $language, 'channel' => getenv('SAYPROOF_CHANNEL'), ]); $curl = curl_init(getenv('SAYPROOF_BASE') . '/v1/ssr?' . $query); curl_setopt_array($curl, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT_MS => 1500, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('SAYPROOF_SSR_KEY')], ]); $body = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); curl_close($curl); return ($body !== false && $status === 200) ? json_decode($body, true) : null;}Varyant değişikliği
Bölüm başlığı “Varyant değişikliği”Kullanıcı sayfada başka bir varyant seçtiğinde container’ın data-review-product değerini güncelleyin; script yeni ürünün yorumlarını kendisi getirir. Sayfa sunucudan yeniden yükleniyorsa (örneğin her varyantın ayrı bir adresi varsa) yeni html gelir ve script bu içeriği devralır.