---
title: "dom:beforeRender Hook · v2 · Unhead"
meta:
  "og:description": "Learn about the dom:beforeRender hook in Unhead that runs before tags are rendered to the DOM"
  "og:title": "dom:beforeRender Hook · v2 · Unhead"
  description: "Learn about the dom:beforeRender hook in Unhead that runs before tags are rendered to the DOM"
---

**Hooks**

# **dom:beforeRender Hook**

**On this page **

- [Hook Signature](#hook-signature)
- [Usage Example](#usage-example)
- [Use Cases](#use-cases)

The `dom:beforeRender` hook is called before tags are rendered to the DOM in client-side environments. This hook allows you to control whether rendering should proceed and provides access to rendering context.

## [Hook Signature](#hook-signature)

```
export interface Hook {
  'dom:beforeRender': (ctx: DomBeforeRenderCtx) => HookResult
}
```

### [Parameters](#parameters)

| **Name** | **Type** | **Description** |
| --- | --- | --- |
| `ctx` | `DomBeforeRenderCtx` | Context object with rendering information |

The `DomBeforeRenderCtx` interface extends `ShouldRenderContext`:

```
interface DomBeforeRenderCtx extends ShouldRenderContext {
  tags: DomRenderTagContext[] // Note: this is deprecated and will always be empty
}

interface ShouldRenderContext {
  shouldRender: boolean
}
```

### [Returns](#returns)

`HookResult` which is either `void` or `Promise<void>`

## [Usage Example](#usage-example)

```
import { createHead } from '#imports'

const head = createHead({
  hooks: {
    'dom:beforeRender': (ctx) => {
      // Log rendering intent
      console.log('About to render tags to DOM')

      // You can prevent rendering by setting shouldRender to false
      if (window.document.querySelector('meta[name="unhead-rendered"]')) {
        console.log('Preventing re-render as tags are already rendered')
        ctx.shouldRender = false
      }
    }
  }
})
```

## [Use Cases](#use-cases)

### [Conditional Rendering](#conditional-rendering)

Control whether rendering should proceed based on page conditions:

```
import { defineHeadPlugin } from '#imports'

export const conditionalRenderPlugin = defineHeadPlugin({
  hooks: {
    'dom:beforeRender': (ctx) => {
      // Only render head tags if we're not in a specific context
      if (window.location.pathname.startsWith('/admin')) {
        // For admin pages, we want to prevent automatic rendering
        // because we'll handle it differently
        ctx.shouldRender = false
      }

      // Prevent rendering during specific user interactions
      if (document.body.classList.contains('modal-open')) {
        // Don't update head while modal is open to prevent flickering
        ctx.shouldRender = false
      }
    }
  }
})
```

### [Render Preparation](#render-preparation)

Prepare the DOM environment before rendering:

```
import { defineHeadPlugin } from '#imports'

export const renderPreparationPlugin = defineHeadPlugin({
  hooks: {
    'dom:beforeRender': () => {
      // Add rendering flag to prevent duplicate processing
      if (!document.querySelector('meta[name="unhead-render-id"]')) {
        const meta = document.createElement('meta')
        meta.setAttribute('name', 'unhead-render-id')
        meta.setAttribute('content', Date.now().toString())
        document.head.appendChild(meta)
      }

      // Clean up specific tags that we always want to manage ourselves
      const existingCanonical = document.querySelector('link[rel="canonical"]')
      if (existingCanonical) {
        existingCanonical.remove()
      }
    }
  }
})
```

### [Delayed Rendering](#delayed-rendering)

Set up delayed rendering for better performance:

```
import { defineHeadPlugin } from '#imports'

export const delayedRenderPlugin = defineHeadPlugin({
  hooks: {
    'dom:beforeRender': (ctx) => {
      // Check if this is the initial page load
      const isInitialLoad = !document.querySelector('[data-unhead-rendered]')

      if (isInitialLoad) {
        // For initial load, we can delay non-critical head updates
        // until the page has finished loading
        if (document.readyState !== 'complete') {
          // Delay rendering until page is complete
          ctx.shouldRender = false

          // Set up listener to trigger rendering when ready
          window.addEventListener('load', () => {
            // Force head to re-evaluate rendering
            setTimeout(() => {
              head.hooks.callHook('entries:updated', head)
            }, 0)
          }, { once: true })
        }
      }
    }
  }
})
```

[Edit this page](https://github.com/unjs/unhead/edit/v2.1.2/docs/v2/head/7.api/hooks/09.dom-before-render.md)

**Did this page help you? **

[**tags:afterResolve** Learn about the tags:afterResolve hook in Unhead that runs after tags have been fully resolved](https://unhead.unjs.io/docs/v2/head/api/hooks/tags-after-resolve) [**dom:renderTag** Learn about the dom:renderTag hook in Unhead that controls how individual tags are rendered to the DOM](https://unhead.unjs.io/docs/v2/head/api/hooks/dom-render-tag)

**On this page **

- [Hook Signature](#hook-signature)
- [Usage Example](#usage-example)
- [Use Cases](#use-cases)