İçeriğe geç

Next.js

Markdown

Next.js App Router kullanan bir mağazada SSR, script ve oturum açmış müşteri entegrasyonu.

Bu sayfa, SSR yönteminin Next.js App Router’daki uygulamasını anlatır. Ek paket kurulumu gerekmez; next ve react yeterlidir.

NEXT_PUBLIC_SAYPROOF_BASE=https://api.sayproof.example
NEXT_PUBLIC_SAYPROOF_SITE_KEY=SITE-ANAHTARINIZ
NEXT_PUBLIC_SAYPROOF_SCRIPT=https://cdn.sayproof.example/sayproof.js
SAYPROOF_SSR_KEY=SUNUCU-ANAHTARINIZ
SAYPROOF_CHANNEL=web
  • NEXT_PUBLIC_ önekli değerler tarayıcıya aktarılır; site anahtarı ve adresler gizli değildir.
  • Sunucu anahtarı SAYPROOF_SSR_KEY öneksiz tanımlanır ve tarayıcıya aktarılmamalıdır.
  • Sunucunuz Sayproof’a farklı bir adres üzerinden erişiyorsa (örneğin iç ağ) ayrıca SAYPROOF_BASE değişkenini tanımlayın.

Sunucu anahtarını okuyan kodu ayrı bir dosyada tutun ve dosyanın başına import "server-only" satırını ekleyin. Bir client component bu dosyayı içe aktarmaya çalışırsa build başarısız olur; böylece anahtar yanlışlıkla tarayıcı bundle’ına girmez.

import "server-only";
const base = process.env.SAYPROOF_BASE || process.env.NEXT_PUBLIC_SAYPROOF_BASE;
export async function sayproofReviews(product: string, name: string, locale: string) {
const query = new URLSearchParams({
product,
name,
lang: locale,
channel: process.env.SAYPROOF_CHANNEL ?? "web",
});
try {
const answer = await fetch(`${base}/v1/ssr?${query}`, {
headers: { Authorization: `Bearer ${process.env.SAYPROOF_SSR_KEY}` },
next: { revalidate: 60 },
signal: AbortSignal.timeout(1500),
});
return answer.ok ? await answer.json() : null;
} catch {
return null;
}
}
import Script from "next/script";
import { sayproofReviews } from "@/lib/sayproof.server";
export default async function ProductPage({ params }) {
const product = await getProduct(params.slug);
const reviews = await sayproofReviews(product.sku, product.name, params.locale);
return (
<>
<div
key={product.sku}
data-review-mount
data-review-product={product.sku}
data-review-product-name={product.name}
data-review-locale={params.locale}
suppressHydrationWarning
dangerouslySetInnerHTML={{ __html: reviews?.html ?? "" }}
/>
<Script
id="sayproof"
type="module"
strategy="afterInteractive"
crossOrigin="anonymous"
src={process.env.NEXT_PUBLIC_SAYPROOF_SCRIPT}
data-review-site-key={process.env.NEXT_PUBLIC_SAYPROOF_SITE_KEY}
data-review-base={process.env.NEXT_PUBLIC_SAYPROOF_BASE}
data-review-locale={params.locale}
/>
</>
);
}

Dikkat edilmesi gerekenler:

  • key={product.sku}: Varyant değiştiğinde React container’ı yeniden oluşturur; script yeni container’ı algılar ve bağlar.
  • suppressHydrationWarning: Container’ın içeriği script tarafından yönetildiği için React’in içerik uyuşmazlığı uyarısını kapatır.
  • dangerouslySetInnerHTML: Sunucudan gelen html burada olduğu gibi kullanılır; ikinci bir sanitizer’dan geçirilmemelidir.
  • router.refresh() sonrasında React container’ı yeni HTML ile yeniden oluşturursa script yeni içeriği algılar ve yeniden devralır.
  • Ürün grubunun tüm yorumlarını göstermek için grup kodunu kullanın, container’a data-review-scope="group" attribute’unu ekleyin ve sunucudan gönderilen isteğe de scope: "group" parametresini ekleyin.

Ürün sayfanız zaten bir Product JSON-LD’si içeriyorsa ikinci bir Product eklemeyin; puanı ve yorumları kendi nesnenize ekleyin. Escape kuralı ve örnek için: SSR › Yapılandırılmış veri.

const jsonLd = reviews?.json_ld?.aggregateRating
? { ...productJsonLd, aggregateRating: reviews.json_ld.aggregateRating, review: reviews.json_ld.review ?? [] }
: productJsonLd;
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: jsonLdScript(jsonLd) }} />

Nonce kullanıyorsanız <Script> bileşenine nonce değerini verin. Script, eklediği <style> öğelerine (#sayproof-style, #sayproof-style-form, #sayproof-style-lightbox) de aynı nonce değerini yazar.

Oturum açmış müşteri için formu sipariş numarası sormadan açmak üzere bir Route Handler yazılır ve container’a data-review-viewer="pending" attribute’u eklenir. Yöntemin tamamı ve Next.js örneği için: Oturum açmış müşteri.

Hesap bölümündeki sipariş detayı sayfasında siparişin ürünlerini sayfanın içinde değerlendirtmek için sunucu bileşeninde oturumdaki e-posta adresi ve sipariş numarasıyla Sayproof’a sorun, yanıtı data-review-order öğesinin içine yazın. sayproofOrderState fonksiyonu ve yanıtın değerleri için: Oturum açmış müşteri › Sipariş detayı sayfası. Oturum bilgisini kendi kimlik doğrulama kütüphanenizden alın; buradaki auth() yalnızca örnektir.

import Script from "next/script";
import { auth } from "@/auth";
import { sayproofOrderState } from "@/lib/sayproof-order.server";
export default async function OrderPage({ params }) {
const session = await auth();
const state = await sayproofOrderState(params.id, session?.user?.email, params.locale);
return (
<>
{state ? (
<div
key={params.id}
data-review-order={params.id}
suppressHydrationWarning
dangerouslySetInnerHTML={{ __html: state }}
/>
) : null}
<Script
id="sayproof"
type="module"
strategy="afterInteractive"
crossOrigin="anonymous"
src={process.env.NEXT_PUBLIC_SAYPROOF_SCRIPT}
data-review-site-key={process.env.NEXT_PUBLIC_SAYPROOF_SITE_KEY}
data-review-base={process.env.NEXT_PUBLIC_SAYPROOF_BASE}
data-review-locale={params.locale}
/>
</>
);
}

Yanıt kişiye özeldir ve cache: "no-store" ile alınır; sayfanın bu bölümü önbelleğe alınmaz. Yanıtta ürün yoksa öğe hiç eklenmez.

Yorum listesini kendi bileşenlerinizle gösterecekseniz container’a data-review-mode="headless" attribute’unu ekleyin ve html yerine state_script değerini kullanın. Örnek için: Headless kullanım.

Sayproof ekibi, bu sayfadaki yöntemleri hazır bileşenler olarak içeren bir Next.js kiti sağlar: sunucudan istek ve JSON-LD birleştirme, varsayılan bileşen için container, headless kullanım için container, script etiketi, oturum açmış müşteri route’u, yorum listeleme, oylama ve bildirim client’ı ile sipariş detayı sayfası için Sayproof isteği (fetchSayproofOrder()), yanıtı güvenle yazan etiket (sayproofOrderStateScript()) ve bileşen (<SayproofOrderReviews>). fetchSayproofOrder() yanıtta ürün yoksa ya da istek başarısız olursa null döndürür; <SayproofOrderReviews> bu durumda hiçbir şey çizmez. Kit mağaza reposuna kopyalanır; paket kurulumu gerektirmez ve es5 hedefli TypeScript ayarlarıyla derlenir. Kitin kullanılması zorunlu değildir; bu sayfadaki kod aynı işi görür.