---
title: "entries:normalize Hook"
description: "Hook for changing the normalized tags produced by an individual head entry."
canonical_url: "https://unhead.unjs.io/docs/head/api/hooks/entries-normalize"
last_updated: "2026-08-11T00:38:17.368Z"
---

The `entries:normalize` hook runs once for each uncached entry after its input has been normalized into tags. It runs before Unhead assigns internal weights and deduplication keys.

At the start of resolution, Unhead compares the combined number of `entries:resolve` and `entries:normalize` listeners with the previous resolution. If that count changed, it clears every entry's normalization cache. Uncached entries pass through this hook once, then remain cached until their input changes or a later listener-count change invalidates them.

## Hook Signature

```ts
export interface Hook {
  'entries:normalize': (ctx: {
    tags: HeadTag[]
    entry: HeadEntry<any>
  }) => SyncHookResult
}
```

### Parameters

<table>
<thead>
  <tr>
    <th>
      Name
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        ctx.tags
      </code>
    </td>
    
    <td>
      <code>
        HeadTag[]
      </code>
    </td>
    
    <td>
      Tags normalized from this entry
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        ctx.entry
      </code>
    </td>
    
    <td>
      <code>
        HeadEntry<any>
      </code>
    </td>
    
    <td>
      The entry that produced the tags
    </td>
  </tr>
</tbody>
</table>

This hook is synchronous. You may mutate `ctx.tags` in place or replace it with another array.

## Usage Example

```ts
import { defineHeadPlugin } from '@unhead/dynamic-import/plugins'

export const descriptionPrefixPlugin = defineHeadPlugin({
  key: 'description-prefix',
  hooks: {
    'entries:normalize': ({ tags }) => {
      for (const tag of tags) {
        if (tag.tag === 'meta' && tag.props.name === 'description')
          tag.props.content = `Preview: ${tag.props.content}`
      }
    }
  }
})
```

`HeadEntry` fields whose names begin with `_` are internal. Avoid storing plugin state on them.
