---
title: "Upgrade Guide"
description: "Learn how to migrate between Unhead versions for React users."
canonical_url: "https://unhead.unjs.io/docs/react/head/guides/get-started/migration"
last_updated: "2026-07-29T16:41:58.475Z"
---

## Migrate to v3 (from v2)

Unhead v3 changes several core defaults and removes v2 compatibility behavior.

### Legacy Property Names

🚦 Impact Level: High

The current `createHead()` entry points omit `DeprecationsPlugin`. Rename these properties before upgrading; the deprecated plugin is still available for staged migrations.

**children → innerHTML**

```diff
useHead({
  script: [{
-   children: 'console.log("hello")',
+   innerHTML: 'console.log("hello")',
  }]
})
```

**hid / vmid → key**

```diff
useHead({
  meta: [{
-   hid: 'description',
+   key: 'description',
    name: 'description',
    content: 'My description'
  }]
})
```

**body: true → tagPosition: 'bodyClose'**

```diff
useHead({
  script: [{
    src: '/script.js',
-   body: true,
+   tagPosition: 'bodyClose',
  }]
})
```

### Schema.org Plugin

🚦 Impact Level: High

If you're using `@unhead/schema-org`, the plugin exports have changed:

```diff
- import { SchemaOrgUnheadPlugin } from '@unhead/schema-org'
+ import { UnheadSchemaOrg } from '@unhead/schema-org'

const head = createHead({
  plugins: [
-   SchemaOrgUnheadPlugin()
+   UnheadSchemaOrg()
  ]
})
```

### Core API Changes

🚦 Impact Level: Medium

**headEntries() → entries Map**

```diff
- const entries = head.headEntries()
+ const entries = [...head.entries.values()]
```

**mode Option Removed**

The `mode` option on head entries has been removed. Use conditional logic instead:

```ts
if (typeof window !== 'undefined') {
  useHead({ title: 'Client Only' })
}
```

### Hooks

🚦 Impact Level: Low

The `init` hook was removed. `dom:renderTag` remains in the type definitions for compatibility but is deprecated and no longer called internally. `dom:rendered` is also deprecated but is still emitted; prefer the `onRendered` entry option for entry-specific work.

The `dom:beforeRender` hook is now synchronous and `renderDOMHead` no longer returns a Promise:

```diff
- await renderDOMHead(head, { document })
+ renderDOMHead(head, { document })
```

The SSR hooks (`ssr:beforeRender`, `ssr:render`, `ssr:rendered`) are now synchronous and `renderSSRHead` no longer returns a Promise:

```diff
- const head = await renderSSRHead(head)
+ const head = renderSSRHead(head)
```
