--- title: Tag Deduplication description: Learn how Unhead manages duplicate tags across your application with automatic deduplication. navigation.title: 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`{lang="html"} element, and a single `<meta name="description">`{lang="html"} 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">`{lang="html"} - **Charset metadata**: `<meta charset="">`{lang="html"} - **Custom keys**: Any tag with a matching `key` attribute - **Meta tag identifiers**: Matching `name`, `property`, or `http-equiv` attributes ::note The deduplication process happens automatically during the head tag resolution phase. :: ### Example: Meta Description Override ```ts import { useHead } from '@unhead/dynamic-import' // 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" /> ``` ::tip You can control which tag takes precedence using [Tag Priorities](/guides/positions) to override the default "most recent wins" behavior. :: ## 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: ```ts import { useHead } from '@unhead/dynamic-import' 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()`{lang="ts"} call: ```ts import { useHead } from '@unhead/dynamic-import' 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"> ``` ::tip This behavior is specifically designed for verification tags and similar use cases where multiple tags with the same name are valid and necessary. :: ## Using Custom Keys for Precise Control When you need more fine-grained control over deduplication, you can provide a custom `key`{lang="ts"} 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 ```ts import { useHead } from '@unhead/dynamic-import' useHead({ script: [ { src: 'https://example.com/script.js', key: 'my-script', }, ] }) ``` ::note Custom keys are particularly useful for: - 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()`{lang="ts"} 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` and `bodyAttrs`, the default strategy is `merge` - allowing you to add attributes without removing existing ones (especially useful for `class` and `style` properties) ### The `tagDuplicateStrategy` Property You can explicitly control this behavior using the `tagDuplicateStrategy`{lang="ts"} property: ```ts import { useHead } from '@unhead/dynamic-import' // 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"> ``` ::tip The `tagDuplicateStrategy`{lang="ts"} 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: ```ts import { useHead } from '@unhead/dynamic-import' // 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 ```ts import { useHead } from '@unhead/dynamic-import' // 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