Skip to main content
seofields
docs
.md

API Reference

Complete reference for the plugin's exports, configuration types, and schema types.

Entry Points

sanity-plugin-seofieldsSanity Studio plugin (not RSC-safe)

default export — plugin factory

SeoHealthDashboard, SeoHealthTool, createSeoHealthPane

SchemaOrgDocumentJsonLdPreview

schema helpers, type exports

sanity-plugin-seofields/headFramework-neutral

buildSeoHead, buildSeoMeta

sanitizeOGType, sanitizeTwitterCard

No Studio UI and no React dependency — use in Astro, Nuxt, Vue, SvelteKit, Remix, and custom SSR renderers

sanity-plugin-seofields/next✓ RSC-safe

buildSeoMeta, sanitizeOGType, sanitizeTwitterCard

SeoMetaTags component

SchemaOrgScripts, buildSchemaOrgJsonLd, buildSchemaOrgJsonLds

No Sanity Studio UI — safe in Next.js Server Components & generateMetadata()

Main Export

Import
import seofields from 'sanity-plugin-seofields'
import type { SeoFieldsPluginConfig } from 'sanity-plugin-seofields'

// Usage
seofields(config?: SeoFieldsPluginConfig)

buildSeoMeta(options)

Converts a Sanity SEO object into a structured metadata object compatible with Next.js App Router's Metadata type. Import from sanity-plugin-seofields/next — safe to use in Next.js Server Components and generateMetadata().

buildSeoMeta
import { buildSeoMeta } from 'sanity-plugin-seofields/next'

const metadata = buildSeoMeta({
  seo: data.seo,              // Sanity SEO object (or null/undefined)
  baseUrl: 'https://example.com',
  path: '/about',
  defaults: {
    title: 'My Site',
    siteName: 'My Site',
    twitterSite: '@mysite',
    ogImage: 'https://example.com/og-default.png',
  },
  imageUrlResolver: (img) => urlFor(img).width(1200).url(),
})

// Returns: { title, description, keywords, robots, openGraph, twitter, alternates, other }

<SeoMetaTags>

Framework-agnostic React component that renders all SEO meta tags as plain React elements. Renders <title>, <meta name/property>, and <link rel="canonical">. Import from sanity-plugin-seofields/next to avoid RSC crashes.

SeoMetaTagsProps
import { SeoMetaTags } from 'sanity-plugin-seofields/next'
import type { SeoMetaTagsProps } from 'sanity-plugin-seofields/next'

interface SeoMetaTagsProps {
  data?: Partial<SeoFields> | null       // Raw Sanity SEO object
  baseUrl?: string                       // e.g. "https://example.com"
  path?: string                          // e.g. "/about"
  defaults?: SeoMetaDefaults             // Fallback values
  imageUrlResolver?: (img) => string     // Resolve Sanity image refs
}

SeoFieldsPluginConfig

SeoFieldsPluginConfig
interface SeoFieldsPluginConfig {
  // Root license key for paid features such as Dashboard and Publish Gate.
  licenseKey?: string

  // Sanity Content Lake API version used by the SEO preview's GROQ
  // fetches and the SEO Health Dashboard. Default: '2024-01-01'.
  apiVersion?: string

  // Enable/disable SEO preview (default: false)
  seoPreview?: boolean | {
    prefix?: (document: SanityDocument) => string

    // Static or function-based suffix appended after the SERP title.
    // The same resolved suffix is included in Meta Title validation length checks.
    titleSuffix?: string | ((document: SanityDocument) => string)

    // GROQ query whose result becomes the suffix.
    // Takes priority over titleSuffix when both are set, and is also used by
    // Meta Title validation feedback.
    titleSuffixQuery?: string

    // Match the parent title color (#1a0dab, weight 500) instead of
    // the default muted gray (#70757a, weight 400). Default: false.
    titleSuffixInheritColor?: boolean
  }

  // Base URL for preview generation
  baseUrl?: string

  // Customize field titles and descriptions
  fieldOverrides?: {
    [fieldKey: string]: {
      title?: string
      description?: string
    }
  }

  // Hide fields on specific document types
  fieldVisibility?: {
    [documentType: string]: {
      hiddenFields: string[]
    }
  }

  // Hide fields globally. If keywords is hidden, keyword feedback is skipped
  // on title/description, baseMeta title/description, and OG/X title/description fields.
  defaultHiddenFields?: string[]

  // Show or hide the GEO / AI Overview readiness checklist. Default: true.
  geo?: boolean

  // Show or hide the live HTML meta tags preview panel. Default: true.
  metaTagsPreview?: boolean

  // Auto-populate hreflang entries from document translations.
  hreflang?: {
    autoFill?: boolean
    localeField?: string
    resolvePath?: (translation: HreflangTranslation) => string
  }

  // Group seoFields into tabbed sections in the Studio
  fieldGroups?: Array<{
    name: string
    title: string
    default?: boolean
    fields: string[]
  }>

  // Enable or configure the SEO Health Dashboard tool.
  // Set false to disable. Defaults to true (enabled with defaults).
  healthDashboard?: boolean | {
    tool?: { title?: string; name?: string }
    toolTitle?: string
    content?: {
      icon?: string
      title?: string
      description?: string
      loadingLicense?: string
      loadingDocuments?: string
      noDocuments?: string
    }
    showTypeColumn?: boolean
    showDocumentId?: boolean
    query?: {
      types?: string[]
      requireSeo?: boolean
      groq?: string
    }
    typeDisplayLabels?: Record<string, string>
    typeColumnMode?: 'badge' | 'text'
    titleField?: string | Record<string, string>
    getDocumentBadge?: (doc: DocumentWithSeoHealth) => {
      label: string
      bgColor?: string
      textColor?: string
      fontSize?: string
    } | undefined
    previewMode?: boolean
    export?: boolean | { enabled?: boolean; formats?: Array<'csv' | 'json'> }
    compactStats?: boolean
    structureTool?: string
  }

  ai?: AiConfig

  publishGate?: {
    mode?: 'block' | 'warn'
    minScore?: number
    requiredFields?: Array<
      | 'title'
      | 'description'
      | 'metaImage'
      | 'keywords'
      | 'canonicalUrl'
      | 'openGraph.title'
      | 'openGraph.description'
      | 'openGraph.image'
      | 'openGraph.type'
      | 'twitter.title'
      | 'twitter.description'
      | 'twitter.image'
      | 'twitter.card'
    >
    types?: string[]
    message?: string | ((score: number, issues: string[]) => string)
  }
}

Schema Types

These types are automatically registered when you add the plugin:

seoFieldsComplete SEO field package

title: string (max 70)

description: text (max 160)

canonicalUrl: url

metaImage: image

keywords: string[]

focusKeyword: string

robots: { noIndex, noFollow, noTranslate, noImageIndex }

metaAttributes: metaAttribute[]

hreflangs: { locale, url }[]

geoChecklist: read-only string

metaTagsPreview: read-only string

openGraph: { title, description, url, siteName, type, image }

twitter: { card, site, creator, title, description, image }

baseMetaStandalone core meta fields

title: string (max 70)

description: text (max 160)

metaImage: image

keywords: string[]

canonicalUrl: url

metaAttributes: metaAttribute[]

openGraphStandalone Open Graph configuration

title: string

description: text

url: url

siteName: string

type: 'website' | 'article' | 'profile' | 'book' | 'music' | 'video' | 'product'

imageType: 'upload' | 'url'

image: image

imageUrl: url

twitterX (formerly Twitter) Card settings

card: 'summary' | 'summary_large_image' | 'app' | 'player'

site: string (@handle)

creator: string (@handle)

title: string (max 70)

description: text (max 200)

imageType: 'upload' | 'url'

image: image

imageUrl: url

robotsSearch engine directives

noIndex: boolean

noFollow: boolean

noTranslate: boolean

noImageIndex: boolean

metaTagArray of custom meta attributes

metaAttributes: metaAttribute[]

metaAttributeIndividual meta attribute

key?: string

type?: 'string' | 'image'

value?: string

image?: SanityImage

Schema.org JSON-LD Preview

Schema.org fields include a live Studio preview by default. For a Structure document view, use SchemaOrgDocumentJsonLdPreview.

Document node view
import { SchemaOrgDocumentJsonLdPreview } from 'sanity-plugin-seofields/schema'

S.view
  .component((props) => (
    <SchemaOrgDocumentJsonLdPreview
      {...props}
      baseUrl="https://example.com"
      schemaOrgField="schemaOrg"
      slugField="slug"
      pathPrefix={(doc) => doc._type === 'post' ? 'blog' : ''}
      maxSlugItems={50}
    />
  ))
  .title('JSON-LD')
baseUrl: string
slugField: string
schemaOrgField: string
pathPrefix: string | (doc) => string
urlBuilder: (doc) => string
slugQuery: string
showSlugList: boolean
maxSlugItems: number

TypeScript Types

Type imports
// Main entry
import type {
  SeoFields,          // Full SEO object shape
  OpenGraphSettings,  // openGraph sub-object
  TwitterCardSettings,// twitter sub-object
  RobotsSettings,     // robots sub-object
  MetaAttribute,      // individual metaAttribute item
  SanityImage,
  SanityImageWithAlt,
  SchemaOrgJsonLdPreviewOptions,
  SchemaOrgJsonLdPreviewProps,
} from 'sanity-plugin-seofields'

// /head entry
import type {
  BuildSeoMetaOptions,  // Options for buildSeoHead/buildSeoMeta()
  SeoHead,              // Return type of buildSeoHead()
  SeoHeadMetaTag,       // Plain meta tag object
  SeoHeadLinkTag,       // Plain link tag object
  SeoMetaDefaults,      // defaults sub-object
  SeoMetadata,          // Return type of buildSeoMeta()
  SeoFieldsInput,       // Permissive input type (accepts Sanity codegen output)
} from 'sanity-plugin-seofields/head'

// /next entry
import type {
  SeoMetaTagsProps,     // Props for <SeoMetaTags>
  SchemaOrgScriptsProps,// Props for <SchemaOrgScripts>
} from 'sanity-plugin-seofields/next'

Field Override Keys

Available keys for fieldOverrides and fieldVisibility.hiddenFields:

Core

titledescriptioncanonicalUrlmetaImagekeywordsmetaAttributesrobotsfocusKeywordhreflangsgeoChecklistmetaTagsPreview

Open Graph

openGraphUrlopenGraphTitleopenGraphDescriptionopenGraphSiteNameopenGraphTypeopenGraphImageTypeopenGraphImageopenGraphImageUrl

X (Twitter)

twitterCardtwitterSitetwitterCreatortwitterTitletwitterDescriptiontwitterImageTypetwitterImagetwitterImageUrl

Was this page helpful?