Unhead Schema.org · Unhead

[Unhead Home](https://unhead.unjs.io/ "Home")

- [Docs](https://unhead.unjs.io/docs/nuxt/head/guides/get-started/overview)
- [Tools](https://unhead.unjs.io/tools)
- [Learn](https://unhead.unjs.io/learn/guides/what-is-capo)

[Releases](https://unhead.unjs.io/releases)

Search…```k`` /`

[Unhead on GitHub](https://github.com/unjs/unhead)

[User Guides](https://unhead.unjs.io/docs/nuxt/head/guides/get-started/overview)

[API](https://unhead.unjs.io/docs/nuxt/head/api/get-started/overview)

[Releases](https://unhead.unjs.io/docs/nuxt/releases/v3)

Nuxt

- [Switch to Nuxt](https://unhead.unjs.io/docs/nuxt/schema-org/guides/get-started/overview)
- [Switch to TypeScript](https://unhead.unjs.io/docs/typescript/schema-org/guides/get-started/overview)
- [Switch to Vue](https://unhead.unjs.io/docs/vue/schema-org/guides/get-started/overview)
- [Switch to React](https://unhead.unjs.io/docs/react/schema-org/guides/get-started/overview)
- [Switch to Svelte](https://unhead.unjs.io/docs/svelte/schema-org/guides/get-started/overview)
- [Switch to Solid.js](https://unhead.unjs.io/docs/solid-js/schema-org/guides/get-started/overview)
- [Switch to Angular](https://unhead.unjs.io/docs/angular/schema-org/guides/get-started/overview)

v3 (stable)

Schema.org

- [Discord Support](https://discord.com/invite/275MBUBvgP)

- Get Started
  - [Introduction](https://unhead.unjs.io/docs/nuxt/schema-org/guides/get-started/overview)
- Core Concepts
  - [Deduping Nodes](https://unhead.unjs.io/docs/nuxt/schema-org/guides/core-concepts/deduping-nodes)
  - [Supported Nodes](https://unhead.unjs.io/docs/nuxt/schema-org/guides/core-concepts/nodes)
  - [Schema.org Params](https://unhead.unjs.io/docs/nuxt/schema-org/guides/core-concepts/params)
- Recipes
  - [Custom Nodes](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/custom-nodes)
  - [Identity](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/identity)
  - [Blog](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/blog)
  - [Breadcrumbs](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/breadcrumbs)
  - [eCommerce](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/e-commerce)
  - [FAQ](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/faq)
  - [How To](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/how-to)
  - [Site Search](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/site-search)

Get Started

# Unhead Schema.org

Last updated Apr 5, 2026 by [Harlan Wilton](https://github.com/harlan-zw) in [docs: documentation content audit and formatting improvements (#718)](https://github.com/unjs/unhead/pull/718).

On this page

- [What is Unhead Schema.org?](#what-is-unhead-schemaorg)
- [Background](#background)
- [How does Schema.org get page data?](#how-does-schemaorg-get-page-data)
- [How are duplicate nodes handled?](#how-are-duplicate-nodes-handled)
- [How are values transformed?](#how-are-values-transformed)
- [How Do Nodes Relate to Each Other?](#how-do-nodes-relate-to-each-other)
- [Testing Your Schema](#testing-your-schema)

## [What is Unhead Schema.org?](#what-is-unhead-schemaorg)

Unhead Schema.org automatically generates valid JSON-LD structured data for Google Rich Results. Instead of manually writing complex JSON-LD, you use simple TypeScript functions like `defineArticle()` or `defineProduct()` that handle validation, URL resolution, and Google requirements automatically.

### [Quick Start](#quick-start)

```
import { defineArticle, useSchemaOrg } from '#imports'

// Generates complete Article JSON-LD with all required Google fields
useSchemaOrg([
  defineArticle({
    headline: 'My Blog Post',
    image: '/images/post.jpg',
    datePublished: new Date(),
  })
])
```

## [Background](#background)

With Unhead Schema.org you can inject a Schema.org graph into your page.

Wrapper functions have been added to make opting in to [Google Rich Results](https://developers.google.com/search/docs/head/guides/core-concepts/search-gallery) nodes easier.

For officially supported nodes, when the graph is being resolved it will apply a number of transforms to ensure the data is valid for Google.

Otherwise, you can provide your own custom nodes that are passed through as is.

## [How does Schema.org get page data?](#how-does-schemaorg-get-page-data)

When resolving the graph, the package will inject config from the site and page level to reduce the amount of boilerplate.

For example, if you have a `<title>` on your page, then it's likely we can use this same title to generate the Schema.org WebPage's `name`.

The following inferences are from your `<head>` data:

- `inLanguage` - `<html lang="en">` (`en`)
- `name` - `<title>test</title>` (`test`)
- `description` - `<meta name="description" content="test">` (`test`)
- `url` - `<link rel="canonical" href="https://example.com/my-page">` (`https://example.com`)
- `image` - `<meta property="og:image" content="https://example.com/image.jpg">` (`https://example.com/image.jpg`)

Otherwise, they will come from your [Schema.org Params](https://unhead.unjs.io/docs/schema-org/guides/core-concepts/params).

## [How are duplicate nodes handled?](#how-are-duplicate-nodes-handled)

For certain nodes, only one of them can exist at once. For example, a page can only have one `WebPage` node.

When resolving the graph, the package will dedupe nodes based on the `@id` of the node.

## [How are values transformed?](#how-are-values-transformed)

There's numerous resolvers available to help minimise the work in maintaining and developing Schema.

In code examples, `@unhead/schema-org/@framework` is a placeholder. Replace `@framework` with your framework: `vue`, `react`, etc.

### [URL Transformer](#url-transformer)

Any URL field allows a relevant link to be provided. This link will either be prefixed with the canonical host or the canonical page URL.

```
import { defineComment } from '#imports'

defineComment({
  text: 'This is really cool!',
  author: {
    name: 'Harlan Wilton',
    url: '/user/harlan-wilton',
  }
})
```

```
[
  {
    "@id": "https://example.com/#/schema/person/1230192103",
    "@type": "Person",
    "name": "Harlan Wilton",
    "url": "https://example.com/user/harlan-wilton"
  },
  {
    "@id": "https://example.com/#/schema/comment/2288441280",
    "@type": "Comment",
    "author": {
      "@id": "https://example.com/#/schema/person/1230192103"
    },
    "text": "This is really cool!"
  }
]
```

### [Image Transformer](#image-transformer)

Uses the same relative link logic as the URL transformer.

Additionally, single string images will be transformed to an [ImageObject](https://schema.org/ImageObject) and added as a root node and an applicable link to the `@id` will be added.

```
import { defineWebPage } from '#imports'

defineWebPage({
  image: '/my-image.png',
})
```

```
{
  "@id": "https://example.com/#/schema/image/1571960974",
  "@type": "ImageObject",
  "contentUrl": "https://example.com//my-image.png",
  "url": "https://example.com//my-image.png"
}
```

### [ID Transformer](#id-transformer)

Providing an `@id` for a Schema node is sometimes useful to setup your own relations. When configuring the `@id` you can provide it as a simple string beginning with `#`.

The ID will be resolved to use the canonical host or the canonical page path as a prefix.

```
import { defineBreadcrumb } from '#imports'

defineBreadcrumb({
  '@id': '#subbreadcrumb',
  'itemListElement': [
    { name: 'Sub breadcrumb link', item: '/blog/test' },
  ],
})
```

```
{
  "@id": "https://example.com/#subbreadcrumb",
  "@type": "BreadcrumbList"
}
```

### [Type Transformer](#type-transformer)

Providing a string of `@type` will be augmented with the default type. This is to allow fallbacks when the specific `@type` is not supported by Google.

```
import { defineWebPage } from '#imports'

defineWebPage({
  '@type': 'FAQPage',
})
```

```
{
  "@type": [
    "WebPage",
    "FAQPage"
  ]
}
```

### [Date Transformer](#date-transformer)

Any date can be provided as a string or a js `Date` object. When a `Date` object is provided it will be transformed to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.

```
import { defineWebPage } from '#imports'

defineWebPage({
  datePublished: new Date(2022, 1, 10, 0, 0, 0),
})
```

```
{
  "datePublished": "2022-01-10T00:00:0+00:00"
}
```

## [How Do Nodes Relate to Each Other?](#how-do-nodes-relate-to-each-other)

Schema.org nodes form a graph with relationships. Unhead automatically creates these connections:

```
WebSite (your site identity)
   └── WebPage (each page)
         ├── Article / Product / etc. (page content type)
         └── BreadcrumbList (navigation path)
```

When you define nodes, Unhead links them automatically:

```
useSchemaOrg([
  defineWebSite({ name: 'My Blog' }), // Root node
  defineWebPage({ name: 'About Us' }), // Linked to WebSite
  defineArticle({ headline: 'My Post' }), // Linked to WebPage
])
```

The generated JSON-LD uses `@id` references to connect nodes, following Google's best practices.

## [Testing Your Schema](#testing-your-schema)

Always validate your Schema.org markup before deploying:

### [1. Google Rich Results Test](#_1-google-rich-results-test)

**URL:** [search.google.com/test/rich-results](https://search.google.com/test/rich-results)

Tests specifically for Google Rich Results eligibility. Shows:

- Which rich result types your page qualifies for
- Missing required fields
- Warnings about recommended fields

### [2. Schema.org Validator](#_2-schemaorg-validator)

**URL:** [validator.schema.org](https://validator.schema.org/)

General Schema.org validation. Shows:

- Syntax errors in JSON-LD
- Type mismatches
- Unknown properties

### [How Rich Results Appear in Google](#how-rich-results-appear-in-google)

When Schema.org is properly implemented, Google may display enhanced results:

| Schema Type | Rich Result |
| --- | --- |
| `Article` | Article preview with image, date, author |
| `Product` | Price, availability, star ratings |
| `FAQ` | Expandable Q&A directly in search results |
| `Recipe` | Cook time, ratings, calorie count |
| `Event` | Date, location, ticket availability |
| `BreadcrumbList` | Navigation path shown below title |

Rich Results are not guaranteed—Google decides based on quality and relevance. Valid Schema.org increases eligibility but doesn't guarantee display.

[Edit this page](https://github.com/unjs/unhead/edit/main/docs/schema-org/2.guides/0.get-started/0.overview.md)

[Markdown For LLMs](https://raw.githubusercontent.com/unjs/unhead/refs/heads/main/docs/schema-org/2.guides/0.get-started/0.overview.md)

Did this page help you?

[Plugins Create custom plugins with defineHeadPlugin to hook into Unhead's tag resolution, DOM rendering, and SSR lifecycle.](https://unhead.unjs.io/docs/head/api/plugins) [Deduping Nodes Automatic Schema.org node deduplication by @id. Add multiple nodes of same type with custom IDs, replace vs merge strategies.](https://unhead.unjs.io/docs/schema-org/guides/core-concepts/deduping-nodes)

On this page

- [What is Unhead Schema.org?](#what-is-unhead-schemaorg)
- [Background](#background)
- [How does Schema.org get page data?](#how-does-schemaorg-get-page-data)
- [How are duplicate nodes handled?](#how-are-duplicate-nodes-handled)
- [How are values transformed?](#how-are-values-transformed)
- [How Do Nodes Relate to Each Other?](#how-do-nodes-relate-to-each-other)
- [Testing Your Schema](#testing-your-schema)

[GitHub](https://github.com/unjs/unhead) [ Discord](https://discord.com/invite/275MBUBvgP)

[ /llms.txt](https://unhead.unjs.io/llms.txt)

[Part of the UnJS ecosystem](https://unjs.io/)

### Head Management

- [Getting Started](https://unhead.unjs.io/docs/nuxt/head/guides/get-started/overview)
- [useHead](https://unhead.unjs.io/docs/nuxt/head/api/composables/use-head)
- [useSeoMeta](https://unhead.unjs.io/docs/nuxt/head/api/composables/use-seo-meta)
- [useHeadSafe](https://unhead.unjs.io/docs/nuxt/head/api/composables/use-head-safe)
- [useScript](https://unhead.unjs.io/docs/nuxt/head/api/composables/use-script)

### Schema.org

- [Getting Started](https://unhead.unjs.io/docs/nuxt/schema-org/guides/get-started/overview)
- [useSchemaOrg](https://unhead.unjs.io/docs/nuxt/schema-org/api/composables/use-schema-org)
- [Nodes](https://unhead.unjs.io/docs/nuxt/schema-org/guides/core-concepts/nodes)
- [Recipes](https://unhead.unjs.io/docs/nuxt/schema-org/guides/recipes/identity)

### Guides

- [Titles](https://unhead.unjs.io/docs/nuxt/head/guides/core-concepts/titles)
- [Streaming SSR](https://unhead.unjs.io/docs/nuxt/head/guides/core-concepts/streaming)
- [DOM Events](https://unhead.unjs.io/docs/nuxt/head/guides/core-concepts/dom-event-handling)
- [Plugins](https://unhead.unjs.io/docs/nuxt/head/guides/plugins/template-params)

### Tools

- [Meta Tag Generator](https://unhead.unjs.io/tools/meta-tag-generator)
- [OG Image Generator](https://unhead.unjs.io/tools/og-image-generator)
- [Schema.org Generator](https://unhead.unjs.io/tools/schema-generator)
- [Capo.js Analyzer](https://unhead.unjs.io/tools/capo-analyzer)

### Articles

- [What is Capo.js?](https://unhead.unjs.io/learn/guides/what-is-capo)

### Research

- [State of <head> in 2026](https://unhead.unjs.io/learn/research/state-of-head-2026)
- [Streaming Head Performance](https://unhead.unjs.io/learn/research/streaming-head-performance)
- [Capo.js Performance Research](https://unhead.unjs.io/learn/research/capo-performance-research)

Copyright © 2025-2026 Harlan Wilton - [MIT License](https://github.com/unjs/unhead/blob/main/license)