Skip to main content
seofields

General

What is sanity-plugin-seofields?
sanity-plugin-seofields is a comprehensive SEO management plugin for Sanity Studio (v3/v4/v5). It adds a single seofields object field to any document schema and exposes meta tags, Open Graph, Twitter/X Cards, robots directives, canonical URLs, a live SERP preview, Schema.org structured-data helpers, and a studio-wide SEO Health Dashboard — all with zero-config.
Is it compatible with Sanity Studio v3, v4, and v5?
Yes. The plugin is fully compatible with Sanity Studio v3, v4, and v5. It follows the official Sanity plugin API and does not use any deprecated internals, so it will continue to work across future minor releases.
Is it free to use?
Most features are completely free with no strings attached. The SEO Health Dashboard requires a free license key during the introductory period. Once paid access launches, existing key holders pay a one-time fee of $10 — no subscription, ever.
Do I need a license key for basic SEO fields?
No. Meta tags, Open Graph, Twitter/X Cards, robots directives, SERP preview, Schema.org helpers, and field-visibility controls are all free without a license key. A key is only required to unlock the SEO Health Dashboard.
Where do I get a license key?
Visit sanity-plugin-seofields.thehardik.in/get-license, enter your email and Sanity project ID, and your key will be emailed to you instantly — no payment required during the free period.

Meta Tags

Which meta tag fields does the plugin add?
The plugin adds: SEO Title (recommended ≤ 60 chars), Meta Description (recommended ≤ 160 chars), Keywords (comma-separated), and Canonical URL. Each field includes inline character-count guidance and validation helpers.
Are there character limits enforced on meta titles and descriptions?
The plugin provides soft guidance — a live character counter that turns amber at 55 characters and red at 60 for titles (or 150/160 for descriptions). Hard validation is intentionally avoided so editors retain control, but the SERP preview reflects the truncated result Google would show.
How do I output the canonical URL in my frontend?
Query seo.canonicalUrl via GROQ and pass it to <link rel="canonical" href={...} />. In Next.js App Router you can set it inside the metadata.alternates.canonical property returned from generateMetadata().
Can I customise the default fallback for the SEO title?
Yes. In your plugin config you can pass a titleTemplate function that receives the document title and returns a string used when the editor leaves the SEO title blank — e.g. (t) => `${t} | My Site`.

Open Graph

Which Open Graph fields are included?
The plugin includes OG Title, OG Description, OG Image (with Sanity image asset picker), and OG Type (website, article, product, profile, video.movie, etc.). All fields are optional and fall back gracefully to the base meta fields when left empty.
How do I generate the OG image URL in my frontend?
Use imageUrlBuilder from @sanity/image-url: urlFor(doc.seo.ogImage).width(1200).height(630).url(). This returns an optimised CDN URL that Facebook and LinkedIn accept.
What OG types are supported?
The selector covers the most common open-graph types: website, article, book, profile, music.song, music.album, video.movie, video.episode, and product.

Twitter / X Cards

Which Twitter/X Card types are supported?
The plugin supports summary (small square image) and summary_large_image (full-width banner). The card type selector is shown only when a Twitter image is provided, keeping the UI clean for documents that don't need it.
Can I set a separate image for Twitter vs Open Graph?
Yes. The plugin has dedicated Twitter Image and Twitter Card Type fields independent of the OG image. If you leave the Twitter image empty, the OG image is used as a fallback, which is standard practice.
How do I render the Twitter meta tags in Next.js?
Return a twitter object from generateMetadata(): { card: doc.seo.twitterCardType, title: doc.seo.twitterTitle ?? doc.seo.ogTitle, description: doc.seo.twitterDescription, images: [twitterImageUrl] }.

Robots Directives

What robots directives can I control per document?
Editors can toggle index / noindex and follow / nofollow independently, control noarchive and nosnippet, and set a sitemap priority (0.0–1.0) and changefreq value per document.
How do I apply the noindex directive in my Next.js app?
In generateMetadata(), map the GROQ result to robots: { index: doc.seo.index !== false, follow: doc.seo.follow !== false }. Next.js automatically renders the appropriate <meta name="robots"> tag.
Does the plugin generate a sitemap automatically?
The plugin itself does not generate a sitemap file — that belongs in your frontend. It does expose seo.sitemapPriority and seo.changefreq fields so your sitemap generation code can read them via GROQ and include the correct values.

SERP Preview

What does the SERP Preview show?
The SERP Preview renders a live, pixel-accurate approximation of how the document will appear in Google Search results (desktop and mobile), including title truncation at ~580px, the green URL breadcrumb, and the meta description snippet. It updates in real time as editors type.
Is there a social preview too?
Yes. Next to the Google preview there is an Open Graph / social preview card that simulates how the document link will appear when shared on Facebook, LinkedIn, and similar platforms — showing the OG image, title, and description at the correct 1.91:1 aspect ratio.
Can I disable the SERP preview if I don't need it?
Pass showSerpPreview: false in the plugin options: seofields({ showSerpPreview: false }). The preview component is tree-shaken from the bundle when disabled.

SEO Health Dashboard

What is the SEO Health Dashboard?
The Health Dashboard is a studio-wide tool (accessible from the Sanity Studio toolbar) that scores every document on a 100-point scale across six dimensions: meta completeness, Open Graph completeness, robots configuration, SERP title length, description length, and Schema.org coverage.
What factors affect the 100-point SEO score?
Points are allocated roughly as: SEO title present and within length (20 pts), meta description present and within length (20 pts), canonical URL set (10 pts), OG title + image present (15 pts), Twitter card set (10 pts), robots index/follow enabled (10 pts), Schema.org type configured (15 pts). Partial credit is given for fields that exist but exceed recommended limits.
How do I fix issues flagged by the dashboard?
Each row in the dashboard shows a colour-coded score badge and a list of failing checks. Click Fix next to any document to jump directly to that document in the Studio editor. The dashboard re-scores in real time after you save changes.
Can I filter the dashboard by document type or score range?
Yes. The dashboard toolbar includes filters for document type, score range (e.g. show only documents scoring below 50), and a search box for document title. All filters persist across sessions using localStorage so you pick up where you left off.
Does the dashboard support pagination?
Yes. The dashboard paginates results in batches of 25, 50, or 100 rows. A compact mode toggle reduces row height so more documents fit on screen simultaneously.
Can I export the dashboard results?
Yes. Use the Export button in the dashboard toolbar to download results as CSV or JSON. The export respects the active filters, so you can export only the under-performing documents.
Does the dashboard require a license key?
Yes. The SEO Health Dashboard requires a free license key tied to your Sanity project ID. Add it to your plugin config: seofields({ licenseKey: 'YOUR_KEY' }). Get a key at /get-license.

Schema.org Structured Data

Which Schema.org types does the plugin support?
The plugin ships with 24 Schema.org types, including Article, BlogPosting, WebPage, WebSite, Product, FAQPage, HowTo, Event, Person, Organization, LocalBusiness, BreadcrumbList, Recipe, Review, NewsArticle, VideoObject, ImageObject, SoftwareApplication, JobPosting, Course, Movie, Book, MusicRecording, and Service.
How do I add Schema.org fields to my document schema?
Import the helper and add it as a field: import { schemaOrgField } from "sanity-plugin-seofields" then include schemaOrgField() in your fields array. The field renders a type selector and contextual input fields for the chosen Schema.org type.
Does the plugin output JSON-LD automatically?
The plugin stores structured data as plain JSON in your Sanity dataset. It does not inject <script type="application/ld+json"> tags server-side — that is intentionally left to your frontend so you keep full control over rendering and hydration.
How do I render the JSON-LD in Next.js?
Query seo.schemaOrg via GROQ and output: <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(doc.seo.schemaOrg) }} /> inside your page component. For App Router, place it inside the root <head> via a layout or a generateMetadata export.

Field Visibility

Can I hide fields I don't need?
Yes. Pass a fields config object to the plugin to selectively enable or disable groups: seofields({ fields: { twitter: false, schemaOrg: false } }). Hidden field groups are excluded from the schema entirely, keeping the editor UI lean.
Can I show fields conditionally based on document values?
Yes. Each field group accepts a hidden callback using Sanity's standard conditional-fields API: seofields({ fields: { schemaOrg: { hidden: ({ document }) => document.type !== 'article' } } }).

CLI

Does the plugin include a CLI?
Yes. The package ships a lightweight CLI accessible via npx sanity-plugin-seofields (or the seofields binary after local install). It currently exposes two commands: validate and audit.
What does the validate command do?
Run npx sanity-plugin-seofields validate in your project root. It checks your sanity.config.ts to confirm the plugin is registered correctly, verifies your license key format (if present), and warns about deprecated config options — useful in CI pipelines.
What does the audit command do?
Run npx sanity-plugin-seofields audit --projectId <id> --dataset <name> --token <token>. It fetches every published document that uses the seofields object and outputs a scored report to stdout (or a file with --output report.json) — the same scoring logic as the in-studio dashboard but usable in scripts and CI.

Frontend Integration

What does the GROQ query for SEO fields look like?
*[_type == "page" && slug.current == $slug][0] {
  title,
  "seo": seo {
    metaTitle,
    metaDescription,
    canonicalUrl,
    ogTitle,
    ogDescription,
    ogImage,
    twitterCardType,
    twitterImage,
    index,
    follow,
    schemaOrg
  }
}
How do I use the SEO data in Next.js generateMetadata()?
Fetch the document server-side and map the fields: return { title: seo.metaTitle, description: seo.metaDescription, alternates: { canonical: seo.canonicalUrl }, robots: { index: seo.index, follow: seo.follow }, openGraph: { title: seo.ogTitle, images: [ogImageUrl] } }.
How do I generate a CDN image URL for the OG image?
Install @sanity/image-url and create a builder: import imageUrlBuilder from "@sanity/image-url"; const builder = imageUrlBuilder(client); const urlFor = (source) => builder.image(source); Then call urlFor(seo.ogImage).width(1200).height(630).url().

License & Pricing

What is the pricing model?
The plugin uses an open-core model. All SEO field features are MIT-licensed and always free. The SEO Health Dashboard requires a license key. During the introductory period the key is free; after that, a one-time payment of $10 USD per project unlocks it permanently — no recurring subscription.
What does the free period include?
During the free period (estimated 1–2 months from launch) you get full access to the SEO Health Dashboard — scoring, filtering, export, pagination, compact mode, and audit CLI — at no cost. Grab a key now to lock in free access.
How does the license key work technically?
The license key is a signed JWT bound to your Sanity project ID. On startup the plugin verifies the key signature client-side; no network call is made at runtime. Keys do not expire — once issued they remain valid for the lifetime of that project.
Can I use one license key across multiple environments (dev/staging/prod)?
Yes. A key is bound to a Sanity project ID, not a deployment URL. As long as all environments (local, staging, production) connect to the same Sanity project, one key covers all of them.
What happens when the free period ends?
If you already have a key, nothing changes immediately — your key keeps working. Once paid access launches, a grace period allows you to complete the one-time $10 payment. After the grace period, the dashboard requires a paid key. The core SEO fields remain free regardless.

Still have a question?

Open an issue on GitHub or check the full documentation.