JSON-LD for Headless CMS Content: Article, FAQ, Breadcrumb, and Product Schema

Add structured data (JSON-LD) to headless CMS-driven pages. Learn which schemas matter, how to model them in your CMS, and how to render valid JSON-LD in Next.js.

R
Raşit Apalak
4 min read

Structured data helps search engines understand your pages and can unlock rich results (FAQ, breadcrumbs, product snippets). In a headless setup, the best approach is to model structured data inputs in your CMS and render JSON-LD server-side.

This guide focuses on the practical schemas most CMS-driven sites need:

  • Article
  • FAQPage
  • BreadcrumbList
  • Product

Table of Contents


How JSON-LD works (quickly)

JSON-LD is a <script type="application/ld+json"> block in your HTML. It doesn’t change what users see; it provides machine-readable meaning:

  • what the page is (Article / Product / FAQ)
  • who published it
  • what the key entities are

You can include multiple JSON-LD blocks per page.


What to model in the CMS vs generate in code

Good rule:

  • Model in CMS: content editors own it
    • headline, description, author, FAQ Q/A, product name, offers, etc.
  • Generate in code: derived from routing and site config
    • canonical URL, breadcrumb URLs, publish organization, site logo URL

Avoid letting editors paste raw JSON-LD unless you truly need a “custom schema” escape hatch—otherwise you’ll fight invalid JSON and inconsistent structure.


Article schema (blog posts)

Use Article schema for blog posts and long-form content.

Model fields (typical):

  • title (headline)
  • description (excerpt)
  • slug
  • publishedAt
  • updatedAt (optional)
  • coverImage (optional)
  • authorName (or author reference)

Then generate JSON-LD with:

  • @type: Article (or BlogPosting)
  • headline
  • datePublished
  • dateModified (if you have it)
  • image (if you have cover image)
  • author and publisher

If you don’t have authors as content, a simple site-wide author works fine.


FAQ schema (FAQPage)

FAQ schema can produce rich results, but only if the FAQ content is actually visible on the page.

Model a FAQ section as structured fields:

  • items[]:
    • question
    • answer (plain text is safest; rich text is okay if you strip markup)

JSON-LD shape:

  • @type: FAQPage
  • mainEntity: array of Question objects

Important: don’t add FAQ schema to pages without real FAQs; that’s considered spammy.


Breadcrumb schema is great for:

  • blog categories
  • docs hierarchies
  • multi-level marketing pages

You usually generate it from routing + CMS metadata:

  • Home → Blog → Category → Post

Model in CMS only what you can’t infer:

  • category title/slug
  • page title/slug

Then generate breadcrumb items as:

  • position 1..n
  • name
  • item (absolute URL)

Product schema

Product schema is for e-commerce, pricing catalogs, and product landing pages where a product/offer is the page’s primary subject.

Model fields:

  • product name
  • description
  • brand (optional)
  • image(s)
  • sku (optional)
  • offers:
    • price
    • currency
    • availability
    • url

If you have multiple plans (pricing tiers), consider:

  • Product page with multiple offers
  • or separate “Plan” pages if each plan has its own landing page

How to render JSON-LD in Next.js safely

In Next.js, render JSON-LD server-side and inject it as a script tag.

Key safety rules:

  • Build the JSON object in code (don’t concat strings).
  • Use JSON.stringify(schemaObject) and inject it in a script tag.
  • Avoid including user-generated HTML in schema fields.

If you have multiple schemas:

  • one script per schema, or
  • one @graph with multiple nodes

Validation checklist

Before shipping:

  • Validate with Google’s Rich Results Test and Schema Markup Validator
  • Make sure URLs are absolute and canonical
  • Dates are ISO 8601
  • Schema matches visible content
  • No contradictory fields (e.g. availability vs price missing)

If you want to expand structured data next:

  • Organization + Website
  • Sitelinks search box (for big sites)
  • HowTo schema (for step-by-step posts)
Share this post:

Related posts