A complete guide to adding AI-powered SEO to Sanity Studio: live scoring, AI meta generation via Groq, OpenAI or Anthropic, Open Graph previews, JSON-LD structured data, hreflang, GEO checklist for ChatGPT and Perplexity, and frontend integration for Next.js, Astro, Nuxt, and more.
Sanity Studio is one of the best content editing experiences available but out of the box, SEO is entirely your responsibility. No meta title field, no description limit, no social preview, no score to tell editors whether a page is ready to rank. Every team handles it differently and none of the approaches scale.
sanity-plugin-seo fixes that. One install adds a full SEO panel to every document in your Studio live scoring, keyword analysis, social previews, AI-generated meta, structured data, hreflang, GEO readiness for AI search engines, and more. This guide covers every feature so you know exactly what you are getting and how to configure it.
1
npm install sanity-plugin-seoWorks with Sanity v3, v4, and v5. Then add it to your sanity.config.ts:
1
2
3
4
5
6
7
8
9
10
import { seoMetaFields } from 'sanity-plugin-seo';
export default defineConfig({
plugins: [
seoMetaFields({
slugField: 'slug',
bodyField: 'body',
}),
],
});Reload the Studio. Every document type now has an SEO tab.
A real-time score ring (0–100) sits at the top of the SEO panel and updates as editors type no save required. The score reflects the overall readiness of the page for search engines based on everything the plugin can inspect at that moment.
What moves the score:
Editors see a color-coded ring: red is poor, amber is improving, green is ready. Beneath it, each contributing factor is listed so editors know exactly what to fix not just that something is wrong.
The focus keyword field drives keyword analysis across every other field. Once set, the plugin checks whether the keyword appears in the meta title, meta description, and body content and at what density. A keyword that appears in the title but not in the body, or appears 12 times and is flagged as stuffed, all shows up in the score breakdown.
This works with the bodyField or bodyFields config you set at plugin initialization. The plugin extracts plain text from your Portable Text body and runs density analysis against it.
Both fields have live character counters with color-coded feedback. Title turns green at 40–60 characters, description at 100–160. Editors see the current count and the ideal range without leaving the field. If AI generation is configured, a generate button sits next to each field.
The meta title and description you set here are separate from the document title. This lets you write a longer H1 for the page while keeping the meta title tighter for search snippets.
The Open Graph section gives editors a live preview of how the page will look when shared on Facebook, LinkedIn, and other platforms that read OG tags. Upload an image, set the OG title and description, and the preview card updates in real time next to the fields.
Fields available under Open Graph:
The preview renders at the right aspect ratio so what editors see in Studio matches what actually appears on social media.
Separate from Open Graph, the Twitter Card section lets you set a card type (summary or summary_large_image), Twitter-specific title, description, and image. A live preview renders the card exactly as it appears in a tweet or link share on X.
If you leave Twitter fields blank, most platforms fall back to OG tags — but having dedicated Twitter fields gives you per-platform control without any extra code.
Structured data (JSON-LD / Schema.org) is what Google uses to generate rich results review stars, FAQ blocks, breadcrumbs, article metadata in search. It is notoriously painful to write manually and even more painful to keep accurate.
sanity-plugin-seo generates it automatically. Based on the document type and the SEO fields the editor has filled in, the plugin produces the correct Schema.org JSON-LD:
No editor action required it is on the GEO checklist as a passing item the moment the plugin is installed. Your frontend just reads the seoMetaFields.jsonLd field and injects it as a script tag.
The canonical URL field lets editors specify the preferred version of a URL important when the same content is accessible at multiple paths (pagination, filters, query strings). A missing canonical on pages with URL variants causes Google to split ranking signals across duplicates.
Set the canonical once in Studio, read it in your frontend, and output it as a standard link rel canonical tag. The live score rewards a filled canonical field.
Toggle noindex and nofollow per document directly from the SEO tab. noindex tells Google not to index the page at all useful for thank-you pages, preview links, staging content. nofollow tells Google not to pass link equity through outbound links on the page.
These translate to the standard robots meta tag in your frontend:
1
<meta name="robots" content="noindex, nofollow" />If your site serves the same content in multiple languages or to region-specific audiences (en-US vs en-GB vs fr-FR), hreflang tags tell Google which URL to serve to which user. Getting these wrong or missing them entirely causes Google to pick the wrong language version, suppresses rankings in targeted regions, and can trigger duplicate content flags.
The plugin gives you an hreflang manager in the SEO tab. Add entries with locale codes and corresponding URLs. The stored data maps directly to the HTML link tags your frontend outputs:
1
2
<link rel="alternate" hreflang="en-US" href="https://yoursite.com/en-us/page" />
<link rel="alternate" hreflang="fr-FR" href="https://yoursite.com/fr/page" />Connect an AI provider and a Generate button appears next to the meta title and description fields. The plugin reads your document body content, sends it to the AI with instructions to write an SEO-optimised title and description at the correct character lengths, and fills the fields. Editors review and adjust they are not writing from scratch.
Three providers are supported:
Groq offers a generous free tier llama-3.3-70b-versatile is fast, capable, and costs nothing at typical content volumes. Sign up at console.groq.com, copy the API key, add three lines of config:
1
2
3
4
5
6
7
8
9
seoMetaFields({
aiFeature: {
provider: 'groq',
apiKey: process.env.SANITY_STUDIO_GROQ_KEY,
model: 'llama-3.3-70b-versatile',
},
slugField: 'slug',
bodyField: 'body',
})gpt-4o-mini costs roughly $2–5 per month at normal editorial volumes. Get a key from platform.openai.com:
1
2
3
4
5
6
7
8
9
seoMetaFields({
aiFeature: {
provider: 'openai',
apiKey: process.env.SANITY_STUDIO_OPENAI_KEY,
model: 'gpt-4o-mini',
},
slugField: 'slug',
bodyField: 'body',
})claude-haiku-4-5 runs at roughly $1–3 per month. Get a key from console.anthropic.com:
1
2
3
4
5
6
7
8
9
seoMetaFields({
aiFeature: {
provider: 'anthropic',
apiKey: process.env.SANITY_STUDIO_ANTHROPIC_KEY,
model: 'claude-haiku-4-5-20251001',
},
slugField: 'slug',
bodyField: 'body',
})All API keys go in environment variables prefixed with SANITY_STUDIO_ so they are available in the browser Studio without being exposed in your frontend.
Most Sanity projects built with a page builder do not have a single body field. Content lives in sections arrays, nested content objects, column layouts sometimes three or four levels deep. The standard bodyField config only reads one field. bodyFields handles complex structures.
Pass an array of paths:
1
2
3
4
5
6
7
8
9
seoMetaFields({
bodyFields: [
'body',
'sections[].content',
'columns[].text',
'hero.description',
],
slugField: 'slug',
})The plugin reads all of them, merges the text, and passes the combined content to the AI provider and to the keyword density analyser. This means the focus keyword analysis and AI generation both see the full page not just one fragment of it.
For deeply nested structures you can also pass Sanity native path arrays:
1
2
3
4
bodyFields: [
['sections', 0, 'content'],
['pageBuilder', '_type', 'textBlock', 'text'],
]GEO stands for Generative Engine Optimization. It is the practice of structuring content so that AI-powered search engines ChatGPT, Perplexity, Google AI Overviews, Bing Copilot can parse, quote, and cite it. These tools do not just link to pages; they extract and reproduce specific passages. If your content is not structured correctly, you will not appear in AI-generated answers even when you rank well in traditional search.
The plugin adds a 5-point GEO checklist that updates live in the SEO panel. Here is what each check does:
AI crawlers consume structured data to understand what type of content a page contains and who authored it. The plugin generates JSON-LD automatically this check passes the moment the plugin is installed with no action required from editors.
AI summarisation tools read meta descriptions as the primary summary signal. A description shorter than 100 characters gives them too little to work with. Longer than 160 and it gets truncated. The sweet spot is 120–150 enough to be a complete, quotable summary. This check enforces that range.
When AI tools cite a page in a response, they often pull the OG image as a visual anchor. Pages without an OG image get cited less frequently and when they are, they appear as text-only, which reduces click-through. This check ensures every page has an image set.
AI search engines rank pages for relevance the same way traditional search does by matching the user's query to page signals. A keyword in both the title and description is the clearest possible relevance signal. This check verifies both are present simultaneously.
Title, description, and image all set in the OG section. Incomplete OG data means AI crawlers fall back to guessing page context from body text which is less accurate and less likely to produce a usable citation. This check requires all three fields to be filled.
Score 5/5 on the GEO checklist and your page is structured correctly for AI citation. Checks 1 and 5 are effectively automatic once structured data is enabled and OG is filled in which most editors do anyway for social sharing. The checklist surfaces the gaps they might otherwise miss.
The plugin stores everything in a seoMetaFields object on each document. Query it with GROQ and pass it into your framework's head management:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
export async function generateMetadata({ params }) {
const post = await client.fetch(query, { slug: params.slug });
const seo = post.seoMetaFields;
return {
title: seo?.metaTitle,
description: seo?.metaDescription,
keywords: seo?.focusKeyword,
robots: {
index: !seo?.noindex,
follow: !seo?.nofollow,
},
alternates: {
canonical: seo?.canonicalUrl,
languages: Object.fromEntries(
(seo?.hreflang || []).map(h => [h.locale, h.url])
),
},
openGraph: {
title: seo?.ogTitle,
description: seo?.ogDescription,
images: [seo?.ogImage?.asset?.url],
},
twitter: {
card: seo?.twitterCard,
title: seo?.twitterTitle,
description: seo?.twitterDescription,
images: [seo?.twitterImage?.asset?.url],
},
};
}1
2
3
4
5
6
7
8
9
const { seoMetaFields: seo } = Astro.props;
---
<title>{seo.metaTitle}</title>
<meta name="description" content={seo.metaDescription} />
<link rel="canonical" href={seo.canonicalUrl} />
<meta property="og:title" content={seo.ogTitle} />
<meta property="og:description" content={seo.ogDescription} />
<meta property="og:image" content={seo.ogImage?.asset?.url} />
<script type="application/ld+json" set:html={JSON.stringify(seo.jsonLd)} />1
2
3
4
5
6
7
8
9
10
11
const { data: post } = await useFetch('/api/post', { query: { slug: route.params.slug } });
const seo = post.value.seoMetaFields;
useSeoMeta({
title: seo.metaTitle,
description: seo.metaDescription,
ogTitle: seo.ogTitle,
ogDescription: seo.ogDescription,
ogImage: seo.ogImage?.asset?.url,
twitterCard: seo.twitterCard,
});1
2
3
4
5
6
7
8
9
10
11
12
// +page.server.ts
export const load = async ({ params }) => {
const post = await client.fetch(query, { slug: params.slug });
return { seo: post.seoMetaFields };
};
// +page.svelte
<svelte:head>
<title>{seo.metaTitle}</title>
<meta name="description" content={seo.metaDescription} />
<link rel="canonical" href={seo.canonicalUrl} />
</svelte:head>sanity-plugin-seo works with Sanity v3, v4, and v5. The plugin API follows Sanity's plugin convention it is a standard definePlugin export with no monkey-patching, so upgrades between Sanity major versions do not break it. Install, configure once, update when you update Sanity.
Package on npm. Full setup docs, AI config, and per-framework examples in the documentation. Feature overview and pricing (all free) on the plugin site. Source under MIT on GitHub. We use it across every project at SW Habitation.
Yes, completely free. Every feature including AI meta generation, GEO checklist, Open Graph previews, JSON-LD, hreflang, and live SEO scoring is available on install. There is no Pro tier or paid plan.
sanity-plugin-seo supports Sanity v3, v4, and v5. It follows the standard Sanity plugin convention so upgrading between major Sanity versions does not break it.
No. AI meta generation is optional. The live SEO score, Open Graph editor, Twitter Card editor, JSON-LD, hreflang, canonical URL, noindex controls, and GEO checklist all work without any AI provider. You only need an API key if you want the Generate button for meta titles and descriptions.
Three providers are supported: Groq (free tier available with llama-3.3-70b-versatile), OpenAI (gpt-4o-mini, roughly $2-5 per month), and Anthropic (claude-haiku, roughly $1-3 per month). Groq is the recommended starting point if you want to try AI generation without any cost.
Yes. The plugin stores SEO data in a seoMetaFields object on each Sanity document. You read it with a GROQ query and pass it into Next.js generateMetadata. The docs include a complete working example for App Router, Pages Router, Astro, Nuxt, SvelteKit, and Remix.
GEO stands for Generative Engine Optimization. It is about structuring your content so AI-powered search tools like ChatGPT, Perplexity, and Google AI Overviews can parse, quote, and cite your pages. Traditional SEO gets you into Google's blue links. GEO gets you into AI-generated answers. The plugin's 5-point checklist verifies the signals these tools rely on: structured data, description length, OG image, keyword placement, and complete Open Graph data.
sanity-plugin-seo covers everything SEO requires in a content-managed site, from the basics editors need every day (meta title, description, Open Graph, score feedback) to the technical layer developers usually have to wire up manually (JSON-LD, hreflang, canonical, noindex) and the emerging layer that most plugins have not caught up with yet (GEO readiness for ChatGPT, Perplexity, and Google AI Overviews).
=> Install once, configure in three lines.
=> Editors get live feedback without leaving Studio.
=> AI generates your meta, editors review, not write.
=> GEO checklist keeps every page ready for AI search citation.
=> Frontend reads one clean seoMetaFields object. Works in Next.js, Astro, Nuxt, SvelteKit, and Remix.
Free and MIT licensed. No Pro tier to unlock, every feature ships on install.