---
title: "useSchemaOrg()"
description: "Add Schema.org structured data with useSchemaOrg(). Pass one or more typed or custom nodes and manage the resulting head entry."
canonical_url: "https://unhead.unjs.io/docs/schema-org/api/composables/use-schema-org"
last_updated: "2026-08-11T00:41:28.089Z"
---

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

```ts
useSchemaOrg(input, options)
```

## Example

Define an Article node:

```ts
useSchemaOrg([
  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:

```ts
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](/docs/schema-org/api/schema/article)

## Options

The second parameter accepts `HeadEntryOptions` for the generated head entry:

```ts
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`.

```ts
const schemaEntry = useSchemaOrg([
  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.

```ts
useSchemaOrg([
  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

- [useHead()](/docs/head/api/composables/use-head): General head management
- [useSeoMeta()](/docs/head/api/composables/use-seo-meta): SEO meta tag management
- [Schema.org Nodes](/docs/schema-org/guides/core-concepts/nodes): How to define and relate schema types
