Skip to main content

Schema generation with Claude: every page type, working JSON-LD, zero hallucinations

July 22, 2026
7 min read
ai-automationschema-markuptechnical-seojson-ldclaude-code

Schema markup is the SEO equivalent of free money. Pages with proper structured data get richer SERP treatments, better AI Overview coverage, and clearer entity association for AI engines. The reason most sites don't have it: it's tedious to write by hand and validators are unforgiving.

Claude is great at writing JSON-LD. It's also great at hallucinating JSON-LD that validates but is semantically wrong. Here's the cookbook that gets the first benefit while preventing the second.

The anti-hallucination prompt structure

Before the cookbook — the prompt scaffold that prevents Claude from inventing fields:

Generate JSON-LD structured data for the page below.

USE ONLY these Schema.org types: BlogPosting, Person, Organization,
  Product, Service, FAQPage, BreadcrumbList, HowTo, WebPage, WebSite.
  If the page doesn't fit one of these, output {"error": "no suitable type"}.

USE ONLY these fields per type (from the official Schema.org spec — 
  list explicitly so Claude doesn't invent):

BlogPosting:
  @context, @type, headline, description, image, author, publisher,
  datePublished, dateModified, mainEntityOfPage, articleSection, wordCount,
  inLanguage, keywords

Person:
  @context, @type, @id, name, givenName, familyName, jobTitle, url, image,
  sameAs, knowsAbout, alumniOf, worksFor

Organization:
  @context, @type, @id, name, url, logo, sameAs, foundingDate,
  founder, contactPoint, address

...etc

NEVER invent fields that aren't in the lists above.

NEVER include fields where you don't have data — better to omit than to guess.
NEVER use @type values not in the allowed list.

Page content:
{paste the page HTML or a description here}

Output valid JSON only. No prose.

No markdown code fence.

That field-allowlist approach is the difference between schema that validates and schema that helps. Without it, Claude will add fields like readingTime (which isn't a Schema.org property, though it sounds like one) or category on a BlogPosting (also not standard — articleSection is).

The cookbook

What follows: ready-to-copy JSON-LD blocks for the page types Booplex (or any small business or portfolio site) needs. Drop into your page's <head>, replace placeholders, validate with Google's Rich Results Test, ship.

BlogPosting

For a blog post. The single most valuable schema for any content site.

{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "@id": "https://example.com/blog/my-post#post",
  "headline": "Your post title here (max 110 chars)",
  "description": "Meta description — 150-160 chars.",
  "image": {
    "@type": "ImageObject",
    "url": "https://example.com/og/post.png",
    "width": 1200,
    "height": 630
  },
  "author": {
    "@type": "Person",
    "@id": "https://example.com/about#gabi",
    "name": "Gabi Florea",
    "url": "https://example.com/about"
  },
  "publisher": {
    "@type": "Organization",
    "@id": "https://example.com/#org",
    "name": "Booplex",
    "logo": {
      "@type": "ImageObject",
      "url": "https://example.com/logo.png"
    }
  },
  "datePublished": "2026-05-17T08:00:00+02:00",
  "dateModified": "2026-05-17T08:00:00+02:00",
  "mainEntityOfPage": "https://example.com/blog/my-post",
  "articleSection": "AI Automation",
  "wordCount": 2150,
  "inLanguage": "en",
  "keywords": "ai automation, claude code, seo workflow"
}

Notes on the version above:

  • @id on the BlogPosting, the Person, and the Organization. This is how AI engines tell that the same entities appear across multiple pages of your site. Critical for citation.
  • dateModified must update whenever the content changes — not when CSS changes. AI engines weight this heavily for content freshness.
  • wordCount is optional but Google occasionally surfaces it. Cheap field, include it.

Person

For your About page. The entity anchor for everything else.

{
  "@context": "https://schema.org",
  "@type": "Person",
  "@id": "https://example.com/about#gabi",
  "name": "Gabi Florea",
  "givenName": "Gabi",
  "familyName": "Florea",
  "jobTitle": "Independent builder & SEO specialist",
  "url": "https://example.com/about",
  "image": "https://example.com/gabi.jpg",
  "sameAs": [
    "https://linkedin.com/in/gabiflorea",
    "https://github.com/gabiflorea",
    "https://twitter.com/gabiflorea"
  ],
  "knowsAbout": [
    "SEO",
    "AI automation",
    "Next.js",
    "Generative Engine Optimization",
    "Technical SEO"
  ],
  "alumniOf": {
    "@type": "CollegeOrUniversity",
    "name": "University name here"
  },
  "worksFor": {
    "@type": "Organization",
    "@id": "https://example.com/#org",
    "name": "Booplex"
  }
}

The sameAs array is the single most important field for entity disambiguation. Add every profile you maintain. Each one is a vote that you are the person Google/Claude/Perplexity think you are.

Organization

For your homepage. Pair with Person via founder/founderOf.

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://example.com/#org",
  "name": "Booplex",
  "url": "https://example.com/",
  "logo": {
    "@type": "ImageObject",
    "url": "https://example.com/logo.png"
  },
  "description": "Independent SEO + AI workflow studio of one.",
  "foundingDate": "2024-09-01",
  "founder": {
    "@type": "Person",
    "@id": "https://example.com/about#gabi"
  },
  "sameAs": [
    "https://linkedin.com/company/booplex",
    "https://github.com/booplex"
  ],
  "contactPoint": {
    "@type": "ContactPoint",
    "email": "hi@booplex.com",
    "contactType": "customer support",
    "availableLanguage": ["en", "ro", "es"]
  }
}

FAQPage

For posts with FAQ sections. Triggers FAQ rich results (still active in some regions/queries, less so in others — but the AI citation benefit alone justifies it).

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Is Claude good for SEO keyword research?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "For the analysis layer, yes — clustering, intent classification, brief drafting. Claude doesn't know search volumes, so pair it with a data source like DataForSEO."
      }
    },
    {
      "@type": "Question",
      "name": "What does DataForSEO cost per query?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Around €0.0001 per search_volume call and €0.002 per SERP query. A typical 300-keyword expansion costs €0.10-€0.30."
      }
    }
  ]
}

Two rules for FAQPage that AI engines reward:

  1. Answers should be 40–60 words. Long enough to be a real answer, short enough to be a citation.
  2. The questions on the page should be ones a real human would search. Don't invent questions. Lift them from PAA + AI Overview captures.

Product

For a product page (commerce or SaaS).

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Canonical URL Checker",
  "description": "Free tool. Paste a URL, see what canonical it serves.",
  "image": "https://example.com/og/canonical-checker.png",
  "brand": {
    "@type": "Organization",
    "@id": "https://example.com/#org"
  },
  "offers": {
    "@type": "Offer",
    "price": "0",
    "priceCurrency": "EUR",
    "availability": "https://schema.org/InStock",
    "url": "https://example.com/tools/canonical-checker"
  }
}

Even for free tools, Product schema works. The Offer block with price=0 tells Google it's a no-cost product. Don't be tempted to use SoftwareApplication — Product is more universally supported.

Service

For service pages — though I'd argue most personal/solo brands shouldn't have explicit service pages. If you must:

{
  "@context": "https://schema.org",
  "@type": "Service",
  "name": "SEO + AI workflow consulting",
  "description": "Hourly consulting on technical SEO and AI workflow design.",
  "provider": {
    "@type": "Organization",
    "@id": "https://example.com/#org"
  },
  "areaServed": {
    "@type": "AdministrativeArea",
    "name": "Worldwide (remote)"
  }
}

Every page below root should have one. Even if your visible breadcrumb is minimal.

{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "Home",
      "item": "https://example.com/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "Brain Dumps",
      "item": "https://example.com/blog"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "Schema cookbook",
      "item": "https://example.com/blog/schema-cookbook"
    }
  ]
}

Combining multiple schemas on one page

You'll often need both a BlogPosting and an FAQPage on the same post. Don't put them in separate <script> tags — use the @graph approach:

{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "BlogPosting", "@id": "https://example.com/blog/post#post", ... },
    { "@type": "FAQPage", "mainEntity": [...] },
    { "@type": "BreadcrumbList", "itemListElement": [...] }
  ]
}

One script tag, one graph, multiple entities. Cleaner for both validators and crawlers.

Validation workflow

  1. Paste the JSON-LD into Google's Rich Results Test. Should pass without errors.
  2. Run through Schema.org's own validator. Catches more pedantic issues.
  3. If you're using Claude to generate it, also run the output through jq to confirm it's valid JSON.
  4. Deploy. Wait 7–14 days for GSC to pick up the structured data and start reporting on it.

What Claude consistently gets wrong (and how to prevent it)

Three patterns I see repeatedly:

Inventing fields that sound right. Claude will add readingTime, category, tags, views — all of which are wrong. Fix: the field allowlist in the prompt scaffold above.

Mismatching @id values. Claude will assign the same @id to two different entities, breaking the graph. Fix: have the prompt produce @ids from a deterministic pattern (e.g., "the URL + '#post' for BlogPosting, '#org' for Organization").

Using deprecated types. Claude may default to Article when BlogPosting is correct, or WebPage when something more specific applies. Fix: explicit type allowlist + the rule "if the page doesn't fit, output {error}."

Why this matters more in 2026 than it did in 2024

Three things changed:

  1. AI engines parse schema as the structured layer of your entity graph. Without schema, you're invisible to entity-level reasoning.
  2. Google's AI Overviews heavily reward structured pages — clear schema means clearer citation eligibility.
  3. Schema is one of the few SEO levers that's fully under your control. No backlink prospecting, no algorithm waiting, no ranking volatility.

The cost is one prompt and a 20-line block per page type. Run it once per template, ship.

FAQ

Should I use JSON-LD or microdata for schema?

JSON-LD. Google and AI engines prefer it. Microdata still works but is verbose and clutters HTML. JSON-LD goes in a single script tag, separated from your content.

How often should I update my schema?

When the underlying data changes. Update dateModified when you edit a post. Update sameAs when you add a new profile. Don't touch schema you haven't changed — meaningless edits don't help anything.

Will Claude-generated schema validate?

Yes, if you use the field allowlist prompt above. Without that, ~30% of generated schemas have at least one invalid field. With it, the rate drops to under 5%.

Do AI Overviews require schema?

Not strictly required. But pages with proper schema get cited in AI Overviews more often, per multiple studies and my own spot-checks. The schema isn't the ranking factor — it's the eligibility factor.

What's the minimum schema for a blog post?

BlogPosting + Person (author) + Organization (publisher). Add BreadcrumbList if the post is in a category. Add FAQPage if there are FAQ sections. That's the practical floor for an AI-cite-able blog post.

Can I have too much schema on a page?

Yes. Don't add schema for entities that aren't actually on the page. If you don't have a real FAQ, don't include FAQPage. Schema you can't substantiate hurts more than it helps.

Topics:ai-automationschema-markuptechnical-seojson-ldclaude-code

Found This Useful?

Share it with someone who might learn from my mistakes!