Content Accessibility

Schema.org JSON-LD

Structured semantic markup for web content via JSON-LD, enabling search engines and AI agents to understand it.

What is Schema.org JSON-LD?

Schema.org JSON-LD is machine-readable metadata embedded in a page as a <script type="application/ld+json"> block. Schema.org is a shared vocabulary of data types from Google, Microsoft, Yahoo, and Yandex. JSON-LD is the syntax for expressing that data.

Example JSON-LD on a homepage:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "name": "Agent Ready Scanner",
  "applicationCategory": "DeveloperApplication",
  "url": "https://agentsready.io",
  "description": "Free AI-readiness scanner for websites"
}
</script>

The markup is embedded in <head> or <body> and has no visual effect — it is only visible to search engines and AI agents.

Why does a site need Schema.org JSON-LD?

Schema.org solves a fundamental problem: HTML contains content but doesn’t say what it means. Is a paragraph of text a review? A schedule? An instruction? Without markup, AI has to guess. With markup, it knows exactly.

For GEO and AEO:

AI assistants (ChatGPT, Perplexity, Google AI Overview) use structured data when generating answers. A page with FAQPage is cited as a ready-made answer — this is the primary tool of AEO. A page with Product and aggregateRating gets rich snippets.

For AI agents:

An agent extracts data from markup faster and more accurately than from raw HTML.

Practical effects:

  • FAQPage → “Question and answer” rich snippet, citation in AI answers
  • Recipe/article → rich snippet with image
  • Organization → Knowledge Panel
  • SoftwareApplication → rating in app search results

How to implement Schema.org JSON-LD?

Minimal set for most sites:

<!-- Homepage: WebSite -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "Site Name",
  "url": "https://example.com"
}
</script>

<!-- About page: Organization -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Company",
  "url": "https://example.com",
  "logo": "https://example.com/logo.png",
  "contactPoint": {
    "@type": "ContactPoint",
    "email": "hello@example.com"
  }
}
</script>

FAQ page:

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What is agent-readiness?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Agent-readiness is the degree to which a site..."
      }
    }
  ]
}

Priority types for agent-readiness:

TypeWhen to use
WebSiteHomepage
OrganizationAbout page
SoftwareApplicationHomepage for SaaS / apps
FAQPageFAQ page
Article / TechArticleArticles, documentation
DefinedTermGlossary pages
ServiceServices / pricing page

For Astro (our approach):

---
const schema = {
  '@context': 'https://schema.org',
  '@type': 'SoftwareApplication',
  name: 'Agent Ready Scanner',
  url: 'https://agentsready.io',
};
---
<script type="application/ld+json" set:html={JSON.stringify(schema)}></script>

Validation: before deploying, check at validator.schema.org — there should be 0 errors, ideally 0 warnings.

How do we check Schema.org?

Our scanner performs GET / (the homepage) and verifies:

  1. Presence of JSON-LD blocks — find all <script type="application/ld+json"> in the HTML
  2. Valid JSON — each block parses without errors
  3. @type from the priority listOrganization, Product, SoftwareApplication, Article, FAQPage, BreadcrumbList, WebSite
  4. Required fields per type — for each type, check for required fields (e.g., WebSite requires name and url)

Status pass — at least one block is valid and contains a priority type with the required fields. Status fail — no JSON-LD block found or all blocks are invalid. Status neutral — other markup formats found (Microdata, RDFa) but not JSON-LD.

Sources and specifications