Page Titles with Unhead
Introduction
Page titles are crucial for SEO. They're your primary call-to-action in search results and help users understand your page's content and context.
<head>
<title>Mastering Titles · My App<</title>
</head>
While setting page titles with Unhead is straightforward, certain scenarios can be tricky. Let's start with the essential patterns you should follow.
Understanding the Title Tags
The <title>
tag displays text in browser tabs and typically appears as your page's heading in search engine results (SERPs).
In Vue, you might be tempted to set titles directly:
// ❌ Careful! This won't work in SSR
document.title = 'Home'
This approach has two major issues:
It breaks during Server-Side Rendering (SSR) Search engines may not properly index your titles
Instead, use Vue's head manager Unhead (already included in Nuxt). New to SEO titles? Check out Google's guide on Influencing your title links in search results.
useHead()
Dynamic Page Titles with
Now that we understand why direct title manipulation won't work, let's use Unhead's useHead()
composable to set titles properly:
useHead({
title: 'Home'
})
<head>
<title>Home</title>
</head>
This single line creates an SSR-friendly title that search engines can read. The composable handles all the complexity of managing your document head in both client and server environments.
You can use this in any component and set any <head>
tag you like.
useHead({
title: 'Home',
meta: [
{ name: 'description', content: 'Welcome to MyApp' }
]
})
Setting Up Title Templates
You may notice that most people set up their titles with a site name and a separator, this is seen as a best practice as it can help with brand recognition and SEO.
<head>
<title>Home | MySite</title>
</head>
Creating your own title like this is simple using useHead()
with a Title Template.
useHead({
title: 'Home',
titleTemplate: '%s | MySite'
})
<head>
<title>Home | MySite</title>
</head>
Template params like %s
act as placeholders that get replaced with your page title and separator.
Template Params
Template params are an opt-in plugin make your tags more dynamic. You get %s
and %separator
built-in, and can add your own:
useHead({
title: 'Home',
titleTemplate: '%s %separator %siteName',
templateParams: {
separator: '·',
siteName: 'My Site'
}
})
<title>Home · My Site</title>
Check out the Template Params guide to get started.
Resetting the Title Template
If you need to reset the title template for a specific page, you can pass null
to the titleTemplate
option.
<script lang="ts" setup>
useHead({
title: 'Home',
titleTemplate: null
})
</script>
<head>
<title>Home</title>
</head>
Social Share Titles
Social platforms use different meta tags for sharing titles.

In the above we can see the title "Nuxt: The Intuitive Vue Framework".
This title is set using the twitter:title
meta tag and will fall back to the og:title
meta tag if not set.
Remembering how to use the meta tags can be annoying, so we can use the useSeoMeta()
composable to set these up.
useSeoMeta({
titleTemplate: '%s | Health Tips',
title: 'Why you should eat more broccoli',
// og title is not effected by titleTemplate, we can use template params here if we need
ogTitle: 'Hey! Health Tips - 10 reasons to eat more broccoli.',
// explicit twitter title is only needed when we want to display something just for X
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="Health Tips: 10 reasons to eat more broccoli." />
<meta name="twitter:title" content="Hey X! Health Tips - 10 reasons to eat more broccoli." />
</head>