Guide Sanity SEO
Sanity stores contenu as JSON et emits zero HTML — votre frontend decides votre SEO. Rendu modes, Portable Texte, le SEO object, sitemaps, draft-mode noindex, JSON-LD, et plugins.
Sanity est a CMS headless que stores contenu as structured JSON dans son Contenu Lake et produces aucun HTML — donc votre frontend framework (Suivant.js, Astro, Remix) decides tout à propos de votre SEO. Le unique biggest lever est rendu: SSG et SSR ship complet HTML et sont sûr; CSR est risky parce que LLM-robot rendu contracts vary par provider. Portable Texte est a JSON AST, pas HTML, donc le frontend doit serialize il. Construire a reusable SEO object dans le contenu model, generate sitemaps et JSON-LD programmatically, garder drafts out de le indexer avec an X-Robots-Balise: noindex header, et utiliser sanity-plugin-seo (pas le deprecated Yoast pane). SEO success dans Sanity comes depuis intentional structure, pas plugins.
TL;DR — Sanity est a placer à store contenu, pas a placer que publishes pages web. Il hands votre contenu out as données (JSON), pas as finished HTML — donc a séparé site web construit avec quelque chose comme Suivant.js or Astro a à turn que données dans pages. Que signifie none de le usual SEO stuff (titles, sitemaps, canonical balises) se produit automatiquement le façon il fait on WordPress. Le biggest règle: construire votre pages on a serveur or à construire temps, pas entirely dans le visitor’s navigateur, or moteur de recherches et AI outils peut jamais voir votre contenu.
Ce que Sanity en réalité is
Personnes parfois assume Sanity est “a CMS like WordPress,” et c’est où le confusion commence. Sanity est a CMS headless. Il fait deux choses: il stores votre contenu (dans quelque chose Sanity calls le Contenu Lake) et il donne contenu editors a placer à écrire (Sanity Studio). Ce que il fait pas faire est produce a unique line de HTML. Votre contenu comes out as données structurées — JSON — via an API.
Preuve à l’appui de cette affirmation Sanity stores structured content in Content Lake and provides it to applications as data rather than finished site HTML. Portée : Sanity platform architecture; the frontend owns public rendering. Niveau de confiance : élevé · Vérifié : Sanity: Content LakeQue signifie a séparé site web — construit avec a framework comme Suivant.js, Astro, or Remix — a à récupérer que JSON et construire le réel pages personnes et moteur de recherches voir. Sanity stores le contenu; votre frontend publishes il. Une fois vous internalize que un sentence, presque tout à propos de Sanity SEO rend sense.
The un decision que matters la plupart: rendering
Parce que votre frontend construit lune pages, comment il construit les decides votre SEO. Là sont deux sûr façons et un risky façon:
- À construire temps (SSG) — pages sont pre-built dans plain HTML fichiers. Rapide et recherche-friendly.
- On a serveur, per requête (SSR) — le serveur construit le complet page et sends il. Aussi recherche-friendly, toujours fresh.
- Dans le visitor’s navigateur (CSR) — le serveur sends a near-empty shell et JavaScript fills il dans afterward. Ce est le risky un.
Google peut eventually exécuter JavaScript et lire a CSR page, mais c’est slower et moins fiable — et aujourd’hui le robots d’exploration behind ChatGPT, Claude, et Perplexity typically ne pas rendre JavaScript à tout, donc ils simplement voir le vide shell. c’est pas a fixed règle, though: Google’s Gemini réponses reuse Googlebot’s propre rendu infrastructure, donc behavior déjà varies par provider et n’est pas guaranteed à stay le même. Donc si vous vouloir à montrer up dans Google et obtenir cited par AI outils, construire votre HTML on le serveur or à construire temps.
Preuve à l’appui de cette affirmation Google can render JavaScript pages, but browser-only content depends on a separate rendering stage. Portée : Google Search only; this record does not support claims about named AI crawlers. Niveau de confiance : élevé · Vérifié : Google: JavaScript SEO basicsLe “où a fait mon SEO paramètres go?” problème
On WordPress, a plugin comme Yoast quietly handled votre titles, meta descriptions, sitemap, et balise canonicals. Sanity a aucun tel chose. Donc quelqu’un a à deliberately:
- Ajouter SEO champs (titre, description, social image) à le contenu dans Sanity.
- Wire ceux champs dans chaque page’s HTML dans le frontend.
- Construire a sitemap, a robots.txt, et données structurées — tout dans code.
None de ce est difficile. Il simplement ne va pas se produire on son propre. A lot de “mon Sanity site a aucun SEO” stories sont vraiment “nobody construit le stuff a plugin utilisé à faire.”
Two choses que quietly go incorrect
- Draft pages getting dans Google. Sanity peut servir unpublished drafts via son API. Si quelqu’un shares a preview lien et a robot d’exploration trouve il, que draft peut obtenir indexé. Vous ont à actively bloquer que.
- Corps texte c’est invisible. Sanity stores rich texte dans a special format appelé Portable Texte — c’est données, pas HTML. Votre frontend a à convert il. On a CSR page, que conversion se produit dans le navigateur, donc AI robots d’exploration jamais voir votre article texte.
Vouloir le complet version — le four rendu modes, le reusable SEO champ setup, sitemaps, draft-mode protection, JSON-LD, et qui plugins à utiliser? Switch à le Avancé tab.
TL;DR — Sanity est contenu-neutral: il stores structured JSON dans le contenu Lake et emits zero HTML, donc le frontend’s rendu mode decides tout. SSG et SSR ship complet HTML et sont sûr; CSR est le risky un parce que LLM robots d’exploration ne pas execute JavaScript, et Google deprecated dynamic rendu as a workaround. Portable Texte est a JSON AST que le frontend doit serialize. Construire a reusable
seoobject dans le contenu model avec overrides (pas requirements) viacoalesce(), generate sitemaps et JSON-LD programmatically depuis existing champs, et garder drafts out de le indexer avec anX-Robots-Tag: noindexheader on chaque preview réponse. Utilisersanity-plugin-seo— jamais le deprecated Yoast pane — mais remember “SEO success dans Sanity comes depuis intentional structure, pas plugins.”
Sanity is content storage, pas a publisher
A utile premier principle: Sanity touches votre contenu, jamais votre rendu.
Le contenu Lake stores tout as structured JSON, queried avec GROQ
(Sanity’s requête langue) or REST. Sanity Studio — le editing UI — est a React
unique-page app que généralement lives on son propre .sanity.studio subdomain et n’est pas
quelque chose vous indexer. Rien dans ce stack produces HTML.
«So the entire SEO surface lives in your frontend framework. As Webstacks put it, “Sanity handles content storage and editing, while your frontend framework handles SEO output.” That’s not a limitation — it’s the whole headless model. Sanity’s own team frames it 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.” The work is real, but it’s the same work as any headless build (see SEO for a Headless CMS). » (Traduction) (Résumé en français de la section vingt-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Rendu mode est le foundation
Parce que le frontend construit le HTML, le rendu décision est le unique la plupart consequential SEO choice on a Sanity site. Four modes:
SSG — Static Site Generation. Contenu est récupéré depuis Sanity à construire temps et baked dans static HTML servi depuis a CDN. Meilleur-case SEO: fully-rendu HTML on premier requête, rapide TTFB. Ideal pour blog posts, marketing pages, et produit/landing pages. Le tradeoff est freshness — modifié contenu nécessite a rebuild (ISR solves ce).
SSR — Rendu côté serveur. Contenu est récupéré per requête et le complet HTML est rendu on le serveur. Excellent SEO, toujours fresh. Utiliser il pour frequently mis à jour contenu. Tradeoff est infrastructure coût et slightly plus élevé TTFB que static fichiers.
ISR — Incremental Static Regeneration (Vercel/Suivant.js). Static pages regenerate dans le background, ideally triggered par a Sanity webhook on publish donc lune page rebuilds le moment an editor hits publish. Ce est le meilleur de SSG’s speed et SSR’s freshness pour contenu que changements on le order de hours or days.
CSR — Rendu côté client. An HTML shell ships, alors JavaScript récupère depuis Sanity et construit le DOM dans le navigateur. Ce est le worst SEO option: Googlebot a à queue lune page pour a plus tard rendre wave, timing est unpredictable, et AI robots d’exploration et nombreux autre bots voir seulement le shell. CSR est acceptable seulement behind authentication pour contenu vous ne pas vouloir indexé anyway.
«And don’t reach for the old shortcut: Google has deprecated dynamic rendering (serving prerendered HTML to bots, CSR to users). Officially, “dynamic rendering was a workaround and not a long-term solution,” and Google now recommends “server-side rendering, static rendering, or hydration.” For a Sanity site, that means SSG or SSR — not a bot-detection hack. (Full rendering treatment in JavaScript SEO.)
Preuve à l’appui de cette affirmation Google describes dynamic rendering as a workaround rather than a recommended long-term solution and recommends server-side rendering, static rendering, or hydration. Portée : Google Search guidance for JavaScript sites. Niveau de confiance : élevé · Vérifié : Google: Dynamic rendering» (Traduction) (Résumé en français de la section trente, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Portable Text — votre corps copy is a JSON AST
Ce est le la plupart Sanity-spécifique chose on lune page. Sanity stores rich texte as
Portable Texte: a JSON abstract syntax tree, pas HTML. Corps copy dans le contenu
Lake semble comme an array de typed bloque, pas <p> balises. Votre frontend a à
serialize il dans HTML avant quelconque robot d’exploration peut lire il:
@portabletext/react— pour React/Suivant.js.@portabletext/to-html— framework-agnostic (Astro, Remix, n’importe quoi).- Le old
@sanity/block-content-to-reactest deprecated — ne pas utiliser il.
Si vous rendre serveur-side or à construire temps, serialization se produit avant lune page est
sent et robots d’exploration obtenir complet HTML. Si vous rendre client-side, le serialization exécute
dans le navigateur. Parce que LLM-robot rendu contracts vary par provider, CSR
Portable Texte crée a coverage risque que raw HTML avoids. il y a aussi a handy GROQ
helper: pt::text(body) extracts tout le plain texte depuis a Portable Texte champ as a
string, qui est perfect pour feeding JSON-LD descriptions sans a séparé editor
champ.
Contenu modeling pour le SEO — le reusable SEO object
«The cleanest pattern, and the one Sanity’s own course teaches, is a single
reusable seo object added to every document type — not SEO fields copy-pasted per
type. The key design principle from 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.”
» (Traduction) (Résumé en français de la section trente-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
En pratique que signifie SEO champs sont overrides avec fallbacks, implemented avec
GROQ’s coalesce():
"title": coalesce(seo.title, title, ""),
"description": coalesce(seo.description, excerpt, "")«A minimum viable seo object: metaTitle (≤65 chars), metaDescription
(≤155 chars), canonicalUrl, openGraphImage (1200×630), and a noIndex boolean.
Add Sanity validation rules to enforce those character limits before publish —
so editors catch problems the platform would otherwise let through. Use a slug
type with a custom generation function, and use references for internal links so
URL changes propagate automatically. Add a hideFromSearch boolean and filter it out
of both the sitemap GROQ query and the page’s robots metadata.
» (Traduction) (Résumé en français de la section trente-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Metadata, sitemaps, and canonicals — all built in the frontend » (Traduction) (Résumé en français de la section quarante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Metadata. In Next.js App Router, use the exported generateMetadata() function
(not inline <head> tags) so metadata doesn’t duplicate across nested layouts.
Build one server-side helper that takes a GROQ result and returns the framework’s
metadata object — implement it once, use it everywhere. Open Graph images can be
generated dynamically with Next.js Edge OG generation, pulling content straight from
Sanity.
» (Traduction) (Résumé en français de la section quarante et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Sitemaps. il y a aucun auto-sitemap. Vous construire il depuis a GROQ requête → URL array →
XML (sitemap.ts dans Suivant.js, @astrojs/sitemap dans Astro). Toujours filter drafts et
hidden pages:
*[_type in ["page", "post"] && defined(slug.current) && hideFromSearch != true]Utiliser _updatedAt (pas _createdAt or a manual date) pour lastModified, garder
individual sitemap fichiers sous 50 000 URLs avec an indexer pour plus grand sites, et
trigger regeneration via a Sanity webhook on publish/unpublish donc il jamais goes stale.
Canonicals. Définir URL canoniques depuis le contenu model, par défaut à a
self-referencing canonical, et construire absolute URLs depuis a unique SITE_URL donc le
canonical jamais drifts. (Mechanics dans
Canonicalization.)
Données structurées — generate it, don’t author it
«The right pattern is to generate JSON-LD programmatically from existing content fields at render time — never build a separate JSON-LD editor surface in Studio, which just creates drift between content and markup. Roboto Studio’s rule is blunt: “Derive JSON-LD from existing fields, at render time, in code.” Sanity agrees — “JSON-LD is a powerful way to provide structured data to search engines — fortunately structured data is what Sanity does best.” » (Traduction) (Résumé en français de la section quarante-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Utiliser pt::text(body) à pull plain texte pour schema descriptions, le TypeScript
package schema-dts pour type safety, et rendre il avec
<script type="application/ld+json">. Remarque que “le JSON-LD markup peut être
rendu anywhere dans lune page — il ne fait pas besoin à être stored à l’intérieur le
<head>.” Priority types pour contenu sites: Article/BlogPosting,
BreadcrumbList, FAQPage, Organization, Site web.
Keeping drafts out de Google — le real-incident pitfall
Sanity’s perspective système contrôle draft visibility: published renvoie seulement
production contenu; drafts renvoie draft documents pour preview. Toujours utiliser le
published perspective dans production API calls. Mais que alone n’est pas suffisant,
parce que draft URLs leak. As un developer recounted, le danger est
“a client panicking parce que an unpublished landing page showed up dans la recherche Google
Console. Si a contenu editor shares que URL dans Slack, et quelqu’un clicks il depuis a
navigateur c’est alors exploré (il se produit), le draft contenu peut fin up indexé.”
The reliable defense is a multi-layer un:
«1. Use the published perspective in production; never expose an unprotected preview
endpoint.
2. Add an X-Robots-Tag: noindex HTTP header to every draft-mode/preview
response — even if a draft URL leaks and gets crawled, Googlebot respects the
header and won’t index it. (Don’t rely on robots.txt for this; a header is more
reliable than a disallow for preview pages.)
3. Validate the preview secret server-side; never reflect it in the redirect URL, and
scope the preview-enable endpoint to your Studio’s origin.
» (Traduction) (Résumé en français de la section cinquante-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Robots, redirects, image SEO, and hreflang » (Traduction) (Résumé en français de la section cinquante-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«robots.txt is a static frontend file (app/robots.ts in Next.js). Block Studio
paths only if they’re on the same domain (Disallow: /studio/); don’t try to block
preview pages with it.
» (Traduction) (Résumé en français de la section cinquante-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Redirects are a genuine workflow win: store them as Sanity documents (from,
to, statusCode) so the content team can manage redirects without a developer
deploy, then implement them in Next.js middleware.ts or a CDN/Worker layer (never
in Sanity itself). Add validation rules to prevent loops and invalid paths.
» (Traduction) (Résumé en français de la section cinquante-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Image SEO: utiliser Sanity’s image CDN avec ?auto=format pour automatic WebP/AVIF,
manage texte alternatif à le asset level avec document-level overrides, utiliser vanity
filenames au lieu de hashed URLs, et définir hotspot/crop donc automatic crops garder
le subject — qui matters la plupart pour OG images.
Hreflang: model locale variants as séparé Sanity documents referencing le canonical version, generate hreflang depuis a GROQ requête returning tout locale slugs, et donner chaque locale page a self-referencing canonical — jamais canonical a non-English page à le English un.
Plugins — utile, pas a substitute
sanity-plugin-seo— le principal recommendation (22k+ downloads). Actif SEO score, meta/OG preview, social cards, robots contrôler, hreflang, readability. Le AI tier ajoute mot-clé suggestions et meta generation.sanity-plugin-seofields— an alternative: 39 schema.org types, an SEO Health Dashboard, et Suivant.js helper functions (buildSeoMeta()).sanity-plugin-seo-pane— DEPRECATED. Ce est le old Yoast integration, supprimé due à an outdated dependency. Il encore montre up dans old tutorials. ne pas utiliser il.
Le honest framing, depuis Yanatiev: “SEO success dans Sanity comes depuis intentional structure, pas plugins.” Plugins surface champs et donner editorial feedback — ils ne pas remplacer proper contenu modeling.
AI search and AEO
«The 2026 wrinkle: LLM training and retrieval crawlers (Anthropic, OpenAI, Common
Crawl) typically don’t execute JavaScript today, so CSR Portable Text is largely
invisible to them regardless of whether Googlebot can render it — but this is
provider-specific and not a guaranteed contract. Google’s Gemini pipeline is the
notable exception, since it reuses Googlebot’s own rendering infrastructure, and
other providers’ behavior can change. Treat “no rendering” as the safe assumption to
build for, not a permanent law. Beyond rendering, two Sanity-friendly
tactics: serve clean markdown via content negotiation when Accept: text/markdown
is present (Sanity’s @portabletext/markdown package converts Portable Text with no
extra authoring), and monitor Bing specifically since Bing’s index feeds
ChatGPT’s browse responses. On llms.txt, Sanity’s own Knut Melvær is skeptical —
“Probably don’t do llms.txt” for large sites, because the all-or-nothing scope and
file-size limits make it impractical; per-page content negotiation is more granular.
Roboto Studio’s summary is the right mindset: “AEO and SEO live on the same plumbing,
so we treat them as one job.” (More in AI Search.)
» (Traduction) (Résumé en français de la section soixante-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
The myths worth killing
«- “Sanity does SEO automatically like WordPress + Yoast.” No. Zero HTML, zero
automatic anything.
» (Traduction) (Résumé en français de la section soixante-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- “Any rendering mode is fine if the content’s in Sanity.” No. CSR breaks
indexing and AI visibility; dynamic rendering is deprecated.
» (Traduction) (Résumé en français de la section soixante-quatre, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- “Drafts can’t be indexed.” They can, if a preview URL leaks. Use a noindex
header.
» (Traduction) (Résumé en français de la section soixante-quatre, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- “Portable Text is HTML.” It’s a JSON AST that the frontend must serialize.
» (Traduction) (Résumé en français de la section soixante-quatre, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- “You need a JSON-LD editor in Studio.” No — generate it from existing fields.
» (Traduction) (Résumé en français de la section soixante-quatre, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
AI summary
A condensed prendre on the Avancé version:
«- Sanity is content-neutral. It stores structured JSON in the Content Lake
(queried via GROQ/REST) and emits zero HTML. The frontend (Next.js, Astro,
Remix) produces all SEO output. “Sanity does SEO like WordPress” is a myth.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Rendering mode is the foundation. SSG and SSR ship complete HTML and
are safe; ISR (webhook-triggered on publish) adds freshness; CSR is risky.
Google deprecated dynamic rendering — use SSR/static/hydration.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- LLM-crawler rendering varies by provider — raw HTML maximizes Portable Text coverage.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Portable Text is a JSON AST, not HTML. Serialize it with @portabletext/react
or @portabletext/to-html; @sanity/block-content-to-react is deprecated. Use
pt::text(body) to extract plain text for JSON-LD.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Content modeling: one reusable seo object across all types, fields as
overrides not requirements via coalesce(), validation rules enforcing limits,
and a hideFromSearch flag filtered from both sitemap and robots metadata.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Sitemaps, metadata, canonicals, robots.txt are all built in the frontend.
Filter drafts from the sitemap GROQ query, use _updatedAt for lastModified, and
regenerate via Sanity webhooks.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Generate JSON-LD programmatically from existing fields at render time — never a
separate Studio editor. Use schema-dts; it can render anywhere, not just <head>.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie sept : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Keep drafts out of the index: use the published perspective in production
and add an X-Robots-Tag: noindex header to every preview response. A leaked
draft URL has caused real indexing incidents.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie huit : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Plugins: sanity-plugin-seo (primary) or sanity-plugin-seofields. The Yoast
sanity-plugin-seo-pane is deprecated. “SEO success in Sanity comes from
intentional structure, not plugins.”
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie neuf : le texte source est conservé pour vérification lors de la relecture francophone.)
«- AEO: monitor Bing (feeds ChatGPT browse); serve markdown via content
negotiation; Sanity advises against llms.txt for large sites.
» (Traduction) (Résumé en français de la section soixante-neuf, sous-partie dix : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Official documentation » (Traduction) (Résumé en français de la section soixante-douze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Primary-source documentation from the search engines and Sanity. » (Traduction) (Résumé en français de la section soixante-treize, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«Google
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Understand JavaScript SEO Basics — the crawl → render → index pipeline, JS canonicals, and why blocked files don’t get rendered. The core reference for any Sanity frontend.
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Dynamic Rendering (deprecated workaround) — why Google deprecated it and what to use instead (SSR, static rendering, hydration).
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Rendering for Content-Driven Web Apps — SSR vs. SSG vs. CSR tradeoffs for exactly the kind of content sites Sanity powers.
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Robots meta tag, data-nosnippet, and X-Robots-Tag — the X-Robots-Tag: noindex HTTP header used to keep draft/preview responses out of the index.
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Intro to robots.txt — what robots.txt does and doesn’t do (it controls crawling, not indexing of leaked drafts).
» (Traduction) (Résumé en français de la section soixante-quatorze, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«Bing / Microsoft » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- The new evergreen Bingbot (Microsoft Edge) — Bingbot rendering JavaScript via Edge; relevant since Bing’s index feeds ChatGPT browse. » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- IndexNow / indexnow.org — the push protocol to wire to your Sanity publish webhook. » (Traduction) (Résumé en français de la section soixante-quinze, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«Sanity
» (Traduction) (Résumé en français de la section soixante-seize, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- SEO with Sanity — Sanity’s own master SEO guide.
» (Traduction) (Résumé en français de la section soixante-seize, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- SEO Optimization course — the full Next.js SEO course (schema types, dynamic sitemaps, JSON-LD).
» (Traduction) (Résumé en français de la section soixante-seize, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- Presenting and previewing content (perspectives) — published vs. drafts perspectives, the basis of draft-mode safety.
» (Traduction) (Résumé en français de la section soixante-seize, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Quotes from the source » (Traduction) (Résumé en français de la section soixante-dix-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
On-le-record statements pertinent à Sanity SEO. Chaque lien est a deep lien que jumps à le quoted passage on le page source.
Sanity — le headless SEO model
«- “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.” — Sanity, SEO with Sanity. Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “SEO doesn’t have to be complicated. It’s a matter of taking content you’ve already responsibly structured with Sanity and rendering it in the format and places that search engines expect.” — Sanity Learn, SEO Optimization course. Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-deux, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- “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.” — Sanity Learn, SEO schema types and metadata. Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-deux, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- “JSON-LD is a powerful way to provide structured data to search engines—fortunately structured data is what Sanity does best.” — Sanity Learn, Generating JSON-LD dynamically. Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-deux, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
Google — dynamic rendu est deprecated
«- “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” — Google Search Central docs. Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Recommended instead: “server-side rendering, static rendering, or hydration.” Jump to quote » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«Industry — frontend owns SEO; structure beats plugins » (Traduction) (Résumé en français de la section quatre-vingt-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- “Sanity handles content storage and editing, while your frontend framework handles SEO output.” — Webstacks, Sanity SEO. Read the guide » (Traduction) (Résumé en français de la section quatre-vingt-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “AEO and SEO live on the same plumbing, so we treat them as one job.” — Roboto Studio / Jono Alford, AEO & SEO best practices for Sanity. Read the post » (Traduction) (Résumé en français de la section quatre-vingt-six, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- “SEO success in Sanity comes from intentional structure, not plugins.” — Yanatiev, SEO best practices for Sanity CMS. Read the post » (Traduction) (Résumé en français de la section quatre-vingt-six, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Probably don’t do llms.txt.” — Knut Melvær, Sanity, How to serve content to agents. Read the field guide » (Traduction) (Résumé en français de la section quatre-vingt-six, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
Remarque: Sanity’s site (le SEO guide, Apprendre course lessons, et blog) et le Webstacks, Roboto Studio, et Yanatiev posts sont JavaScript-rendu et resist automated texte-fragment checking; confirmer ces citations contre le actif pages avant treating les as final. Le Google dynamic-rendu doc est likewise JS-rendu.Sanity SEO checklist
A réussir construit autour comment Sanity en réalité fonctionne — construire le choses le plateforme laisse à votre frontend, et lock bas le choses que quietly break.
Rendu & contenu (le foundation)
- Pages rendre leur contenu dans HTML on premier requête (SSG or SSR), pas seulement après client-side JavaScript exécute.
- Aucun SEO-critical page dépend on CSR (raw HTML maximizes LLM-robot coverage).
- ISR (si utilisé) regenerates on a Sanity publish webhook, pas simplement a timer.
- Portable Texte est serialized serveur-side avec
@portabletext/reactor@portabletext/to-html(pas le deprecatedblock-content-to-react).
Contenu model
- Un reusable
seoobject on chaque document type — pas per-type duplication. - SEO champs sont overrides via
coalesce(), avec validation règles enforcing titre/description length avant publish. - A
hideFromSearch(ornoIndex) boolean exists et est filtered depuis les deux le sitemap GROQ requête et lune page’s robots metadata.
«Frontend outputs
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Metadata wired from GROQ into generateMetadata() (or framework equivalent) —
one reusable helper.
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Sitemap generated from GROQ, drafts/hidden filtered, _updatedAt used for
lastModified, regenerated on a webhook.
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] Canonicals are absolute URLs from a single SITE_URL, per-page and
self-referencing by default.
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] robots.txt exists in the frontend; .js/.css are not blocked.
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)
«- [ ] JSON-LD generated programmatically from existing fields (Article, Breadcrumb,
FAQ, Organization), verified with the Rich Results Test.
» (Traduction) (Résumé en français de la section quatre-vingt-quatorze, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
Draft / preview safety
- Production API calls utiliser le
publishedperspective. - Chaque draft/preview réponse sends an
X-Robots-Tag: noindexheader. - Preview secret validated serveur-side et scoped à le Studio origin.
AEO & monitoring
- Bing Webmaster Outils définir up (Bing feeds ChatGPT browse); IndexNow on publish.
- (Optional) markdown served via content negotiation pour AI robots d’exploration.
«## The mental models » (Traduction) (Résumé en français de la section quatre-vingt-dix-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«1. Sanity stores, the frontend publishes. The Content Lake holds JSON; your framework produces every byte of HTML and every SEO signal. Before debugging any Sanity SEO problem, ask: what is the frontend actually sending crawlers? Almost everything resolves to that. » (Traduction) (Résumé en français de la section cent, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«2. Rendering mode is the product. Pick by how the content changes: » (Traduction) (Résumé en français de la section cent un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- Mostly static (blog, docs, marketing) → SSG (rebuild or ISR on publish). » (Traduction) (Résumé en français de la section cent un, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- Frequently changing, must be fresh → SSR. » (Traduction) (Résumé en français de la section cent un, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- Hours/days cadence, want static speed → ISR (webhook-triggered). » (Traduction) (Résumé en français de la section cent un, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.) «- Behind a login, not meant to be indexed → CSR is acceptable. » (Traduction) (Résumé en français de la section cent un, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.) «- Public content you want ranked or cited by AI → never CSR. » (Traduction) (Résumé en français de la section cent un, sous-partie six : le texte source est conservé pour vérification lors de la relecture francophone.)
«3. Overrides, not requirements.
SEO fields default to the primary content and only override when an editor fills them
in — implemented with coalesce(). This keeps the editing experience clean and
guarantees every page has something for its title and description.
» (Traduction) (Résumé en français de la section cent deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«4. Generate, don’t author, the markup. Sitemaps, JSON-LD, hreflang, and canonicals are all derived from existing fields in code at render time. A separate editor surface for any of them just creates drift. “Derive from existing fields, at render time, in code.” » (Traduction) (Résumé en français de la section cent trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«5. Defense in depth for drafts.
published perspective in production is layer one; an X-Robots-Tag: noindex header
on every preview response is layer two. Never rely on a single control to keep
unpublished content out of the index.
» (Traduction) (Résumé en français de la section cent quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
«## Sanity SEO — cheat sheet » (Traduction) (Résumé en français de la section cent sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Rendering modes En un coup d’œil
| Mode | Où HTML is construit | SEO | Meilleur pour | Watch out pour |
|---|---|---|---|---|
| SSG | Construire temps → static fichiers | ✅ Meilleur | Blogs, docs, marketing | Stale jusqu’à rebuild |
| SSR | Server, per requête | ✅ Meilleur | Frequently-updated content | Plus élevé infra cost |
| ISR | Static + webhook regen | ✅ Bon | Hourly/daily content | Configurer the publish webhook |
| CSR | In le navigateur | ⚠️ Risky | Logged-in dashboards | Invisible to AI robots d’exploration |
What’s construit in the frontend (pas in Sanity)
| Sortie | Comment |
|---|---|
| Corps copy HTML | Serialize Portable Texte (@portabletext/react / -to-html) |
| Meta balises | generateMetadata() depuis a GROQ résultat |
| Sitemap | GROQ requête → XML; filter drafts; _updatedAt pour lastmod |
| Canonicals | Absolute URLs depuis un SITE_URL, per-page |
| robots.txt | Static frontend fichier (robots.ts dans Suivant.js) |
| JSON-LD | Generated depuis existing champs; schema-dts pour types |
| Redirections | Sanity documents → frontend middleware / Worker |
GROQ extraits worth memorizing
- Override avec fallback:
coalesce(seo.title, title, "") - Plain texte depuis Portable Texte:
pt::text(body) - Sitemap filter:
*[... && defined(slug.current) && hideFromSearch != true]
Rapide règles
- LLM-robot rendu varies par provider → éviter CSR-seulement public contenu.
- Dynamic rendu est deprecated — utiliser SSR/static/hydration.
- Drafts:
publishedperspective +X-Robots-Tag: noindexheader. - Plugin:
sanity-plugin-seo✅ /sanity-plugin-seo-pane(Yoast) ❌ deprecated. - “SEO success dans Sanity comes depuis intentional structure, pas plugins.”
Draft or preview contenu appeared dans Search Console
Utiliser ce runbook quand an unpublished Sanity document has a discoverable preview URL or montre up dans la recherche Google Console.
- Confirmer qui réponse leaked. Récupérer le reported URL sans Studio
credentials et inspect les deux le status et
X-Robots-Tagheader. Si il renvoie publié contenu, continuer à étape 2. Si il exposes a draft, disable le preview entry point pendant que vous continuer. - Vérifier le production perspective. Trace lune page’s GROQ requête et confirmer
production utilise le
publishedperspective. Si il utilisedrafts, corriger que requête premier; si il déjà utilisepublished, continuer à la réponse couche. - Ajouter le indexation backstop. Send
X-Robots-Tag: noindexon chaque preview et draft-mode réponse. Si le header est manquant on quelconque preview route, corriger le shared preview middleware plutôt que patching un page. - Valider preview accès. Confirmer le preview secret est vérifié serveur-side, n’est pas reflected dans le destination URL, et accepts requêtes seulement depuis le prévu Studio origin. Si a public preview URL encore fonctionne, rotate le secret et fermer que route.
- Supprimer le indexé copy. Après la réponse est sûr, utiliser Search Console’s
removal workflow quand le exposure est urgent, alors requête a fresh explorer. Si le
URL devrait jamais exist publicly, garder le
noindexréponse disponible long suffisant pour robots d’exploration à voir il plutôt que blocking il dans robots.txt. - Vérifier le corriger. Récupérer l’URL pendant que logged out et exécuter Inspection d’URL. Le
draft doit être absent depuis le corps et le preview réponse doit carry
noindex.
Sanity SEO mistakes to éviter
Expecting Sanity à emit SEO HTML
Pourquoi c’est incorrect: Sanity stores JSON; il ne fait pas publish titles, canonicals, sitemaps, or page HTML. Faire ce à la place: faire le frontend responsible pour chaque sortie et vérifier le generated réponse plutôt que le Studio champs.
Choosing CSR pour public content
Pourquoi c’est incorrect: Le initial réponse est an vide shell, et nombreux AI robots d’exploration faire pas execute JavaScript à tout. Faire ce à la place: ship public contenu avec SSG, SSR, or webhook-triggered ISR.
Assuming unpublished signifie unindexable
Pourquoi c’est incorrect: A shared preview URL peut leak et être exploré. Faire ce à la place:
utiliser le published perspective dans production et send an X-Robots-Tag: noindex
header on chaque preview réponse.
Treating Portable Texte as HTML
Pourquoi it’s incorrect: Portable Text is a JSON AST, so un-serialized content jamais
becomes crawlable corps copy. Do ce à la place: serialize it on le serveur with
@portabletext/react or @portabletext/to-html.
Maintaining JSON-LD dans a séparé editor
Pourquoi c’est incorrect: A deuxième copy de produit, article, or organization facts drifts depuis le visible page. Faire ce à la place: derive JSON-LD depuis le même Sanity champs à rendre temps et valider le rendu sortie.
Vérifier si a Sanity page ships réel HTML
Run ce après modification rendering mode, Portable Text serialization, or page données chargement. It checks the initial réponse, avant client-side JavaScript peut fill gaps.
macOS / Linux — comparer normal and Googlebot réponses
URL="https://example.com/article-slug"
curl -sL "$URL" -o /tmp/sanity-page.html
curl -sL -A "Googlebot" "$URL" -o /tmp/sanity-googlebot.html
grep -Ei '<title>|rel="canonical"|<h1|application/ld\+json' /tmp/sanity-page.html
diff -u /tmp/sanity-page.html /tmp/sanity-googlebot.html«The first command should find the page’s real title, canonical, H1, and JSON-LD in
raw HTML. A meaningful content difference in the diff deserves investigation;
crawlers and users should not receive different canonical content.
» (Traduction) (Résumé en français de la section cent trente-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)
Windows PowerShell — inspect le initial réponse
$url = "https://example.com/article-slug"
$html = (Invoke-WebRequest -Uri $url).Content
$html | Select-String -Pattern '<title>|rel="canonical"|<h1|application/ld\+json'DevTools Console — confirmer Portable Text became semantic elements
[...document.querySelectorAll('main article p, main article h2, main article li')]
.map((node) => node.textContent.trim())
.filter(Boolean)
.slice(0, 20)Exécuter le extrait dans le navigateur Console. Il est a rendu-DOM vérifier, donc pair il avec
le curl tester: contenu appearing seulement ici mais pas dans le initial réponse est encore
client-rendu.
Outils pour Sanity SEO
- Inspection d’URL (Recherche Google Console) — voir comment a unique URL était exploré et rendu. Le rendu HTML indique vous si votre Portable Texte en réalité fait il dans — essential pour catching CSR gaps on a Sanity frontend.
- Résultats enrichis Tester — confirmer votre programmatic JSON-LD est présent dans le rendu sortie après quelconque rendu or template modifier.
- Screaming Frog SEO Spider — explorer avec JavaScript rendu on/off à comparer raw HTML vs. rendu HTML; ce est comment vous prove si votre contenu est serveur- rendu or client-rendu.
- Ahrefs Site Audit — surfaces manquant metadata, broken canonicals, redirection chains, et indexability problèmes à travers le entier frontend.
- Bing Webmaster Outils — submit votre sitemap et monitor Bing indexation (il feeds ChatGPT browse), plus où IndexNow submissions montrer up.
sanity-plugin-seo— dans-Studio actif SEO score, meta/OG preview, et robots contrôler donc editors obtenir feedback à authoring temps.
Testez vos connaissances: Sanity SEO
Five rapide questions on how SEO fonctionne on a Sanity-backed site. Pick an réponse pour chaque, alors vérifier.
Ressources utiles
Mon connexe writing
- JavaScript SEO Problèmes & Meilleur Practices — mon principal référence on rendu modes, qui decide tout on a Sanity frontend.
- Le Beginner’s Guide à SEO technique — où rendu et exploration fit dans le bigger picture.
Mon speaking
- JavaScript SEO — Ungagged 2019 (SlideShare) — mon walkthrough de comment headless/decoupled CMSes split le frontend depuis le backend, plus Googlebot’s stateless rendu. (Standing disclaimer: le dynamic-rendu recommendation dans que deck est maintenant outdated — Google deprecated il.)
On ce site
- SEO pour a CMS headless — le sibling guide; Sanity est a spécifique application de le même headless règles.
- JavaScript SEO — le rendu deep dive.
- Canonicalization — le consolidation mechanics behind votre frontend’s balise canonicals.
- AI Recherche — comment AI robots d’exploration et réponse moteurs behave.
Depuis autour le industry
- SEO avec Sanity (Sanity) — Sanity’s propre master SEO guide; commencer ici pour plateforme-actuel behavior.
- SEO Optimization course (Sanity Apprendre) — le hands-on Suivant.js course covering le SEO object, dynamic sitemaps, et JSON-LD.
- Sanity SEO (Webstacks, Devon Wood) — agency guide making le “frontend handles SEO sortie” point clairement.
- AEO & SEO meilleur practices pour Sanity (Roboto Studio, Jono Alford) — le AEO angle et le “derive JSON-LD depuis existing champs” règle.
- SEO meilleur practices pour Sanity CMS (Yanatiev) — le “structure, not plugins” framing.
- Comment servir contenu à agents: a champ guide (Knut Melvær, Sanity) — contenu negotiation et le cas contre llms.txt pour grand sites.
- CMS headless SEO (Ahrefs, Despina Gavoyannis) — le broader headless playbook (contenu/code/design optimized independently) que Sanity sits à l’intérieur.
- turbo-commencer-sanity (Roboto Studio, GitHub) — an open-source Sanity SEO starter avec réel
query.ts,seo-fields.ts, etseo.tsimplementations.
Journal des modifications
Mis à jour le 19 juil. 2026.
Résumé éditorial et détails enregistrés des changements.Détails des changements
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
-
Les notes détaillées des changements sont actuellement disponibles en anglais.
Comparaison complète indisponible — aucun instantané antérieur n’a été archivé pour cette révision.