Page Titles with Unhead
Use useHead({ title: 'Your Title' }) for a title that works in both server and client rendering. Add titleTemplate: '%s | Site Name' when pages share the same suffix.
<head>
<title>Mastering Titles · My App</title>
</head>
The title element
The <title> tag labels the document in browser tabs and is one of several sources Google may use to generate a search-result title link.
Setting document.title directly works only in a browser:
// Browser-only: document is unavailable during SSR
document.title = 'Home'
document.title is unavailable during server-side rendering and bypasses Unhead's server output.Google documents how page titles and other signals can influence title links in search results.
Dynamic Page Titles with useHead()
Use useHead() to register a title with the active head instance:
import { useHead } from 'unhead'
useHead(unheadInstance, {
title: 'Home'
})
<head>
<title>Home</title>
</head>
The entry is included in server output and kept in sync on the client. The same entry can include other head tags:
import { useHead } from 'unhead'
useHead(unheadInstance, {
title: 'Home',
meta: [
{ name: 'description', content: 'Welcome to MyApp' }
]
})
Reactivity follows the conventions of each framework adapter; the useHead() input shape stays the same.
Shared site names
Set a shared site name and separator with a title template:
<head>
<title>Home | MySite</title>
</head>
import { useHead } from 'unhead'
useHead(unheadInstance, {
title: 'Home',
titleTemplate: '%s | MySite'
})
<head>
<title>Home | MySite</title>
</head>
The %s placeholder in a string titleTemplate is replaced with the page title. Additional template params require TemplateParamsPlugin.
Template Params
Template params are an opt-in feature for making tags more dynamic. Register TemplateParamsPlugin when creating the head instance, then provide templateParams with your entry. The plugin supplies %s, %separator, and your custom parameters:
import { useHead } from 'unhead'
useHead(unheadInstance, {
title: 'Home',
titleTemplate: '%s %separator %siteName',
templateParams: {
separator: '·',
siteName: 'My Site'
}
})
<title>Home · My Site</title>
content, link href, and the lang HTML attribute. Other inline content requires processTemplateParams: true on the tag.See Template Params for the complete placeholder rules.
Resetting the Title Template
Pass null to titleTemplate to disable an inherited template for one page.
<script lang="ts" setup>
import { useHead } from 'unhead'
useHead({
title: 'Home',
titleTemplate: null
})
</script>
<head>
<title>Home</title>
</head>
Social Share Titles
Social platforms use different meta tags for sharing titles.

The example preview uses X-specific title metadata alongside the standard og:title field. Use
useSeoMeta() to set these fields by name:
import { useSeoMeta } from 'unhead'
useSeoMeta(unheadInstance, {
titleTemplate: '%s | Health Tips',
title: 'Why you should eat more broccoli',
// ogTitle is not affected by titleTemplate; use template params here if needed
ogTitle: 'Hey! Health Tips - 10 reasons to eat more broccoli.',
// Legacy X-specific override; twitterTitle is deprecated in favor of ogTitle
twitterTitle: 'Hey X! Health Tips - 10 reasons to eat more broccoli.',
})
<head>
<title>Why you should eat more broccoli | Health Tips</title>
<meta property="og:title" content="Hey! Health Tips - 10 reasons to eat more broccoli." />
<meta name="twitter:title" content="Hey X! Health Tips - 10 reasons to eat more broccoli." />
</head>
The useSeoMeta input shape is the same across Vue, React, Svelte, Solid, and Angular.
Common Use Cases
Reactive Titles
Pass a getter to update a title when component state changes:
import { useHead } from 'unhead'
import { ref } from 'vue'
const productName = ref('Widget X')
const isLoading = ref(true)
useHead(unheadInstance, {
title: () => isLoading.value
? 'Loading...'
: `Product: ${productName.value}`
})
Hierarchical Titles
For nested pages like documentation, show hierarchy:
import { useHead } from 'unhead'
// Works in any framework
useHead(unheadInstance, {
title: 'Installation',
titleTemplate: '%s | Documentation | MyApp'
})
Language-Specific Titles
For multilingual sites:
import { useHead } from 'unhead'
// In a real app, you'd get this from your i18n library
const locale = 'en'
const titles = {
en: 'Welcome',
fr: 'Bienvenue',
es: 'Bienvenido'
}
useHead(unheadInstance, {
title: titles[locale] || titles.en,
htmlAttrs: {
lang: locale
}
})
import { useHead } from 'unhead'
import { useTranslation } from 'react-i18next' // Example i18n library
function HomePage() {
const { t, i18n } = useTranslation()
useHead(unheadInstance, {
title: t('home.title'),
htmlAttrs: {
lang: i18n.language
}
})
return <div>Home Page</div>
}
Writing useful titles
Google recommends descriptive, concise, page-specific title text. Search results truncate titles as needed for the device, so there is no fixed character limit.
- Keep titles concise and descriptive rather than targeting a fixed character count
- Make each page title unique across your site
- Keep shared branding brief so the page-specific text remains distinct
- Ensure titles accurately describe the page content