Template Params Plugin
Template params replace placeholders such as %s and %siteName during tag resolution. Configure them with templateParams: { siteName: 'My Site', separator: '·' } in useHead().
Template params
The Template Params plugin replaces named placeholders across titles and tag properties during head resolution.
Setup
Add the plugin to your Unhead configuration:
import { createHead } from 'unhead/client'
import { TemplateParamsPlugin } from 'unhead/plugins'
const head = createHead({
plugins: [
TemplateParamsPlugin
]
})
Built-in params
Unhead includes these built-in template params:
| Token | Description |
|---|---|
%s | The current page title |
%pageTitle | Alias for the current page title |
%separator | Smart separator (defaults to |) |
%separator appears only between non-empty content. It removes itself when:
- The title is empty
- Multiple separators would appear next to each other
useHead(unheadInstance, {
title: 'Home',
titleTemplate: '%s %separator %siteName',
templateParams: {
separator: '—', // Use an em dash instead of |
siteName: 'MySite'
}
})
<title>Home — MySite</title>
Separators
Choose a separator that matches the site's title style:
// Choose a more readable separator
useHead(unheadInstance, {
templateParams: {
separator: '—' // Em dash
// Other options: '-' (hyphen), '•' (bullet), '·' (middot), '❤️' (heart)
}
})
Meta tags
Template params also work with SEO meta tags and social metadata:
useHead(unheadInstance, {
templateParams: {
siteName: 'MyApp',
separator: '·'
},
title: 'Home',
meta: [
{ name: 'description', content: 'Read the latest updates from %siteName' },
{ property: 'og:title', content: 'Home %separator %siteName' },
{ property: 'og:description', content: 'Check out %siteName today!' }
]
})
<head>
<title>Home · MyApp</title>
<meta name="description" content="Read the latest updates from MyApp">
<meta property="og:title" content="Home · MyApp">
<meta property="og:description" content="Check out MyApp today!">
</head>
Scripts and other inline content
Enable for Script and Other Tags
For tags using innerHTML or textContent, add processTemplateParams: true:
useHead(unheadInstance, {
templateParams: { name: 'My App' },
script: [
{
innerHTML: { name: '%name' },
type: 'application/json',
processTemplateParams: true
}
]
})
<script type="application/json">{"name":"My App"}</script>
Disabling template processing
Add processTemplateParams: false to skip template processing:
useHead(unheadInstance, {
title: 'Hello %name',
templateParams: { name: 'World' },
}, {
processTemplateParams: false,
})
<title>Hello %name</title>
Shared and nested values
Shared brand values
Define shared brand values once, then reference them from page entries:
// In your site setup
const head = createHead({
plugins: [
TemplateParamsPlugin
]
})
// Define global template params
head.push({
templateParams: {
brand: 'ProductName™',
tagline: 'Release notes and migration guides',
separator: '—'
}
})
// In page components
useHead(unheadInstance, {
title: 'Features',
titleTemplate: '%s %separator %brand',
meta: [
{ name: 'description', content: '%brand: %tagline' }
]
})
Nested objects
Use nested objects for more structured data:
useHead(unheadInstance, {
templateParams: {
site: {
name: 'My Site',
url: 'https://example.com',
},
separator: '·',
subPage: null
},
title: 'My Page',
titleTemplate: '%s %separator %subPage %separator %site.name',
meta: [
{
name: 'description',
content: 'Welcome to %site.name.',
},
{
property: 'og:site_name',
content: '%site.name',
},
{
property: 'og:url',
content: '%site.url/my-page',
},
],
})
<head>
<title>My Page · My Site</title>
<meta name="description" content="Welcome to My Site.">
<meta property="og:site_name" content="My Site">
<meta property="og:url" content="https://example.com/my-page">
</head>
Related
- Canonical Plugin: Normalize absolute URLs
- Infer SEO Meta: Generate social metadata
ESLint Plugin
Catch unhead misuse, type-narrowing gaps, and v2-to-v3 migration problems at the source level. Pairs with the runtime ValidatePlugin and the unhead CLI.
Alias Sorting
Order head tags with before: and after: prefixes. More readable than numeric priorities for script loading and CSS dependencies.