ai

Content type schema

MetricSpot checks for a JSON-LD `@type` that matches what the page actually is — Article, Product, HowTo, FAQPage, etc. Without it, AI agents have to guess.

What this check does

Parses every <script type="application/ld+json"> block on the page and verifies that at least one declares an @type matching the page’s actual purpose. A blog post should declare Article (or BlogPosting / NewsArticle); a product page Product; a step-by-step guide HowTo; an FAQ page FAQPage. A page that only emits WebPage or WebSite schema fails — those types are too generic to tell agents anything useful.

Why it matters

JSON-LD is the scaffolding AI agents and search engines use to understand a page without parsing prose. When @type is specific, ChatGPT, Perplexity, and Google AI Overviews know which fields to extract (headline, author, datePublished for an Article; price, availability, aggregateRating for a Product) and how to cite the page in answers.

When @type is missing or generic, the agent falls back to body-text heuristics — slower, less accurate, and far more likely to skip your page in favor of a competitor’s better-marked one. The same logic applies to Google rich results: only specific types unlock the SERP features (review stars, recipe cards, FAQ accordions) that lift click-through rate.

How to fix it

Pick the @type that best matches the page and emit a complete JSON-LD block in the <head>.

Article / BlogPosting / NewsArticle — for editorial content. Use NewsArticle for time-stamped news; BlogPosting for blog posts; plain Article is the safe default.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "How to enable HSTS on nginx",
  "datePublished": "2026-05-11",
  "dateModified": "2026-05-11",
  "author": {
    "@type": "Person",
    "name": "Jane Doe",
    "url": "https://example.com/authors/jane-doe"
  },
  "image": "https://example.com/og/hsts.png",
  "mainEntityOfPage": "https://example.com/blog/hsts"
}
</script>

HowTo — for step-by-step guides (recipes, repair instructions, setup tutorials). Required fields: name, step.

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "Enable HSTS on nginx",
  "step": [
    { "@type": "HowToStep", "name": "Add the header", "text": "Add `add_header Strict-Transport-Security ...` to your server block." },
    { "@type": "HowToStep", "name": "Reload nginx", "text": "Run `nginx -t && systemctl reload nginx`." }
  ]
}

FAQPage — only when the page is genuinely a Q&A. See FAQ schema for the full pattern.

Product — for individual product pages. Include offers, aggregateRating, review when you have them.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "MetricSpot Premium",
  "description": "Unlimited audits, scheduled monitoring, PDF reports.",
  "brand": { "@type": "Brand", "name": "MetricSpot" },
  "offers": {
    "@type": "Offer",
    "price": "29.00",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Next.js — inject via the App Router’s <Script> or a metadata helper:

import Script from "next/script";

export default function Post() {
  const schema = {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    headline: "How to enable HSTS on nginx",
    datePublished: "2026-05-11",
    author: { "@type": "Person", name: "Jane Doe" }
  };
  return (
    <Script id="ld" type="application/ld+json">
      {JSON.stringify(schema)}
    </Script>
  );
}

Astro — set the JSON-LD in your layout <head>:

---
const schema = { "@context": "https://schema.org", "@type": "BlogPosting", /* … */ };
---
<script type="application/ld+json" set:html={JSON.stringify(schema)} />

WordPress — Yoast SEO, Rank Math, and SEOPress all auto-emit Article schema for posts. Check the rendered source to confirm the @type is Article / BlogPosting, not just WebPage. For Product pages, WooCommerce emits Product schema by default.

After shipping, validate with Google’s Rich Results Test and the Schema Markup Validator. See also: JSON-LD structured data, organization schema.

Frequently asked questions

Can a page have multiple @type blocks?

Yes — common and recommended. A blog post typically ships Article + BreadcrumbList + Organization. Each goes in its own <script type="application/ld+json"> block, or combine them in a single @graph array. Don’t conflict (don’t declare the page as both Article and Product).

Should I use Article or BlogPosting?

BlogPosting is a subclass of Article — slightly more specific, no downsides. Use BlogPosting for blog content, NewsArticle for dated news, Article for evergreen editorial or technical guides. Google treats them equivalently for rich results.

What if my page doesn’t fit any schema type?

Generic landing pages can stay on WebPage — this check will flag it as a soft warning rather than a hard fail. But most “doesn’t fit” cases actually do fit something: a pricing page is a Product or Service, an about page is AboutPage, a contact page is ContactPage. Browse schema.org’s full type list before defaulting to WebPage.

Sources

Last updated 2026-05-11