Index of every page on this site: llms.txt
TypeScript
Composables

useSchemaOrg: Add Schema.org JSON-LD to Vue and Nuxt

Implementation overview

useSchemaOrg() adds typed, reactive Schema.org nodes to the document head. This guide explains node definitions, graph relationships, deduplication, framework imports, and server-rendered JSON-LD output.

The useSchemaOrg() composable adds one or more Schema.org nodes to the page.

useSchemaOrg(unheadInstance, input, options)

Example

Define an Article node:

useSchemaOrg(unheadInstance, [
  defineArticle({
    headline: 'My Blog Post',
    image: '/images/post.jpg',
    datePublished: new Date(),
  })
])

Input

The input accepts one Schema.org node or an array of nodes. Nodes can come from define* helpers or be plain objects:

type UseSchemaOrgInput = Thing | Record<string, any> | Array<Thing | Record<string, any>>

Available node functions include:

  • defineWebSite(): Site-level metadata
  • defineWebPage(): Page-level metadata
  • defineArticle(): Blog posts and articles
  • defineProduct(): E-commerce products
  • defineOrganization(): Company/organization info
  • definePerson(): Author/person profiles
  • defineBreadcrumb(): Navigation breadcrumbs
  • Browse all node helpers

Options

The second parameter accepts HeadEntryOptions for the generated head entry:

export interface HeadEntryOptions {
  processTemplateParams?: boolean
  tagPriority?: number | 'critical' | 'high' | 'low' | `before:${string}` | `after:${string}`
  tagPosition?: 'head' | 'bodyClose' | 'bodyOpen'
  key?: string
  tagDuplicateStrategy?: 'replace' | 'merge'
  head?: Unhead
  onRendered?: (ctx: { renders: DomRenderTagContext[] }) => void | Promise<void>
}

Entry API

The useSchemaOrg composable returns an entry that you can patch or dispose.

const schemaEntry = useSchemaOrg(unheadInstance, [
  defineWebPage({ name: 'My Page' })
])

// removes the schema nodes
schemaEntry.dispose()

XSS safety

The rendered JSON-LD is escaped so input cannot close the script element. Unhead does not validate node values or sanitize HTML contained in them.

Do not pass unknown or untrusted third-party input without validating and sanitizing it first.

Common Questions

How do I add multiple schema types to a page?

Pass an array to useSchemaOrg(); each item becomes a node in the graph.

useSchemaOrg(unheadInstance, [
  defineWebPage({ name: 'Product Page' }),
  defineProduct({
    name: 'Widget',
    offers: { price: 29.99, priceCurrency: 'USD' },
  }),
  defineBreadcrumb({
    itemListElement: [
      { name: 'Home', item: '/' },
      { name: 'Products', item: '/products' },
    ]
  })
])

Do I need to set @id manually?

Usually not. Helpers with primary roles use stable IDs, while other nodes receive numbered IDs. Set @id when you need a specific identity or several separately addressable nodes.

How does Schema.org get page metadata?

The plugin collects metadata from <title>, the meta description, the canonical link's host, og:image, <html lang>, and templateParams.schemaOrg. Each resolver chooses which values to inherit.

See Also

Did this page help you?