Sanity Seo Plugin
The sanity-plugin-seo Plugin is designed to simplify the process of generating SEO fields for various types of content.
Install command
npm i sanity-plugin-seo
β‘ Sanity Plugin SEO
Sanity Studio Compatibility:
Framework Support:
The complete SEO toolkit for Sanity Studio. Empower your team with live SEO scoring, AI-powered content suggestions, team workflows, and comprehensive structured data support.
Production-Ready: Free and AI tiers live. Pro features coming soon with team workflows, bulk optimization, and schema management.
Demo Video

Complete Feature Set
Everything from basic SEO optimization to advanced team workflows.
| Feature | Free | AI | π Pro |
|---|---|---|---|
| Live SEO Score (0β100) | β | β | β |
| GEO Checklist (AI Overview readiness) | β | β | β |
| Meta Tags Preview + HTML snippet | β | β | β |
| Social Preview Cards (X, Facebook, LinkedIn, WhatsApp) | β | β | β |
| Focus Keyword tracking | β | β | β |
| Robots Meta (noindex, nofollow, noarchiveβ¦) | β | β | β |
| hreflang / multi-language targeting | β | β | β |
| Open Graph & Twitter/X card fields | β | β | β |
| Additional meta tags | β | β | β |
| Frontend integration guides (Next.js, Astro, Vue) | β | β | β |
| Readability score | β | β | β |
| AI Keyword Suggestions | β | β | β |
| AI Meta Title & Description generation | β | β | β |
| SERP Preview (desktop + mobile) | β | β | π |
| Schema.org Wizard (30+ structured data types) | β | β | π |
| Live JSON-LD preview | β | β | π |
| SEO Health Dashboard (site-wide scores) | β | β | π |
| SEO Optimizer β inline bulk edit, type filter, CSV import/export | β | β | π |
| Bulk Open Graph sync | β | β | π |
| Advanced Validation (5 checks + auto-fix) | β | β | π |
| Team Workflow (Draft β Review β Approved) | β | β | π |
| Workflow Dashboard (site-wide status tracking) | β | β | π |
| Duplicate meta title detection | β | β | π |
| AI Bulk SEO Generation | β | β | π |
What Each Tier Includes
π Free β Essential SEO tools built-in. Start optimizing immediately.
π€ AI β Add AI-powered suggestions. Choose from OpenAI, Anthropic, or Groq (free tier available).
π₯ Pro β Coming Soon. Team workflows, bulk optimization, advanced analytics, and schema management for enterprise teams.
Table of Contents
- Quick Start
- Configuration Options
- Framework Integration Guides
- GROQ Fragment & Types
- Body Fields
- AI Provider Setup
- Pro Features β Coming Soon
- Upgrading from v1.3
Quick Start
1. Install the plugin
npm install sanity-plugin-seoOr with yarn/pnpm:
yarn add sanity-plugin-seo # or
pnpm add sanity-plugin-seoCompatibility: Sanity Studio v3, v4, and v5
2. Configure in Sanity Studio
Option A: Free features only
// sanity.config.ts
import { defineConfig } from "sanity";
import { seoMetaFields } from "sanity-plugin-seo";
export default defineConfig({
plugins: [seoMetaFields()],
});Option B: With AI (OpenAI, Anthropic, or Groq)
Add AI-powered suggestions for meta titles, descriptions, and keywords.
import { defineConfig } from "sanity";
import { seoMetaFields } from "sanity-plugin-seo";
export default defineConfig({
plugins: [
seoMetaFields({
aiFeature: {
provider: "openai", // 'openai' | 'anthropic' | 'groq'
apiKey: process.env.SANITY_STUDIO_OPENAI_KEY!,
model: "gpt-4o-mini", // optional
},
bodyFields: ["body"], // single field β or pass multiple, see bodyFields docs below
slugField: "slug",
}),
],
});Option C: With Pro license (Coming Soon)
Unlock team workflows, bulk optimization, and advanced schema management.
seoMetaFields({
proFeature: process.env.SANITY_STUDIO_SEO_LICENSE!,
projectId: process.env.SANITY_STUDIO_PROJECT_ID!,
});| Env variable | Value |
|---|---|
SANITY_STUDIO_SEO_LICENSE | Your license key from Lemon Squeezy |
SANITY_STUDIO_PROJECT_ID | Your Sanity project ID (find it in sanity.json or manage.sanity.io) |
Sanity Studio env vars must be prefixed with
SANITY_STUDIO_to be included in the browser bundle.
Complete Configuration
import { defineConfig } from "sanity";
import { seoMetaFields } from "sanity-plugin-seo";
export default defineConfig({
plugins: [
seoMetaFields({
// AI provider (OpenAI, Anthropic, or Groq)
aiFeature: {
provider: "openai", // 'openai' | 'anthropic' | 'groq'
apiKey: process.env.SANITY_STUDIO_OPENAI_KEY!,
model: "gpt-4o-mini",
},
// Body content fields for AI analysis β string, string path, or Sanity path array
bodyFields: [
"body", // simple field
"sections[].content", // array traversal
["sections", "columns", "body"], // Sanity native path array
],
slugField: "slug",
// Show SEO Health + Optimizer in Studio toolbar (default: true)
dashboard: true,
}),
],
});3. Add SEO to Your Documents
Add the seoMetaFields type to any document schema in your project:
// schemas/page.ts
export default {
name: "page",
type: "document",
fields: [
{ name: "title", type: "string" },
{ name: "slug", type: "slug", options: { source: "title" } },
{ name: "body", type: "array", of: [{ type: "block" }] },
{ name: "seo", type: "seoMetaFields" },
],
};This adds a fully-featured SEO panel with four tabs:
- Basic SEO β Meta title, description, keywords
- Social Sharing β Open Graph & Twitter cards
- Advanced β Robots meta, hreflang, custom tags
- Schema.org β 30+ structured data types (Pro)
Configuration Options
All options are optional. The plugin works great with zero configuration.
| Option | Type | Default | Description |
|---|---|---|---|
| Content Fields | |||
bodyField | string | 'body' | Single body field name (legacy β prefer bodyFields) |
bodyFields | Array<string | string[]> | β | One or more body field paths; each item is a string path ('sections[].content') or a Sanity path array (['sections','content']) |
slugField | string | 'slug' | Slug field for URL preview in SERP |
| AI Features | |||
aiFeature | object | β | Enable AI keyword and content suggestions |
aiFeature.provider | 'openai' | 'anthropic' | 'groq' | β | AI provider (OpenAI/Anthropic/Groq) |
aiFeature.apiKey | string | β | API key from your provider |
aiFeature.model | string | provider default | Model ID (e.g., gpt-4o-mini, claude-haiku-4-5-20251001) |
| Pro Features | |||
proFeature | string | β | Your Lemon Squeezy license key |
projectId | string | β | Your Sanity project ID β used for seat-binding (required for Pro) |
| UI | |||
dashboard | boolean | true | Show SEO Health & Optimizer in Studio toolbar |
Framework Integration Guides
Complete copy-paste guides with GROQ queries, TypeScript types, and JSON-LD helpers are on the docs site.
Next.js
Works with both App Router (generateMetadata) and Pages Router (next-seo). Includes a buildMetadata helper and JSON-LD support.
Astro
Works with astro-seo or native <head> tags. Includes Sanity client setup and a buildJsonLd helper.
β Full Astro guide
Vue 3 / Nuxt
Works with Nuxt 3 (useHead) and Vue 3 standalone (@unhead/vue). Uses @sanity/client directly β no @nuxtjs/sanity needed.
SvelteKit
Works with SvelteKit's +page.server.ts load function and <svelte:head> for meta tags.
GROQ Fragment & Types
Copy and use this GROQ fragment to fetch all SEO fields from your documents:
const pageQuery = groq`*[_type == "page" && slug.current == $slug][0]{
title,
seo {
metaTitle, metaDescription, focusKeyword, seoKeywords,
nofollowAttributes, robotsMeta,
metaImage { asset->{ url } },
openGraph { title, description, siteName, image { asset->{ url } } },
twitter { cardType, site, creator, handle },
hreflang[] { locale, url },
schemaOrg {
schemaType, name, description, url, author,
datePublished, dateModified,
price, priceCurrency, availability,
ratingValue, ratingCount,
startDate, endDate, location,
faqItems[] { question, answer }
},
seoStatus, seoReviewNotes
}
}`;| Field | Type | Notes |
|---|---|---|
metaTitle | string | Page title for search engines |
metaDescription | string | Page description |
focusKeyword | string | Primary keyword |
seoKeywords | string[] | Additional keywords |
nofollowAttributes | boolean | Noindex toggle |
robotsMeta | string[] | e.g. ['noindex', 'nofollow'] |
metaImage.asset.url | string | Fallback OG/Twitter image |
openGraph.title | string | OG title |
openGraph.description | string | OG description |
openGraph.siteName | string | OG site name |
openGraph.image.asset.url | string | OG image |
twitter.cardType | string | e.g. summary_large_image |
twitter.site | string | Twitter @account |
twitter.creator | string | Twitter @author |
hreflang[].locale | string | BCP 47 locale code |
hreflang[].url | string | Alternate URL for that locale |
schemaOrg.schemaType | string | Schema.org type |
seoStatus | string | draft | review | approved |
seoReviewNotes | string | Reviewer notes |
Body Fields (bodyFields)
bodyFields accepts an array where each item is either a string path or a Sanity path array:
seoMetaFields({
bodyFields: [
"body", // simple field
"excerpt", // plain string or Portable Text
"sections[].content", // string with '[]. ' array traversal
"sections[].columns[].body", // nested array traversal
["sections", "columns", "content"], // Sanity native path array
],
});Path formats
| Item | Resolves to |
|---|---|
"body" | document.body |
"sections[].content" | .content from every item in document.sections |
"sections[].columns[].body" | nested array traversal |
["sections", "columns", "body"] | document.sections.columns.body (direct path, no iteration) |
Fields are resolved in order β earlier fields are higher priority when the AI prompt trims to 2000 characters.
bodyField: "body"(single string) still works and is kept for backwards compatibility.bodyFieldstakes precedence when both are set.
Free Features
Readability Score
Calculates a Flesch-Kincaid Grade Level for your content and shows it with color-coded feedback directly beneath the body field.
| Grade | Meaning |
|---|---|
| 1β6 | Very easy β general public |
| 7β8 | Easy β ideal for most blog posts |
| 9β12 | Average β acceptable for technical content |
| 13+ | Difficult β academic/specialist |
Green = Grade β€ 8, Amber = 9β12, Red = 13+.
Pro Features (Coming Soon)
Team workflows, bulk optimization, SERP preview, Schema.org wizard, advanced validation, and site-wide dashboards β all in development.
Star the GitHub repo to get notified when Pro launches.
AI Provider Setup
Three AI providers supported. Choose based on your needs and budget.
OpenAI (Paid)
seoMetaFields({
aiFeature: {
provider: "openai",
apiKey: process.env.SANITY_STUDIO_OPENAI_KEY!,
model: "gpt-4o-mini",
},
bodyFields: ["body"],
});Recommended: gpt-4o-mini (fast), gpt-4o (better quality)
Anthropic (Paid)
seoMetaFields({
aiFeature: {
provider: "anthropic",
apiKey: process.env.SANITY_STUDIO_ANTHROPIC_KEY!,
model: "claude-haiku-4-5-20251001",
},
bodyFields: ["body"],
});Recommended models: claude-haiku-4-5-20251001 (fast & cheap), claude-sonnet-4-6 (best quality)
Groq (Free)
seoMetaFields({
aiFeature: {
provider: "groq",
apiKey: process.env.SANITY_STUDIO_GROQ_KEY!,
model: "llama-3.3-70b-versatile",
},
bodyFields: ["body"],
});Free API: Sign up at console.groq.com
Recommended models: llama-3.3-70b-versatile, mixtral-8x7b-32768
β οΈ Security Note: API keys are bundled in the browser. Always use restricted API keys with minimal permissions, and prefix env vars with
SANITY_STUDIO_.
Upgrading from v1.3 to v1.4
Good news: No schema migrations needed. All existing SEO fields continue to work. Just update your config.
What Changed
The basic setup works exactly the same:
// v1.3 and v1.4 β no changes needed
plugins: [seoMetaFields()];New in v1.4: AI and Pro features are now available with renamed config keys:
| Feature | Config Key (v1.4) |
|---|---|
| AI suggestions | aiFeature |
| Pro license | proFeature |
See AI Provider Setup and Pro License Setup for configuration examples.
New Fields in v1.4
These new schema fields are optional and automatically included:
| Field | Type | Purpose |
|---|---|---|
focusKeyword | string | Primary target keyword for tracking |
robotsMeta | string[] | Indexing control (noindex, nofollow, noarchive, nosnippet) |
hreflang | array | Alternate language/regional URLs |
additionalMetaTags | array | Custom name/content meta tag pairs |
schemaOrg | object | Schema.org structured data (Pro feature) |
seoStatus | string | Workflow status: draft, review, approved (Pro feature) |
seoReviewNotes | string | Reviewer feedback and notes (Pro feature) |
Existing documents work fine without these new fields β they're completely optional.
TypeScript Types
interface SeoData {
metaTitle?: string;
metaDescription?: string;
focusKeyword?: string;
seoKeywords?: string[];
nofollowAttributes?: boolean;
robotsMeta?: string[];
metaImage?: { asset: { url: string } };
openGraph?: {
title?: string;
description?: string;
siteName?: string;
image?: { asset: { url: string } };
};
twitter?: {
cardType?: string;
site?: string;
creator?: string;
handle?: string;
};
hreflang?: { locale: string; url: string }[];
schemaOrg?: {
schemaType?: string;
name?: string;
description?: string;
url?: string;
author?: string;
datePublished?: string;
dateModified?: string;
price?: string;
priceCurrency?: string;
availability?: string;
ratingValue?: string;
ratingCount?: string;
startDate?: string;
endDate?: string;
location?: string;
faqItems?: { question: string; answer: string }[];
};
seoStatus?: "draft" | "review" | "approved";
seoReviewNotes?: string;
}Support & Community
- Bug Reports: GitHub Issues
- NPM Package: sanity-plugin-seo
Creator
Built by Bhargav Patel
License
MIT β Free and AI features are open source. Pro coming soon.