Agent Surface

Discovery & AEO

Structured Data for Agents

JSON-LD schema markup that gives search and agent systems machine-readable facts about your content

Last verified 2026-09-25

Summary

JSON-LD markup embeds structured data so search engines and agents can extract facts without relying only on natural language . Use it to describe FAQs, breadcrumbs, products, articles, , and other page entities in a machine-readable form. The fundamental rule: schema must exactly match visible page content, not supplement it.

  • JSON-LD is the easiest structured-data format for agents to parse directly
  • FAQPage and HowTo schema are still valid Schema.org markup for agents and other parsers, but Google no longer shows either as a Search rich result (HowTo since September 2023, FAQPage since May 2026)
  • BreadcrumbList schema for navigation and hierarchy
  • LocalBusiness, Product, and NewsArticle schemas for specific content types
  • Schema must match visible content exactly; mismatched schema is a trust signal search engines penalize

Search-augmented AI systems retrieve pages from the web before generating answers. Structured data gives those systems machine-readable facts that sit alongside your prose, reducing the inference work required to extract accurate information. Treat it as an extraction aid and search-quality signal, not as a guarantee that a page will appear in generated answers.

Page identity and presentation metadata

Set a descriptive page title, the document language (html lang), and a canonical URL. Use accurate Open Graph type and image metadata when consumers present shared previews. Keep alternate and regional versions tied to their actual source. These signals complement structured data; they do not establish ranking or factual accuracy. Verify the rendered head and the fetched document rather than relying on framework configuration alone.

Why JSON-LD

JSON-LD embeds structured data in a separate `<script>` block rather than wrapping HTML elements in microdata attributes. For , this is the preferable format:

  • No HTML parsing required - the agent reads the JSON directly
  • The data model is explicit and fully typed
  • Google recommends JSON-LD for structured data because it does not require annotating visible HTML
  • Multiple schemas can coexist in the same page without interference

The practical benefit is extraction reliability: agents can read named fields instead of guessing from prose. Validate the effect on your own pages with search appearance data, answer-quality tests, and retrieval logs.

The Fundamental Rule

JSON-LD must exactly match the visible content on the page. If your FAQ schema contains a question-and-answer pair that does not appear in the page body, search engines will penalize the page and agents may distrust all structured data from your domain. The schema is a machine-readable version of the page.

FAQPage

Use FAQPage for any content structured as questions and answers: FAQ sections, definition pages, policy explanations, troubleshooting guides. Google removed FAQ rich results from Search in May 2026, so this schema no longer earns Google's rich-result presentation. Keep it anyway: it is still valid Schema.org markup, and agents and other parsers that read JSON-LD directly still benefit from question-and-answer content marked up explicitly rather than left to prose inference.

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "What is the rate limit for the API?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "The API is rate limited to 1,000 requests per minute per API key. If you exceed this limit, the API returns HTTP 429 with a Retry-After header specifying how many seconds to wait before retrying."
        }
      },
      {
        "@type": "Question",
        "name": "How do I authenticate API requests?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Include your API key in the Authorization header as a Bearer token: Authorization: Bearer YOUR_API_KEY. API keys are scoped to specific permissions and can be rotated without downtime."
        }
      },
      {
        "@type": "Question",
        "name": "What formats does the API return?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "The API returns JSON by default. Set the Accept header to text/markdown to receive Markdown-formatted responses, or application/xml for XML."
        }
      }
    ]
  }
</script>

The name field should be the exact heading text of the question as it appears on the page. The text field in acceptedAnswer should be the full answer, including any code snippets or specific values that agents might extract.

HowTo

Use HowTo for procedural content: setup guides, integration walkthroughs, step-by-step tutorials. Google removed HowTo rich results from Search in September 2023; do not expect a Google rich result from this schema. Keep it for agents and other parsers that read structured step data directly.

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "HowTo",
    "name": "Connect to the API using OAuth 2.0",
    "description": "Authenticate your application with the API using the OAuth 2.0 Client Credentials flow.",
    "totalTime": "PT15M",
    "tool": [
      {
        "@type": "HowToTool",
        "name": "API client (curl, Postman, or your HTTP library)"
      },
      {
        "@type": "HowToTool",
        "name": "Client ID and Client Secret from the developer dashboard"
      }
    ],
    "step": [
      {
        "@type": "HowToStep",
        "position": 1,
        "name": "Obtain credentials",
        "text": "Log in to the developer dashboard at dashboard.example.com. Navigate to API Keys and create a new OAuth application. Copy the Client ID and Client Secret.",
        "url": "https://docs.example.com/oauth#obtain-credentials"
      },
      {
        "@type": "HowToStep",
        "position": 2,
        "name": "Request an access token",
        "text": "POST to https://auth.example.com/oauth/token with grant_type=client_credentials, client_id, and client_secret in the request body. The response includes an access_token and expires_in value.",
        "url": "https://docs.example.com/oauth#request-token"
      },
      {
        "@type": "HowToStep",
        "position": 3,
        "name": "Use the access token",
        "text": "Include the access token in the Authorization header of API requests: Authorization: Bearer {access_token}. Tokens expire after the number of seconds indicated by expires_in. Request a new token before expiry.",
        "url": "https://docs.example.com/oauth#use-token"
      }
    ]
  }
</script>

totalTime uses ISO 8601 duration format: PT15M is 15 minutes, PT1H30M is 90 minutes. The url in each step should anchor to the specific step heading on the page.

TechArticle

Use TechArticle for technical documentation pages: API reference pages, concept explanations, architecture documentation.

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "TechArticle",
    "headline": "Webhook Event Reference",
    "description": "Complete reference for all webhook events emitted by the API, including payload schemas and example payloads.",
    "datePublished": "2024-09-01T00:00:00Z",
    "dateModified": "2025-03-15T00:00:00Z",
    "author": {
      "@type": "Organization",
      "name": "Acme Inc",
      "url": "https://example.com"
    },
    "publisher": {
      "@type": "Organization",
      "name": "Acme Inc",
      "logo": {
        "@type": "ImageObject",
        "url": "https://example.com/logo.png"
      }
    },
    "proficiencyLevel": "Expert",
    "dependencies": "API version 2.0 or later",
    "articleSection": "Reference",
    "keywords": ["webhooks", "events", "API", "payload", "HMAC"],
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://docs.example.com/webhooks/events"
    }
  }
</script>

proficiencyLevel accepts: Beginner, Expert. dateModified is more important than datePublished for agent trust - agents use modification date to assess whether documentation is current.

SoftwareApplication

Use SoftwareApplication for tool and product pages, documentation, and landing pages.

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "SoftwareApplication",
    "name": "Acme CLI",
    "description": "Command-line interface for managing Acme resources, running jobs, and inspecting logs.",
    "applicationCategory": "DeveloperApplication",
    "operatingSystem": "macOS, Linux, Windows",
    "offers": {
      "@type": "Offer",
      "price": "0",
      "priceCurrency": "USD"
    },
    "downloadUrl": "https://example.com/cli/install",
    "softwareVersion": "2.4.1",
    "releaseNotes": "https://github.com/acme/cli/releases/tag/v2.4.1",
    "programmingLanguage": "Go",
    "codeRepository": "https://github.com/acme/cli",
    "license": "https://opensource.org/licenses/MIT"
  }
</script>

WebAPI

Use WebAPI specifically for API reference and documentation pages. This schema type signals to agents that the page describes a callable interface.

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "WebAPI",
    "name": "Acme REST API",
    "description": "REST API for programmatic access to all Acme platform features. Supports JSON and Markdown response formats.",
    "documentation": "https://docs.example.com/api",
    "termsOfService": "https://example.com/terms",
    "version": "2024-11-01",
    "provider": {
      "@type": "Organization",
      "name": "Acme Inc",
      "url": "https://example.com"
    },
    "license": "https://example.com/api/license",
    "endpointUrl": "https://api.example.com/v2",
    "potentialAction": {
      "@type": "ConsumeAction",
      "target": {
        "@type": "EntryPoint",
        "urlTemplate": "https://api.example.com/v2/{path}",
        "httpMethod": "GET",
        "encodingType": "application/json"
      }
    }
  }
</script>

Multiple Schemas on One Page

A single page can carry multiple schema types. A page that is both an API overview (WebAPI) and contains setup steps (HowTo) should include both:

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@graph": [
      {
        "@type": "WebAPI",
        "name": "Acme REST API",
        ...
      },
      {
        "@type": "HowTo",
        "name": "Make your first API call",
        ...
      }
    ]
  }
</script>

Use @graph when combining schemas. Do not use multiple `<script>` tags with competing @context declarations - this is valid JSON-LD but some parsers mishandle it.

Implementing in Next.js

// app/docs/[slug]/page.tsx
import type { WithContext, FAQPage, TechArticle } from 'schema-dts'

export default function DocPage({ page }) {
  const faqSchema: WithContext<FAQPage> = {
    '@context': 'https://schema.org',
    '@type': 'FAQPage',
    mainEntity: page.faqs.map((faq) => ({
      '@type': 'Question',
      name: faq.question,
      acceptedAnswer: {
        '@type': 'Answer',
        text: faq.answer,
      },
    })),
  }

  const articleSchema: WithContext<TechArticle> = {
    '@context': 'https://schema.org',
    '@type': 'TechArticle',
    headline: page.title,
    description: page.description,
    dateModified: page.lastModified,
    author: { '@type': 'Organization', name: 'Acme Inc' },
  }

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(faqSchema) }}
      />
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
      />
      {/* page content */}
    </>
  )
}

The schema-dts package provides TypeScript types for all Schema.org types, catching type errors at build time rather than at validation.

Validation

Test structured data before deploying:

  • Google Rich Results Test - search.google.com/test/rich-results - validates whether Google can process your schema and whether it qualifies for rich results. It no longer covers FAQPage (Google dropped the rich result itself on 7 May 2026, with Rich Results Test support following in June 2026) or HowTo (removed September 2023); use it for the schema types Google still surfaces, and the Schema.org Validator for FAQPage and HowTo.
  • Schema.org Validator - validator.schema.org - validates against the full Schema.org specification, including fields outside Google's subset
  • JSON-LD Playground - json-ld.org/playground - useful for debugging @context and @graph issues

External identity evidence

Use sameAs for verified equivalent identities, not arbitrary mentions. Wikipedia/Wikidata eligibility, official-site linking, and truthful Organization details are covered in Commercial and Entity Discovery.

On this page