---
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