agentspeed.
← all fixes
Issue remediation

Missing structured data (JSON-LD)

Your pages have no JSON-LD, so agents must guess what each page is about.

failed checkstructured_data.jsonld_present
What this means

JSON-LD is a small block of structured metadata embedded in a <script type="application/ld+json"> tag inside <head>. It tells agents (and search engines) exactly what a page is: a Product, an Article, an Organization, a FAQPage. Without it, the agent has to infer the page type from prose, which is error-prone.

Why it matters for AI agents

Agents prefer structured signals over prose because they're cheaper to parse and harder to misread. With JSON-LD, an agent can answer 'how much does this cost' or 'who wrote this article' from a single field instead of reading the whole page. Without it, the agent either guesses or gives up. JSON-LD is also one of the highest-signal inputs to Google's AI Overviews and ChatGPT shopping.

Business impact

Pages with JSON-LD get cited at meaningfully higher rates by AI shopping agents and answer engines. For e-commerce, missing Product schema means your prices and availability are not eligible for agent-driven shopping. For publishers, missing Article schema means your byline and publish date may not appear in citations. Adding the right schema is a one-time effort that pays out forever.

How to check manually

View source on a page (Ctrl-U) and search for 'application/ld+json'. If you find no matches, you have no structured data. If you find one, paste its contents into Google's Rich Results Test (search.google.com/test/rich-results); it will surface validation errors and tell you which schema types it recognised.

The exact fix

Add a <script type="application/ld+json"> to every page with the correct schema.org type. Use Product for product pages, Article for blog posts, Organization for the homepage and about page, FAQPage for FAQs, BreadcrumbList for category pages. Keep the JSON minimal but accurate; every field you include must match what is on the page.

Copy-paste snippet
Reference snippethtmlproduct-page.html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Cast-Iron Skillet, 10\"",
  "image": "https://acme.com/img/skillet-10.jpg",
  "description": "Pre-seasoned cast-iron skillet, made in Ohio.",
  "brand": { "@type": "Brand", "name": "Acme" },
  "sku": "ACME-CIS-10",
  "offers": {
    "@type": "Offer",
    "url": "https://acme.com/products/skillet-10",
    "priceCurrency": "USD",
    "price": "79.00",
    "availability": "https://schema.org/InStock"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "reviewCount": "412"
  }
}
</script>
Platform-specific implementations

The reference snippet above is platform-agnostic. Below are the concrete steps for the four most common stacks plus a generic fallback for any other host.

Next.js

Add a server component that emits the <script> tag using dangerouslySetInnerHTML with JSON.stringify. Place it inside the page's <head> via the App Router layout, or directly at the top of the page component. Generate the JSON from your page data so it stays in sync with the rendered content.

Next.jstsxapp/products/[slug]/page.tsx
import { getProduct } from '@/lib/products';

export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const product = await getProduct(slug);
  const ld = {
    '@context': 'https://schema.org',
    '@type': 'Product',
    name: product.name,
    image: product.imageUrl,
    description: product.description,
    sku: product.sku,
    offers: {
      '@type': 'Offer',
      url: `https://acme.com/products/${slug}`,
      priceCurrency: product.currency,
      price: product.price.toFixed(2),
      availability: product.inStock
        ? 'https://schema.org/InStock'
        : 'https://schema.org/OutOfStock',
    },
  };
  return (
    <>
      <script type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(ld) }} />
      <h1>{product.name}</h1>
      {/* …rest of the page */}
    </>
  );
}

WordPress

The cleanest path is the Yoast SEO or Rank Math plugin; both emit JSON-LD automatically for posts, pages, products, and FAQs once configured. If you cannot use a plugin, hook into wp_head from your theme and echo the script tag with data pulled from get_post() and post meta.

WordPressphpfunctions.php
add_action( 'wp_head', function () {
  if ( ! is_singular( 'post' ) ) return;
  $post = get_post();
  $ld = [
    '@context' => 'https://schema.org',
    '@type' => 'Article',
    'headline' => get_the_title( $post ),
    'datePublished' => get_the_date( 'c', $post ),
    'dateModified' => get_the_modified_date( 'c', $post ),
    'author' => [
      '@type' => 'Person',
      'name' => get_the_author_meta( 'display_name', $post->post_author ),
    ],
    'mainEntityOfPage' => get_permalink( $post ),
  ];
  echo '<script type="application/ld+json">' . wp_json_encode( $ld ) . '</script>';
} );

Shopify

Shopify's Dawn theme already includes Product JSON-LD by default. Open templates/product.json or sections/main-product.liquid and look for the {%- render 'product-schema' -%} include. If you removed it or you're on a custom theme, add the snippet back. For non-product pages (Articles, FAQs), add a Liquid snippet that emits JSON-LD and include it from the relevant template.

Shopifyliquidsnippets/product-schema.liquid
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": {{ product.title | json }},
  "image": {{ product.featured_image | image_url: width: 1200 | prepend: 'https:' | json }},
  "description": {{ product.description | strip_html | json }},
  "sku": {{ product.selected_or_first_available_variant.sku | json }},
  "brand": { "@type": "Brand", "name": {{ shop.name | json }} },
  "offers": {
    "@type": "Offer",
    "url": {{ request.origin | append: product.url | json }},
    "priceCurrency": {{ cart.currency.iso_code | json }},
    "price": {{ product.selected_or_first_available_variant.price | money_without_currency | json }},
    "availability": "https://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}"
  }
}
</script>

Webflow

Webflow does not render dynamic JSON-LD from CMS fields out of the box, but it does let you embed custom code in the <head> per-page. For a static site go to Page settings → Custom code → Inside <head> tag and paste the JSON-LD. For CMS pages, use the "Embed" component in your CMS template and reference fields via {{wf {fieldId, type: "PlainText"} }} placeholders.

WebflowhtmlCMS template Embed block
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "{{wf {fieldId: 'name', type: 'PlainText'} }}",
  "datePublished": "{{wf {fieldId: 'published-on', type: 'Date'} }}",
  "author": {
    "@type": "Person",
    "name": "{{wf {fieldId: 'author-name', type: 'PlainText'} }}"
  },
  "image": "{{wf {fieldId: 'cover-image', type: 'Image'} }}"
}
</script>

Static HTML / any stack

Hand-author a JSON-LD block per page and paste it into <head>. For more than a handful of pages, generate the JSON at build time from a data file. Most static-site generators (Astro, Eleventy, Hugo, Jekyll) have first-class support for emitting <script> tags from front-matter.

Static HTML / any stackhtmlindex.html
<head>
  <title>Acme — Cookware made in Ohio</title>
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "name": "Acme",
    "url": "https://acme.com",
    "logo": "https://acme.com/img/logo.png",
    "sameAs": [
      "https://twitter.com/acme",
      "https://www.linkedin.com/company/acme"
    ]
  }
  </script>
</head>
Common mistakes
How to re-test

Validate every JSON-LD block at search.google.com/test/rich-results by pasting the URL or the snippet. Then run a fresh AgentSpeed scan; the 'structured-data jsonld present' check flips to pass once a valid block is detected on the homepage. For broader coverage, scan a representative product/article URL too.

FAQ
Do I need JSON-LD on every page?

You need it on every page that maps to a recognised schema.org type: Product pages, Article pages, FAQ pages, the homepage (Organization). Pure marketing pages without a clear type can skip it.

JSON-LD vs Microdata vs RDFa?

JSON-LD is the format Google, OpenAI, Anthropic, and Perplexity all explicitly recommend. Microdata and RDFa still work, but they're inline with the HTML and harder to maintain. New code should be JSON-LD.

Will adding JSON-LD slow my page down?

No. A typical JSON-LD block is 1–3 KB and ships in <head>; it's parsed by agents but ignored by browsers' render path.

Verify on your site
Run a scan

Free scan, no signup. The score page is permanent and citable, so you can link it from your team's remediation ticket alongside this guide for “Missing structured data (JSON-LD)”.

Run a free scan →See all fixes →