Rotten Tomatoes added structured data to 100,000 pages and measured a 25% higher click-through rate on those pages compared to pages without it ([Google Search Central](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data#why)). That lift came from richer, more informative search listings that earned more clicks. Structured data is the annotation layer that makes this possible. It’s a machine-readable description of what a page contains, written in a shared vocabulary ([Schema.org](http://Schema.org)) that search engines and some AI systems already understand.

A reliable structured data implementation depends on three things: crawlers need to be able to see the markup, the schema needs to stay in sync with page content, and the markup needs validation before it ships. The [Next.js App Router](https://nextjs.org/docs/app) helps here for three reasons. First, Server Components render JSON-LD (JavaScript Object Notation for Linked Data) into the initial HTML so crawlers can see it. Second, co-located data fetching keeps your schema aligned with the content on the page, including the named entities it describes. Third, preview URLs let you validate the markup with the Rich Results Test before you merge.

## [Copy link to heading](#structured-data-gives-machines-explicit-page-context)Structured data gives machines explicit page context

Every web page has two audiences. Humans read the visible content, like headings, paragraphs, and images. Machines read the structured data, a separate annotation layer embedded in the page's HTML that describes what the content represents in terms a search engine or AI system can parse without guessing.

Structured data uses the [Schema.org](http://Schema.org) vocabulary, a shared standard founded by Google, Microsoft, Yahoo, and Yandex. It defines types (like Article, Product, or BreadcrumbList) and properties (like headline, price, or datePublished) that map the meaning of a page into a format machines can consume directly. The HTTP Archive's Web Almanac analyzed structured data across 16.9 million websites for its 2024 edition, and found JSON-LD on 41% of pages. It concluded that the technology's true impact lies in how it is transforming AI discovery and machine understanding, not only in traditional rich results ([Web Almanac 2024](https://almanac.httparchive.org/en/2024/structured-data)).

Search engines are not the only machines reading your pages. Some AI assistants and search tools parse the same annotation layer, and they increasingly sit between your content and your audience.

## [Copy link to heading](#how-search-engines-use-structured-data)How search engines use structured data

When Google crawls a page with valid structured data, it uses that markup to understand the content of the page and to gather information about the web and the world, such as the people, books, or companies described in the markup. If the schema type matches one of Google's supported rich result formats, the page becomes eligible for enhanced search listings. A product page may show pricing and ratings beneath its link, an article may appear with an enhanced title and image, and an event listing may show its date, location, and ticket information.

These enhanced listings are called rich results (sometimes referred to as "rich snippets," an older term). They don't change where a page ranks. Google's [John Mueller](https://bsky.app/profile/johnmu.com/post/3lmoenzsfwc2c) has stated that "Structured data won't make your site rank better." What markup changes is how the listing looks and, in turn, how often people click it. Structured data qualifies your page for richer presentation, and richer presentation can earn more clicks.

Google maintains a [Search Gallery](https://developers.google.com/search/docs/appearance/structured-data/search-gallery) listing 25 supported rich result types. Not every schema type produces a visible SERP enhancement, and even valid markup displays at Google's discretion, but a page with no structured data is never eligible in the first place.

## [Copy link to heading](#why-json-ld-is-the-standard-format)Why JSON-LD is the standard format

While [Schema.org](http://Schema.org) vocabulary supports JSON-LD, Microdata, and RDFa, JSON-LD has emerged as the industry standard. Google treats all three formats as equally valid when the markup is correct, and recommends whichever is easiest to implement and maintain, which in most cases is JSON-LD.

The core issue with Microdata and RDFa is that they weave structured data directly into your HTML elements. This tangles your data with your markup, making maintenance increasingly difficult as web pages grow more complex. JSON-LD solves this by isolating your structured data inside a standalone `<script>` tag, completely separate from the visible HTML.

In modern, component-driven architectures like React and Next.js, where component trees can include hundreds of nested elements, this separation of concerns is critical. It prevents schema attributes from polluting component props and allows developers to update structured data without touching the render tree.

The following JSON-LD block shows the `@context` and `@type` fields that every schema needs.

```
<script type="application/ld+json">
  {
    "@context": "<https://schema.org>",
    "@type": "Article",
    "headline": "Structured data for SEO: how to implement JSON-LD in Next.js"
  }
</script>
```

The `@context` field tells parsers to use the [Schema.org](http://Schema.org) vocabulary. The `@type` field identifies what entity the page represents. Every property after that describes the entity in machine-readable terms.

## [Copy link to heading](#which-schema-types-to-implement)Which schema types to implement

Google's supported rich result types change over time. In 2023, Google limited FAQ rich results to authoritative government and health sites and deprecated HowTo rich results. As of May 7, 2026, Google deprecated FAQ rich results entirely. They no longer appear in Search for any site ([Google Search Central](https://developers.google.com/search/updates#faq-deprecation)). Google also introduced new types around this time, including vacation rentals, profile pages, and 3D product models.

The following table maps high-value schema types to common Next.js page patterns.

| Schema type | Page type | Rich result format | Status |
| --- | --- | --- | --- |
| Article / BlogPosting | Blog posts, editorial content | Enhanced article titles and images | Active |
| Product | E-commerce product pages | Price, availability, reviews, ratings | Active |
| BreadcrumbList | Any page with nested navigation | Breadcrumb trail in the visible URL (desktop only) | Active |
| Organization | Homepage, about page | Knowledge panel, logo | Active |
| Event | Event listings | Date, location, ticket information | Active |
| LocalBusiness | Location pages | Knowledge panel with opening hours, ratings, and directions | Active |
| FAQPage | FAQ pages | Expandable Q&A | Deprecated |
| HowTo | Tutorial pages | Step-by-step in SERP | Deprecated |

The highest-return cases for most Next.js applications are Article or BlogPosting for content pages, Product for e-commerce, and Organization for the homepage. BreadcrumbList deserves its own mention. It appears on 5.66% of pages crawled ([HTTP Archive Web Almanac 2024](https://almanac.httparchive.org/en/2024/structured-data#json-ld)), making it one of the most widely deployed navigation schema types. On desktop search results, it renders the visible URL as your domain plus a readable path hierarchy, giving users context about where the page sits within your site architecture before they click.

## [Copy link to heading](#implementing-json-ld-in-the-next.js-app-router)Implementing JSON-LD in the Next.js App Router

Render structured data with a plain `<script type="application/ld+json">` tag in `page.tsx`. JSON-LD does not benefit from `next/script` loading optimizations, so a standard `<script>` element is the simplest and most reliable choice.

### [Copy link to heading](#page-level-schema-in-page.tsx)Page-level schema in `page.tsx`

Each page defines the entity it represents. Here's a BlogPosting example for an article page.

```
// app/blog/[slug]/page.tsx
export default async function BlogPost({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const { slug } = await params
  const post = await getPost(slug)

  const jsonLd = {
    '@context': '<https://schema.org>',
    '@type': 'BlogPosting',
    headline: post.title,
    description: post.excerpt,
    image: post.coverImage,
    datePublished: post.publishedAt,
    dateModified: post.updatedAt,
    author: {
      '@type': 'Person',
      name: post.author.name,
      url: post.author.url,
    },
  }

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(jsonLd).replace(/</g, '\\u003c'),
        }}
      />
      <article>
        <h1>{post.title}</h1>
        {/* page content */}
      </article>
    </>
  )
}
```

The `.replace(/</g, '\\u003c')` call is a security measure. Without it, a malicious string in your data (for example, a title containing `</script>`) could break out of the JSON-LD block and inject arbitrary HTML.

### [Copy link to heading](#homepage-schema-in-page.tsx)Homepage schema in `page.tsx`

Google recommends adding Organization structured data to your homepage, or to a single page that describes your organization, such as an about page. This gives Google administrative details about your organization without repeating the same block across every page.

app/page.tsx

```
export default function HomePage() {
  const jsonLd = {
    '@context': '<https://schema.org>',
    '@type': 'Organization',
    name: 'Your Company',
    url: '<https://yoursite.com>',
    logo: '<https://yoursite.com/logo.png>',
    sameAs: [
      '<https://twitter.com/yourcompany>',
      '<https://github.com/yourcompany>',
    ],
  }

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(jsonLd).replace(/</g, '\\u003c'),
        }}
      />
      <main>{/* homepage content */}</main>
    </>
  )
}
```

### [Copy link to heading](#placement-rules)Placement rules

- Page-specific schema in `page.tsx`. Article, Product, Event, and similar entity types belong where the data lives. Co-location keeps the schema in sync with the content it describes.

- Homepage schema in `page.tsx`. Add Organization structured data to the homepage, or to a single page describing your organization, rather than repeating the same block across the site.

- Route-specific BreadcrumbList schema in `page.tsx`. Generate breadcrumb markup from the current page's route. Layouts don't re-render on navigation and can't read the current pathname on the server, so a shared layout can't derive per-route breadcrumb values. Keep BreadcrumbList in the page that owns the route.

- Render JSON-LD from Server Components by default. Structured data is most reliable when it appears in the initial HTML payload. In the Next.js App Router, place JSON-LD `<script type="application/ld+json">` tags in Server Components so crawlers can parse them without waiting for client-side JavaScript.

- Always sanitize. Use `dangerouslySetInnerHTML` with the XSS escape pattern shown above. You can add compile-time validation by typing your JSON-LD objects with TypeScript, using a community package like `schema-dts`.

- Multiple blocks per page are fine. An article page might carry both a BlogPosting block and a BreadcrumbList block.

## [Copy link to heading](#server-rendering-keeps-json-ld-crawler-visible)Server rendering keeps JSON-LD crawler-visible

Crawler support for client-side JavaScript varies. Googlebot can render JavaScript, but rendering happens after the initial crawl and can delay when Google processes client-rendered structured data. The official documentation for crawlers such as OAI-SearchBot and PerplexityBot does not guarantee JavaScript rendering. Including JSON-LD in server-rendered HTML avoids depending on each crawler's rendering capabilities.

If your JSON-LD is injected client-side, crawlers that do not render JavaScript may never see it. The structured data exists in the browser but not in the HTML returned by the server. The diagnostic is straightforward: view your page source (not the DevTools Elements panel, which shows the post-hydration DOM) and search for `application/ld+json`. If the `<script>` tag is missing from the raw HTML, some crawlers may miss your structured data. Common causes include injecting JSON-LD in a `useEffect` hook, rendering it only after a browser-side condition is met, using a component with server rendering disabled, or relying on a third-party library that inserts the markup after hydration. A component being marked `'use client'` does not by itself mean its initial output is missing from the server-rendered HTML.

Next.js App Router components are Server Components by default. When implemented as shown above, the JSON-LD `<script>` tag renders on the server and ships in the HTML response without requiring client-side JavaScript. Static Site Generation (SSG) can include the JSON-LD in HTML generated at build time, while Incremental Static Regeneration (ISR) can update it when the page regenerates.

## [Copy link to heading](#structured-data-and-ai-search-visibility)Structured data and AI search visibility

Structured data was designed for search engines, but AI systems are becoming a second, increasingly important consumer. Google is explicit that structured data is not required for its generative AI features and that no special markup exists for them, though the markup still governs rich result eligibility. Microsoft is more encouraging but still hedged: its Bing webmaster guidelines say structured data may support clearer grounding across Bing and Copilot, though they note it does not guarantee visibility or grounding traffic. We built our own [agent readability specification](https://vercel.com/kb/guide/agent-readability-spec) around this principle. JSON-LD is a scored requirement alongside llms.txt and sitemaps, because AI agents use explicit entity definitions to understand page context without inferring meaning from raw HTML.

That specification reflects how we see structured data fitting into the broader shift toward AI-driven discovery. Schema markup alone doesn't guarantee AI citation, and content quality still determines whether a page gets surfaced. But structured data provides the machine-readable layer that makes your content interpretable at scale, for both retrieval-augmented generation systems and knowledge graph pipelines.

Several AI-adjacent systems already consume structured data.

- Bing and Copilot may surface pages more clearly when structured data accurately reflects visible content, though Microsoft notes it does not guarantee visibility or grounding traffic.

- NLWeb (Natural Language Web) is an open protocol from Microsoft for building conversational interfaces to websites. It builds on the schema markup sites already publish, and lets both users and AI agents query a site's content in natural language.

- Apple's Siri and Spotlight are powered by content crawled by Applebot, which may render pages in a browser. Apple documents limited schema support, such as the `isAccessibleForFree` property for labeling paywalled content.

## [Copy link to heading](#validating-structured-data-before-you-ship)Validating structured data before you ship

Implementing structured data without validating it is a common reason developers see no rich results. Google's tools surface errors, warnings, and eligibility status before your markup ever reaches production.

1.  Implement the JSON-LD in your `page.tsx` following the patterns above.

2.  Push your branch. We generate a unique [preview URL](https://vercel.com/docs/deployments/environments) for every pull request, giving you a live page to test against. Preview URLs send an `X-Robots-Tag: noindex` header by default, so search engines will not index them, but validation tools can still fetch the URL directly.

3.  Validate the markup. Run the [Rich Results Test](https://search.google.com/test/rich-results) against your preview URL. It parses the page's structured data, flags errors and warnings, and shows which rich result types the page is eligible for.

4.  Check general compliance. The [Schema Markup Validator](https://validator.schema.org) covers vocabulary compliance beyond Google-specific rich results.

5.  Merge once validated. Only merge after the preview deployment confirms the structured data is valid.

6.  Monitor in Google Search Console. After deployment, relevant rich-result status reports, when available, show valid and invalid structured-data items Google has detected across your site, along with any validation errors. Track impressions, clicks, and CTR for pages with structured data compared to pages without.

Because every PR gets its own preview URL, you can validate schema changes in isolation without deploying to production. Note that if Deployment Protection is enabled, preview URLs are not publicly reachable, so external tools cannot fetch them for validation.

## [Copy link to heading](#common-structured-data-mistakes)Common structured data mistakes

When structured data is invalid or misconfigured, Google ignores it. These are the most frequent failure modes.

- Schema doesn't match visible content. Google requires that structured data reflect what is actually visible on the page. Keep your JSON-LD values sourced from the same data your components render.

- Client-side-only injection\*\*.\*\* JSON-LD rendered exclusively in client components or `useEffect` hooks may never reach crawlers. Render it server-side instead, as covered above.

- Implementing deprecated types. HowTo rich results were deprecated in 2023, and FAQ rich results were fully deprecated on May 7, 2026. Valid markup for these types won't produce errors, but it won't produce rich results either. Check the Google Search Gallery for current eligibility.

- Missing recommended properties. Google lists no required properties for Article, but omitting recommended ones like `headline`, `datePublished`, `image`, and `author` gives Google less to work with and reduces the chance of an enhanced listing. Google's Rich Results Test surfaces these gaps explicitly.

- Skipping XSS sanitization. Using `dangerouslySetInnerHTML` with `JSON.stringify` without escaping the `<` character opens a cross-site scripting vector. Always apply `.replace(/</g, '\\u003c')` or an equivalent sanitization step.

## [Copy link to heading](#measuring-structured-data-impact)Measuring structured data impact

Rich results produce measurable outcomes, but the measurement requires patience. Google may take days or weeks to process new structured data, and rich results appear at Google's discretion even when markup is valid.

Google Search Console is the primary measurement tool. In the Performance report, filter by search appearance type, such as review snippets or videos, then compare CTR, impressions, and clicks for pages with structured data against those without. Google's own documentation recommends comparing pages with several months of baseline data to isolate the effect of adding schema markup.

## [Copy link to heading](#structured-data-on-vercel)Structured data on Vercel

Next.js Server Components can render JSON-LD and the page content it describes in the same HTML response when implemented as shown above. On Vercel, [Fluid compute](https://vercel.com/docs/fluid-compute) provides the execution model for dynamic workloads, while Next.js controls how components render. Preview deployments give every pull request a unique URL for Rich Results Test validation before merge. [v0](https://v0.app) includes built-in support for metadata and structured data using Next.js conventions, and [every v0 deployment ships with JSON-LD support](/blog/how-v0-is-building-seo-optimized-sites-by-default) for rich snippets in search. Our own starter templates (like the [Portfolio Blog Starter](https://vercel.com/templates/next.js/portfolio-starter-kit)) ship with JSON-LD schema as a built-in feature.

Many structured data implementations fail for one reason: the markup exists in the codebase but never reaches the systems it was written for. To get started, [deploy your Next.js project on Vercel](https://vercel.com/docs/frameworks/full-stack/nextjs) and run the Rich Results Test against a preview URL.

## [Copy link to heading](#frequently-asked-questions)Frequently asked questions

### [Copy link to heading](#does-structured-data-improve-google-rankings)Does structured data improve Google rankings?

No. Google's John Mueller has said directly that structured data won't make your site rank higher. It qualifies your pages for rich results, and rich results can earn higher CTR than plain text listings.

### [Copy link to heading](#should-i-use-microdata,-rdfa,-or-json-ld)Should I use Microdata, RDFa, or JSON-LD?

Use JSON-LD. Google treats all three formats as equally valid and recommends whichever is easiest for you to implement and maintain, which in most cases is JSON-LD. JSON-LD lives in a standalone `<script>` tag, separate from your HTML, so it doesn't tangle with your component tree the way Microdata and RDFa attributes do.

### [Copy link to heading](#does-client-rendered-json-ld-work-for-seo)Does client-rendered JSON-LD work for SEO?

It can work for Google, but it introduces a rendering dependency and may delay when Google processes the markup. Other crawlers do not consistently document or support JavaScript rendering, so client-only JSON-LD may be missed. Rendering JSON-LD through a Server Component puts it in the server-rendered HTML and avoids that dependency.

### [Copy link to heading](#can-a-single-page-have-multiple-json-ld-blocks)Can a single page have multiple JSON-LD blocks?

Yes. An article page might carry both a BlogPosting block and a BreadcrumbList block, each in its own `<script type="application/ld+json">` tag. Google supports multiple structured data items on a page.

### [Copy link to heading](#is-faqpage-schema-still-worth-implementing)Is FAQPage schema still worth implementing?

Not for earning a Google rich result. As of May 7, 2026, Google no longer shows FAQ rich results, although `FAQPage` remains a valid [Schema.org](http://Schema.org) type and may be consumed by other systems. Existing valid markup does not need to be removed solely because Google deprecated the rich result.

### [Copy link to heading](#how-long-does-it-take-to-see-rich-results-after-adding-structured-data)How long does it take to see rich results after adding structured data?

Allow at least several days, and sometimes longer. Google needs to recrawl and reindex the page before it can show a rich result, and valid markup only makes the page eligible. In Search Console, use the relevant rich result report to confirm that Google has detected the markup and to review any errors.