Panduan Sanity SEO

Sanity stores konten sebagai JSON dan emits zero HTML — Anda frontend decides Anda SEO. rendering modes, Portable Text, SEO object, sitemaps, draft-mode noindex, JSON-LD, dan plugins.

Pertama kali diterbitkan: 27 Jun 2026 · Terakhir diperbarui: 3 Agu 2026 · Advanced
Bahasa

Sanity adalah sebuah CMS headless itu stores konten sebagai structured JSON di -nya konten Lake dan produces no HTML — so Anda frontend framework (Next.js, Astro, Remix) decides everything tentang Anda SEO. single biggest lever adalah rendering: SSG dan SSR ship complete HTML dan adalah safe; CSR adalah risky because LLM-crawler rendering contracts vary oleh provider. Portable Text adalah sebuah JSON AST, not HTML, so frontend harus serialize ini. bangun reusable SEO object di konten model, generate sitemaps dan JSON-LD programmatically, pertahankan drafts out dari indeks dengan sebuah X-Robots-Tag: noindex header, dan gunakan sanity-plugin-seo (not deprecated Yoast pane). SEO success di Sanity comes dari intentional structure, not plugins.

TL;DR — Sanity adalah konten-neutral: ini stores structured JSON di konten Lake dan emits zero HTML, so frontend’s rendering mode decides everything. SSG dan SSR ship complete HTML dan adalah safe; CSR adalah risky one because LLM crawler don’t execute JavaScript, dan Google deprecated dynamic rendering sebagai sebuah workaround. Portable Text adalah sebuah JSON AST itu frontend harus serialize. bangun reusable seo object di konten model dengan overrides (not requirements) via coalesce(), generate sitemaps dan JSON-LD programmatically dari existing fields, dan pertahankan drafts out dari indeks dengan sebuah X-Robots-Tag: noindex header pada setiap preview respons. gunakan sanity-plugin-seo — tidak pernah deprecated Yoast pane — tetapi remember “SEO success in Sanity comes from intentional structure, not plugins.” (terjemahan) “SEO success di Sanity comes dari intentional structure, not plugins.”

Sanity adalah konten storage, not sebuah publisher

sebuah berguna pertama principle: Sanity touches Anda konten, tidak pernah Anda rendering. konten Lake stores everything sebagai structured JSON, queried dengan GROQ (Sanity’s kueri language) atau REST. Sanity Studio — editing UI — adalah sebuah React single-halaman app itu biasanya lives pada -nya own .sanity.studio subdomain dan isn’t something Anda indeks. Nothing di ini stack produces HTML.

Evidence for this claim Sanity Content Lake is queried using APIs and GROQ; it is distinct from a site's frontend rendering layer. Scope: Sanity-hosted content data and query APIs. Confidence: high · Verified: Sanity: Content Lake

So entire SEO surface lives di Anda frontend framework. sebagai Webstacks put ini, “Sanity handles content storage and editing, while your frontend framework handles SEO output.” (terjemahan) “Sanity handles konten storage dan editing, while Anda frontend framework handles SEO output.” itu’s not sebuah limitation — ini adalah whole headless model. Sanity’s own team frames ini well: “When using Sanity as a CMS, you’re doing headless SEO. Although this approach requires thoughtful technical implementation, it can liberate your content to help you reach more users across all channels.” (terjemahan) “When menggunakan Sanity sebagai sebuah CMS, Anda’re doing headless SEO. Although ini approach memerlukan thoughtful technical implementation, ini dapat liberate Anda konten untuk help Anda reach more pengguna di seluruh semua channels.” berfungsi adalah nyata, tetapi ini adalah yang sama berfungsi sebagai apa pun headless bangun (see SEO untuk sebuah CMS headless).

rendering mode adalah foundation

Because frontend membangun HTML, rendering decision adalah single sebagian besar consequential SEO choice pada sebuah Sanity situs. Four modes:

SSG — Static situs Generation. konten adalah fetched dari Sanity di bangun time dan baked ke static HTML disajikan dari sebuah CDN. Best-case SEO: fully-rendered HTML pada pertama permintaan, fast TTFB. Ideal untuk blog posts, marketing halaman, dan product/landing halaman. tradeoff adalah freshness — changed konten perlu sebuah rebuild (ISR solves ini).

SSR — rendering sisi server. konten adalah fetched per permintaan dan full HTML adalah rendered pada server. Excellent SEO, selalu fresh. gunakan ini untuk frequently updated konten. Tradeoff adalah infrastructure cost dan slightly higher TTFB daripada static files.

ISR — Incremental Static Regeneration (Vercel/Next.js). Static halaman regenerate di background, ideally triggered oleh sebuah Sanity webhook pada publish so halaman rebuilds moment sebuah editor hits publish. ini adalah best dari SSG’s speed dan SSR’s freshness untuk konten itu perubahan pada order dari hours atau days.

CSR — rendering sisi klien. sebuah HTML shell ships, lalu JavaScript fetches dari Sanity dan membangun DOM di browser. ini adalah worst SEO option: Googlebot memiliki untuk queue halaman untuk sebuah later render wave, timing adalah unpredictable, dan AI crawler dan banyak lainnya bot see hanya shell. CSR adalah acceptable hanya behind authentication untuk konten Anda tidak ingin terindeks anyway.

dan don’t reach untuk old shortcut: Google memiliki deprecated dynamic rendering (serving prerendered HTML untuk bot, CSR untuk pengguna). Officially, “dynamic rendering was a workaround and not a long-term solution,” (terjemahan) “dynamic rendering adalah sebuah workaround dan not sebuah panjang-istilah solusi,” dan Google now recommends “server-side rendering, static rendering, or hydration.” (terjemahan) “rendering sisi server, static rendering, atau hydration.” untuk sebuah Sanity situs, itu berarti SSG atau SSR — not sebuah bot-detection hack. (Full rendering treatment di JavaScript SEO.)

Evidence for this claim Google describes dynamic rendering as a workaround rather than a recommended long-term solution and recommends server-side rendering, static rendering, or hydration. Scope: Google Search guidance for JavaScript sites. Confidence: high · Verified: Google: Dynamic rendering

Portable Text — Anda body copy adalah sebuah JSON AST

ini adalah paling Sanity-spesifik thing pada halaman. Sanity stores rich text sebagai Portable Text: sebuah JSON abstract syntax tree, not HTML. Body copy di konten Lake looks like sebuah array dari typed blocks, not <p> tags. Anda frontend memiliki untuk serialize ini ke HTML sebelum apa pun crawler dapat read ini:

  • @portabletext/react — untuk React/Next.js.
  • @portabletext/to-html — framework-agnostic (Astro, Remix, anything).
  • old @sanity/block-content-to-react adalah deprecated — don’t gunakan ini.

jika Anda render server-side atau di bangun time, serialization happens sebelum halaman adalah dikirim dan crawler get full HTML. jika Anda render client-side, serialization runs di browser. Because LLM-crawler rendering contracts vary oleh provider, CSR Portable Text membuat sebuah coverage risk itu raw HTML menghindari. There’s juga sebuah handy GROQ helper: pt::text(body) extracts semua plain text dari sebuah Portable Text field sebagai sebuah string, which adalah perfect untuk feeding JSON-LD deskripsi without sebuah separate editor field.

konten modeling untuk SEO — reusable SEO object

cleanest pattern, dan one Sanity’s own course teaches, adalah sebuah single reusable seo object ditambahkan untuk setiap document jenis — not SEO fields copy-pasted per jenis. key design principle dari Sanity Learn: “For the benefit of content authors, fields relevant to SEO should not always be required. Instead, they should be used to override some existing content, when provided.” (terjemahan) “untuk benefit dari konten authors, fields relevant untuk SEO seharusnya not selalu menjadi diperlukan. Instead, mereka seharusnya menjadi digunakan untuk override beberapa existing konten, when disediakan.”

dalam praktik itu berarti SEO fields adalah overrides dengan fallbacks, implemented dengan GROQ’s coalesce():

"title": coalesce(seo.title, title, ""),
"description": coalesce(seo.description, excerpt, "")

sebuah minimum viable seo object: metaTitle (≤65 chars), metaDescription (≤155 chars), canonicalUrl, openGraphImage (1200×630), dan sebuah noIndex boolean. tambahkan Sanity validation aturan untuk enforce itu character limits sebelum publish — so editors catch masalah platform akan otherwise let melalui. gunakan slug jenis dengan sebuah custom generation function, dan gunakan references untuk tautan internal so URL perubahan propagate automatically. tambahkan sebuah hideFromSearch boolean dan filter ini out dari both sitemap GROQ kueri dan halaman’s robots metadata.

Metadata, sitemaps, dan canonicals — semua dibangun di frontend

Metadata. di Next.js App Router, gunakan exported generateMetadata() function (not inline <head> tags) so metadata doesn’t duplicate di seluruh nested layouts. bangun one server-side helper itu takes sebuah GROQ hasil dan mengembalikan framework’s metadata object — implement ini once, gunakan ini everywhere. Open Graph images dapat menjadi generated dynamically dengan Next.js Edge OG generation, pulling konten straight dari Sanity.

Sitemaps. There’s no auto-sitemap. Anda bangun ini dari sebuah GROQ kueri → URL array → XML (sitemap.ts di Next.js, @astrojs/sitemap di Astro). selalu filter drafts dan hidden halaman:

*[_type in ["page", "post"] && defined(slug.current) && hideFromSearch != true]

gunakan _updatedAt (not _createdAt atau sebuah manual date) untuk lastModified, pertahankan individual sitemap files di bawah 50 000 URLs dengan sebuah indeks untuk larger situs, dan trigger regeneration via sebuah Sanity webhook pada publish/unpublish so ini tidak pernah goes stale.

Canonicals. Set canonical URLs dari konten model, default untuk sebuah self-referencing canonical, dan bangun absolute URLs dari sebuah single SITE_URL so canonical tidak pernah drifts. (Mechanics di Canonicalization.)

data terstruktur — generate ini, don’t author ini

right pattern adalah untuk generate JSON-LD programmatically dari existing konten fields di render time — tidak pernah bangun separate JSON-LD editor surface di Studio, which hanya membuat drift antara konten dan markup. Roboto Studio’s aturan adalah blunt: “Derive JSON-LD from existing fields, at render time, in code.” (terjemahan) “Derive JSON-LD dari existing fields, di render time, di code.” Sanity agrees — “JSON-LD is a powerful way to provide structured data to search engines — fortunately structured data is what Sanity does best.” (terjemahan) “JSON-LD adalah sebuah powerful cara untuk menyediakan data terstruktur untuk mesin pencari — fortunately data terstruktur adalah what Sanity melakukan best.”

gunakan pt::text(body) untuk pull plain text untuk schema deskripsi, TypeScript package schema-dts untuk jenis safety, dan render ini dengan <script type="application/ld+json">. Note itu “the JSON-LD markup can be rendered anywhere in the page — it doesn’t need to be stored inside the <head>.” (terjemahan) “ JSON-LD markup dapat menjadi rendered anywhere di halaman — ini doesn’t perlu untuk menjadi stored inside undefined.” Priority jenis untuk konten situs: artikel/BlogPosting, BreadcrumbList, FAQPage, Organization, situs web.

Keeping drafts out dari Google — nyata-incident pitfall

Sanity’s perspective sistem controls draft visibilitas: published mengembalikan hanya production konten; drafts mengembalikan draft documents untuk preview. selalu gunakan published perspective di production API panggilan. tetapi itu alone isn’t enough, because draft URLs leak. sebagai one developer recounted, danger adalah “a client panicking because an unpublished landing page showed up in Google Search Console. If a content editor shares that URL in Slack, and someone clicks it from a browser that’s then crawled (it happens), the draft content can end up indexed.” (terjemahan) “sebuah client panicking because sebuah unpublished landing halaman showed up di Google Search Console. jika sebuah konten editor shares itu URL di Slack, dan someone clicks ini dari sebuah browser itu’s lalu di-crawl (ini happens), draft konten dapat end up terindeks.”

reliable defense adalah sebuah multi-layer one:

  1. gunakan published perspective di production; tidak pernah expose sebuah unprotected preview endpoint.
  2. tambahkan sebuah X-Robots-Tag: noindex header HTTP untuk setiap draft-mode/preview respons — bahkan jika sebuah draft URL leaks dan gets di-crawl, Googlebot respects header dan won’t indeks ini. (Don’t rely pada robots.txt untuk ini; sebuah header adalah more reliable daripada sebuah disallow untuk preview halaman.)
  3. Validate preview secret server-side; tidak pernah reflect ini di redirect URL, dan scope preview-enable endpoint untuk Anda Studio’s origin.

Robots, redirects, image SEO, dan hreflang

robots.txt adalah sebuah static frontend file (app/robots.ts di Next.js). Block Studio paths hanya jika mereka’re pada yang sama domain (Disallow: /studio/); don’t try untuk block preview halaman dengan ini.

Redirects adalah sebuah genuine workflow win: store them sebagai Sanity documents (from, to, statusCode) so konten team dapat manage redirects without sebuah developer deploy, lalu implement them di Next.js middleware.ts atau sebuah CDN/Worker layer (tidak pernah di Sanity itself). tambahkan validation aturan untuk mencegah loops dan invalid paths.

Image SEO: gunakan Sanity’s image CDN dengan ?auto=format untuk automatic WebP/AVIF, manage teks alt di asset tingkat dengan document-tingkat overrides, gunakan vanity filenames alih-alih hashed URLs, dan set hotspot/crop so automatic crops pertahankan subject — which penting sebagian besar untuk OG images.

Hreflang: model locale variants sebagai separate Sanity documents referencing canonical versi, generate hreflang dari sebuah GROQ kueri returning semua locale slugs, dan give setiap locale halaman sebuah self-referencing canonical — tidak pernah canonical sebuah non-English halaman untuk English one.

Plugins — helpful, not sebuah substitute

  • sanity-plugin-seo — primary recommendation (22k+ downloads). Live SEO score, meta/OG preview, social cards, robots control, hreflang, readability. AI tier menambahkan keyword suggestions dan meta generation.
  • sanity-plugin-seofields — sebuah alternative: 39 schema.org jenis, sebuah SEO Health Dashboard, dan Next.js helper functions (buildSeoMeta()).
  • sanity-plugin-seo-paneDEPRECATED. ini adalah old Yoast integration, dihapus karena sebuah outdated dependency. ini masih menampilkan up di old tutorials. Don’t gunakan ini.

honest framing, dari Yanatiev: “SEO success in Sanity comes from intentional structure, not plugins.” (terjemahan) “SEO success di Sanity comes dari intentional structure, not plugins.” Plugins surface fields dan give editorial feedback — mereka don’t replace proper konten modeling.

AI search dan AEO

2026 wrinkle: LLM training dan retrieval crawler (Anthropic, OpenAI, umum crawl) typically don’t execute JavaScript today, so CSR Portable Text adalah largely invisible untuk them regardless dari whether Googlebot dapat render ini — tetapi ini adalah provider-spesifik dan not sebuah guaranteed contract. Google’s Gemini pipeline adalah notable exception, since ini reuses Googlebot’s own rendering infrastructure, dan lainnya providers’ perilaku dapat perubahan. Treat “no rendering” (terjemahan) “no rendering” sebagai safe assumption untuk bangun untuk, not sebuah permanent law. Beyond rendering, two Sanity-friendly tactics: sajikan clean markdown via konten negotiation when Accept: text/markdown adalah present (Sanity’s @portabletext/markdown package converts Portable Text dengan no extra authoring), dan monitor Bing specifically since Bing’s indeks feeds ChatGPT’s browse respons. pada llms.txt, Sanity’s own Knut Melvær adalah skeptical — “Probably don’t do llms.txt” (terjemahan) “Probably don’t melakukan llms.txt” untuk besar situs, because semua-atau-nothing scope dan file-size limits membuat ini impractical; per-halaman konten negotiation adalah more granular. Roboto Studio’s summary adalah right mindset: “AEO and SEO live on the same plumbing, so we treat them as one job.” (terjemahan) “AEO dan SEO live pada yang sama plumbing, so kami treat them sebagai one job.” (More di AI Search.)

myths worth killing

  • “Sanity does SEO automatically like WordPress + Yoast.” (terjemahan) “Sanity melakukan SEO automatically like WordPress + Yoast.” No. Zero HTML, zero automatic anything.
  • “Any rendering mode is fine if the content’s in Sanity.” (terjemahan) “apa pun rendering mode adalah fine jika konten’s di Sanity.” No. CSR breaks pengindeksan dan AI visibilitas; dynamic rendering adalah deprecated.
  • “Drafts can’t be indexed.” (terjemahan) “Drafts dapat’t menjadi terindeks.” mereka dapat, jika sebuah preview URL leaks. gunakan noindex header.
  • “Portable Text is HTML.” (terjemahan) “Portable Text adalah HTML.” ini adalah sebuah JSON AST itu frontend harus serialize.
  • “You need a JSON-LD editor in Studio.” (terjemahan) “Anda perlu sebuah JSON-LD editor di Studio.” No — generate ini dari existing fields.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.