TypeScript
You're viewing Unhead v3 beta documentation.
Get Started

Unhead Schema.org

What is Unhead Schema.org?

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

import { defineArticle, useSchemaOrg } from '@unhead/schema-org/typescript'

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

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 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?

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.

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?

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

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 '@unhead/schema-org/typescript'

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

Uses the same relative link logic as the URL transformer.

Additionally, single string images will be transformed to an ImageObject and added as a root node and an applicable link to the @id will be added.

import { defineWebPage } from '@unhead/schema-org/typescript'

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

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 '@unhead/schema-org/typescript'

defineBreadcrumb({
  '@id': '#subbreadcrumb',
  'itemListElement': [
    { name: 'Sub breadcrumb link', item: '/blog/test' },
  ],
})
{
  "@id": "https://example.com/#subbreadcrumb",
  "@type": "BreadcrumbList"
}

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 '@unhead/schema-org/typescript'

defineWebPage({
  '@type': 'FAQPage',
})
{
  "@type": [
    "WebPage",
    "FAQPage"
  ]
}

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 format.

import { defineWebPage } from '@unhead/schema-org/typescript'

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?

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

Always validate your Schema.org markup before deploying:

1. Google Rich Results Test

URL: 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

URL: validator.schema.org

General Schema.org validation. Shows:

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

How Rich Results Appear in Google

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

Schema TypeRich Result
ArticleArticle preview with image, date, author
ProductPrice, availability, star ratings
FAQExpandable Q&A directly in search results
RecipeCook time, ratings, calorie count
EventDate, location, ticket availability
BreadcrumbListNavigation 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.
Did this page help you?