Tag Deduplication
Introduction
When implementing head tags across an application hierarchy (layouts, pages, components), you'll often need to override tags. This automatic replacement of duplicate tags is called "deduplication" or "deduping."
Unhead intelligently determines which tags are duplicates based on HTML specifications about which elements can appear multiple times in the DOM.
For example, you can only have one title
element, and a single <meta name="description">
tag in a valid HTML document.
Deduplication Logic
When you register multiple tags that are considered duplicates, only the most recent one will be used by default. This allows page-level components to override tags defined at the layout level.
How Duplicates Are Identified
Unhead uses several strategies to identify duplicate tags:
- Special singleton tags:
base
,title
,titleTemplate
,bodyAttrs
,htmlAttrs
- Specific link types:
<link rel="canonical">
- Charset metadata:
<meta charset="">
- Custom keys: Any tag with a matching
key
attribute - Meta tag identifiers: Matching
name
,property
, orhttp-equiv
attributes
Example: Meta Description Override
import { useHead } from '@unhead/svelte'
// Called in a layout component (higher in the hierarchy)
useHead({
meta: [
{
name: 'description',
content: 'my site wide description',
},
],
})
// Called in a page component (lower in the hierarchy)
useHead({
meta: [
{
name: 'description',
content: 'my page description',
},
],
})
// Result in the rendered HTML:
// <meta name="description" content="my page description" />
Allowing Multiple Tags with the Same Name
While deduplication is useful in most cases, there are scenarios where you need multiple tags with the same identifiers. A common example is verification tags from multiple services.
Using Content Arrays
To have multiple meta tags with the same name
attribute, you can provide an array of values for the content
attribute:
import { useHead } from '@unhead/svelte'
useHead({
meta: [
{
name: 'google-site-verification',
content: [
'verification-id-1',
'verification-id-2',
]
},
],
})
// Result in HTML:
// <meta name="google-site-verification" content="verification-id-1">
// <meta name="google-site-verification" content="verification-id-2">
Multiple Tags in a Single Entry
Unhead also intelligently preserves multiple tags with the same identifier when they're defined within a single useHead()
call:
import { useHead } from '@unhead/svelte'
useHead({
meta: [
{
name: 'google-site-verification',
content: 'verification-id-1'
},
{
name: 'google-site-verification',
content: 'verification-id-2'
},
],
})
// Result in HTML:
// <meta name="google-site-verification" content="verification-id-1">
// <meta name="google-site-verification" content="verification-id-2">
Using Custom Keys for Precise Control
When you need more fine-grained control over deduplication, you can provide a custom key
attribute to your tags.
The key serves as a unique identifier, ensuring that only one instance of a tag with that key exists in the final HTML output. This works regardless of the tag type or other attributes.
Example: Ensuring Script Uniqueness
import { useHead } from '@unhead/svelte'
useHead({
script: [
{
src: 'https://example.com/script.js',
key: 'my-script',
},
]
})
- Managing third-party scripts across components
- Ensuring unique instances of specific resources
- Creating explicit relationships between tags in different components
Overriding Tags Using Keys
Any tag can be overridden or removed by using the same key in a subsequent useHead()
call, regardless of the tag type or other properties.
Customizing Duplicate Handling Strategy
By default, when a duplicate tag is found, Unhead will replace
the existing tag with the new one.
Default Strategies
- For most tags: The default strategy is
replace
- the new tag completely replaces the old one - For attribute tags: When dealing with
htmlAttrs
andbodyAttrs
, the default strategy ismerge
- allowing you to add attributes without removing existing ones (especially useful forclass
andstyle
properties)
tagDuplicateStrategy
Property The
You can explicitly control this behavior using the tagDuplicateStrategy
property:
import { useHead } from '@unhead/svelte'
// In a layout file we added a class
useHead({
htmlAttrs: {
class: 'my-class',
},
})
// On a specific page, we want to replace instead of merge
useHead({
htmlAttrs: {
tagDuplicateStrategy: 'replace', // Override the default merge behavior
class: 'my-new-class',
},
})
// Result in HTML:
// <html class="my-new-class">
tagDuplicateStrategy
is particularly useful when:- You need to completely replace HTML/body attributes instead of merging them
- You want to ensure clean slate behavior for certain tags
Practical Examples
Removing a Tag from a Parent Component
You can remove a tag defined in a parent component by using its key with an empty object:
import { useHead } from '@unhead/svelte'
// A layout file sets the background color to red
useHead({
style: [
{
key: 'red-bg',
textContent: 'body { color: red }',
}
]
})
// On a specific page, we want to remove that style
useHead({
style: [
{
// A tag with only a key will be removed
key: 'red-bg',
}
]
})
// Result: No style is rendered
Replacing a Style with a Different Value
import { useHead } from '@unhead/svelte'
// A layout file sets the background color to red
useHead({
style: [
{
key: 'bg-colour',
textContent: 'body { color: red }',
}
]
})
// In a page component, we want to change it to blue
useHead({
style: [
{
key: 'bg-colour',
textContent: 'body { color: blue }',
}
]
})
// Result: Only the blue style is rendered
Common Use Cases
- Layout/Page Overrides: Define base tags in layouts and override them in specific pages
- Component-Specific Tags: Add tags in components that won't conflict with others
- Feature Toggles: Enable/disable certain tags based on feature flags
- Third-Party Integrations: Manage verification tags from multiple services
- Environment-Specific Settings: Change tags based on development, staging, or production environments