Dev 6 Feb 2026 11 min read

Headless CMS SEO Guide: Contentful, Sanity & Storyblok

Headless CMS gives you speed and deployment flexibility — but it introduces SEO risks around metadata, canonical URLs, and structured data that traditional CMS platforms handle automatically. Here's how to solve each one.

Moving from WordPress, Squarespace, or Webflow to a headless architecture is one of the most performance-positive decisions a development team can make. Next.js with Contentful or Sanity on the backend produces pages that score 90+ on Core Web Vitals out of the box. But it also removes the guardrails that traditional CMS platforms provide for SEO — and teams who aren't proactive about this discover the gap the hard way, after launch.

The Headless SEO Checklist

Before we dive into platform-specific guidance, here are the core SEO concerns in every headless implementation:

Metadata

  • Title tags per page
  • Meta descriptions
  • Open Graph tags
  • Twitter Cards

Canonical URLs

  • Self-referencing canonicals
  • Cross-domain handling
  • Pagination canonicals
  • Preview URL prevention

Structured Data

  • Article / BlogPosting schema
  • Breadcrumb schema
  • Product schema (e-com)
  • FAQPage schema

Rendering

  • SSR or SSG (not CSR)
  • Crawlable on first response
  • No JS required for content
  • Robots.txt / Sitemap

Metadata Architecture in Next.js + Headless CMS

In Next.js App Router, metadata is defined via the generateMetadata function, which can fetch data from your CMS:

// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug); // fetch from Contentful/Sanity
  return {
    title: post.seoTitle || post.title,
    description: post.seoDescription,
    alternates: { canonical: `https://yoursite.com/blog/${params.slug}` },
    openGraph: {
      title: post.ogTitle || post.title,
      description: post.ogDescription,
      images: [{ url: post.ogImage?.url }],
    },
  };
}

CMS Content Model for SEO Fields

Add these fields to every content type in your CMS:

  • seoTitle — Short text, max 60 chars, optional override of page title
  • seoDescription — Short text, max 160 chars
  • canonicalUrl — Short text, optional override for edge cases
  • noindex — Boolean, for draft pages, tag pages, etc.
  • ogImage — Media/Asset field for social sharing image

Platform-Specific Notes

Contentful

Contentful's content model is schema-based and type-safe. Create a "SEO" content type and include it as a reference field in your Page and Blog Post types. Use the contentful SDK with TypeScript types generated from your schema for reliable data fetching. Note: Contentful's preview API uses different base URLs — always validate that your canonical tags point to your production domain, not Contentful's preview URLs.

Sanity

Sanity's GROQ query language is extremely powerful for fetching structured data. Define a seo object in your schema with all metadata fields, then query it alongside your page content:

// GROQ query
const query = groq`*[_type == "post" && slug.current == $slug][0]{
  title,
  "seo": seo{ title, description, image{ asset->{ url } } }
}`

Storyblok

Storyblok's visual editor is excellent for non-technical teams but requires careful setup for SEO. Use the storyblok-rich-text-renderer for blog content and ensure your renderer outputs proper HTML heading hierarchy (H1 once, H2/H3 for structure). The bridge.js Storyblok provides for live preview can conflict with Google's rendering — ensure it only loads in preview mode, never in production.

Validating Your Headless SEO Implementation

After launch, validate every key page type using our free comparison tools. Check that your meta tags match your design with the Meta Tag Comparison tool, validate structured data with the Schema Validator, and confirm redirects are correct with the Redirect Checker. Run all pages through the Bulk URL Checker to catch any 404s before they impact rankings.

Frequently Asked Questions

Is headless CMS good for SEO?
Yes, when implemented correctly. Headless CMS paired with Next.js or similar frameworks produces statically generated or server-rendered HTML, which Google crawls excellently. The SEO risks arise from incorrect metadata setup, missing canonical tags, or improperly rendered structured data — all of which are solvable.
Does Google crawl JavaScript-rendered content from headless CMS?
Google can crawl client-side JavaScript, but it's slower and less reliable than static HTML. For SEO-critical pages, always use server-side rendering (SSR) or static site generation (SSG) with Next.js. Never rely on client-side rendering alone for content you want indexed.
How do I add structured data to a headless CMS?
The most reliable approach is generating JSON-LD structured data in your Next.js page component using data fetched from the CMS. This ensures the schema is rendered in the initial HTML response. Alternatively, add schema fields directly to your CMS content model and map them to JSON-LD templates.
What is the SEO difference between Contentful, Sanity, and Storyblok?
The CMS itself has minimal direct SEO impact — it's how you implement the frontend that matters. Contentful has the most mature ecosystem and documentation. Sanity's GROQ query language is powerful for complex data relationships. Storyblok includes a visual editor that non-technical editors prefer. Choose based on team requirements, not SEO.
How do I handle canonical URLs in a headless CMS setup?
Define canonical URLs explicitly in your CMS content model as a field editors can override. For default canonicals, generate them programmatically from the page slug and your base URL in Next.js metadata. Never rely on the CMS preview URL as a canonical — always point to the production domain.

Validate Your Headless CMS Migration

Free tools to check meta tags, schema, redirects, and URL health post-launch.