Skip to main content
AC
SEO & AEO4.7 KBMIT licensed

schema

Rewritten from patterns in an open SaaS marketing skills pack (MIT)

Implement and validate schema.org structured data as JSON-LD for rich results. Use when the user says "schema markup", "structured data", "JSON-LD", "rich snippets", "FAQ schema", "product schema", or wants star ratings or enhanced listings in Google. Not for full SEO diagnostics: use seo-audit. Not for AI answer engine optimization: use ai-seo. Not for planning page hierarchy or breadcrumb structure: use site-architecture.

  • schema

SKILL.md

Schema Markup

Schema earns rich results only when it is valid JSON-LD, matches what a human sees on the page, and uses a type Google still rewards. Markup that overstates the page is not optimization, it is a penalty risk.

Before You Write Markup

If a product marketing context file exists (.agents/product-marketing.md or .claude/product-marketing.md), read it first. Then confirm three things:

  1. Page type and primary content. That decides which types are even eligible.
  2. Existing markup. Never stack a second block of the same type on top of a broken one.
  3. Target rich result and its business value. No target, no markup.

Workflow

  1. Pick the type from the page, not the wishlist. Homepage: Organization plus WebSite. Blog post: Article. Product page: Product with offers. FAQ content: FAQPage. Tutorial: HowTo. Local page: LocalBusiness. Read references/schema-types.md for required and recommended properties per type plus full JSON-LD examples.
  2. Write JSON-LD only. Google's stated preference, easiest to maintain. Place in <head> or end of <body>, in server-rendered HTML. Client-injected markup can be processed late or missed.
  3. Combine types with `@graph` when one page needs Organization, WebSite, and BreadcrumbList together. One script block, one graph.
  4. Fill only facts the page displays. No fabricated ratings, no invented dates. Unknown values become <FILL_ME> for the user, never guesses.
  5. Validate before shipping. Rich Results Test for eligibility, validator.schema.org for syntax, Search Console Enhancements reports for ongoing monitoring.

Format Rules

  • Dates in ISO 8601, URLs absolute and fully qualified.
  • Enumerations exact: https://schema.org/InStock, not "in stock".
  • One canonical block per type per page.
  • Keep markup in sync with content. Stale schema after a redesign is a common silent failure.

Implementation by Stack

StackApproach
Static HTMLJSON-LD in the template, partials for reusable blocks
React / Next.jsSchema component, server-side rendered, data serialized to JSON-LD
WordPress / CMSPlugin (Yoast, Rank Math) or theme-level template edit

Verification

Run the generated block through a JSON parser: python3 -c "import json,sys; json.load(sys.stdin)" < schema.json. Expect silent success. If it errors, fix the reported syntax issue (trailing comma, unquoted key) and re-run.

Then paste the page URL or code into the Rich Results Test (search.google.com/test/rich-results). Expect zero errors and the target rich result listed as detected. If errors appear, fix required properties first, warnings second, and retest before delivering.

Good vs Bad

Bad: Product page has no reviews yet. You add aggregateRating with a placeholder 4.8 so the stars show up. That is fabricated markup, a manual-action risk, and it will be your client's problem in six months.

Good: You skip rating markup, ship Product with real name, image, and offers, and note: "Add aggregateRating only after real reviews render on the page."

Footguns

  • Markup for content that is not on the page. Google's top reason for structured data manual actions. Fix: every property value must be visible on the rendered page.
  • Relative URLs. "url": "/pricing" fails silently in some validators. Fix: absolute URLs everywhere.
  • JS-injected JSON-LD. SEO plugins and tag managers often inject schema client-side, so curl-based checks miss it and Google may process it late. Fix: move blocks into server-rendered HTML, especially Product and Offer.
  • Duplicate conflicting blocks. A plugin block plus a hand-added block of the same type with different values. Fix: audit existing markup first, keep one source of truth.

Completion Checklist

  • [ ] Type matches page content and current Google eligibility
  • [ ] JSON parses clean, all URLs absolute, dates ISO 8601
  • [ ] No fabricated values, unknowns marked <FILL_ME>
  • [ ] Rich Results Test passes with zero errors
  • [ ] Placement is server-rendered, one block per type

Any box unchecked: not done. Fix or say so.

Reference files

More in SEO & AEO

All skills