Svelte
Core Concepts

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, or http-equiv attributes
The deduplication process happens automatically during the head tag resolution phase.

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" />
You can control which tag takes precedence using Tag Priorities 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:

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">
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 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',
    },
  ]
})
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() 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 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">
The 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
Did this page help you?