Search engines like Google donΓÇÖt just look at your websiteΓÇÖs design and content ΓÇö they also care about how clearly your content is structured. ThatΓÇÖs where structured schema markup comes in. By adding schema, you help search engines understand your pages, which can boost visibility with rich results like star ratings, breadcrumbs, or FAQs.
In this article, weΓÇÖll show you:
Schema markup uses schema.org vocabulary to label your content. For example, a blog post can be explicitly marked as a BlogPosting
with details like title, author, and publish date.
Benefits:
How Hooks Work in Payload CMS
Payload CMS provides lifecycle hooks (like beforeChange, afterRead, etc.) that let you run custom logic when a document is created, updated, or fetched.
WeΓÇÖll use these hooks to auto-generate JSON-LD schema markup whenever content is saved or fetched.
First, extend your collection (for example, BlogPosts
) with a schemaMarkup
field to hold JSON schema data.
import type { CollectionConfig } from 'payload'
export const BlogPosts: CollectionConfig
= { slug: 'blog-posts'
, fields
: [
{ name: 'title'
, type: 'text'
, required: true
,
},
{ name: 'author'
, type: 'relationship'
, relationTo: 'authors'
, required: true
,
},
{ name: 'publishDate'
, type: 'date'
,
},
{ name: 'schemaMarkup'
, type: 'json'
, admin
: { readOnly: true, // prevent editors from overwriting
},
},
],}
With this hook, Payload will generate schema JSON-LD whenever an entry is created or updated.
hooks
: { afterChange
: [ async
({ data,operation,req }) => { if (operation === 'create' || operation === 'update') { const schema
= { "@context": "https://schema.org"
, "@type": "BlogPosting"
, "headline": data.title
, "author"
: { "@type": "Person"
, "name": data.author?.name || "Unknown"
,
}, "datePublished": data.publishDate
, "publisher"
: { "@type": "Organization"
, "name": "My Company"
,
},
} doc.schemaMarkup= schema
return doc
} }],}
In your frontend (e.g., Next.js), embed schema markup into <head>
with JSON-LD
.
import Head from 'next/head'
export default function BlogPage({ post }
) { return
( <>
<Head
> <script type="application/ld+json">
{JSON.stringify(post.schemaMarkup
)} </script
> </Head
> <h1>{post.title}</h1
> <p>By {post.author?.name}</p
> </>
)}
Validate schema with Google rich results test