Hooks
dom:rendered Hook
 On this page 
The dom:rendered hook is called after all tags have been rendered to the DOM. This hook provides access to the rendered elements and is useful for post-rendering operations, measurements, or triggering side effects that depend on the DOM being updated.
Hook Signature
export interface Hook {
  'dom:rendered': (ctx: { renders: DomRenderTagContext[] }) => HookResult
}
Parameters
| Name | Type | Description | 
|---|---|---|
| ctx | Object | Context object containing rendering information | 
| ctx.renders | DomRenderTagContext[] | Array of rendered tag contexts | 
The DomRenderTagContext interface is defined as:
interface DomRenderTagContext {
  id: string
  $el: Element
  shouldRender: boolean
  tag: HeadTag
  entry?: HeadEntry<any>
  markSideEffect: (key: string, fn: () => void) => void
}
Returns
HookResult which is either void or Promise<void>
Usage Example
import { createHead } from '@unhead/vue'
const head = createHead({
  hooks: {
    'dom:rendered': (ctx) => {
      // Log total number of elements rendered
      console.log(`Finished rendering ${ctx.renders.length} tags to the DOM`)
      // Add a class to the document to indicate rendering is complete
      document.documentElement.classList.add('head-rendered')
      // Dispatch an event that other code can listen for
      window.dispatchEvent(new CustomEvent('head-rendered', {
        detail: { count: ctx.renders.length }
      }))
    }
  }
})
Use Cases
Performance Monitoring
Track and report rendering performance:
import { defineHeadPlugin } from '@unhead/vue'
export const performanceMonitorPlugin = defineHeadPlugin({
  hooks: {
    'dom:rendered': (ctx) => {
      // Calculate rendering metrics
      const renderCount = ctx.renders.length
      // Record performance entry
      if (window.performance && window.performance.mark) {
        window.performance.mark('unhead-dom-rendered')
        // Calculate time since navigation start
        const navStart = window.performance.timing.navigationStart
        const renderTime = Date.now() - navStart
        // Log performance data
        console.log(`Head rendering complete: ${renderCount} tags in ${renderTime}ms`)
        // Create a performance measure
        window.performance.measure('unhead-render-time', 'navigationStart', 'unhead-dom-rendered')
      }
      // Report to analytics if available
      if (window.dataLayer) {
        window.dataLayer.push({
          event: 'unhead_rendered',
          unhead_render_count: renderCount
        })
      }
    }
  }
})
Post-rendering Operations
Perform operations that need to happen after all tags are rendered:
import { defineHeadPlugin } from '@unhead/vue'
export const postRenderPlugin = defineHeadPlugin({
  hooks: {
    'dom:rendered': (ctx) => {
      // Find all script tags that were rendered
      const scriptElements = ctx.renders
        .filter(render => render.tag.tag === 'script')
        .map(render => render.$el)
      // Set up monitoring for script completion
      if (scriptElements.length > 0) {
        let loadedCount = 0
        // Track when all scripts have loaded
        const scriptLoadHandler = () => {
          loadedCount++
          if (loadedCount === scriptElements.length) {
            console.log('All head scripts have loaded')
            document.body.classList.add('scripts-ready')
            // Notify application that scripts are ready
            window.dispatchEvent(new CustomEvent('head-scripts-loaded'))
          }
        }
        // Monitor each script
        scriptElements.forEach((script) => {
          if (script.hasAttribute('async') || script.hasAttribute('defer')) {
            script.addEventListener('load', scriptLoadHandler, { once: true })
            script.addEventListener('error', scriptLoadHandler, { once: true })
          }
          else {
            // Synchronous scripts are already loaded at this point
            loadedCount++
          }
        })
        // If all scripts were synchronous, trigger the event now
        if (loadedCount === scriptElements.length) {
          scriptLoadHandler()
        }
      }
    }
  }
})
DOM Cleanup
Clean up old or unused elements after rendering:
import { defineHeadPlugin } from '@unhead/vue'
export const domCleanupPlugin = defineHeadPlugin({
  hooks: {
    'dom:rendered': (ctx) => {
      // Get IDs of all rendered elements
      const renderedIds = new Set(ctx.renders.map(render => render.id))
      // Find elements with data-unhead-id that weren't in this render batch
      const outdatedElements = document.querySelectorAll('[data-unhead-id]')
      Array.from(outdatedElements).forEach((element) => {
        const id = element.getAttribute('data-unhead-id')
        if (id && !renderedIds.has(id)) {
          // This element was from a previous render and is no longer needed
          console.log('Removing outdated head element:', element)
          element.parentNode?.removeChild(element)
        }
      })
      // Clean up any temporary markers
      document.querySelectorAll('[data-unhead-temp]').forEach((el) => {
        el.parentNode?.removeChild(el)
      })
    }
  }
})
 Did this page help you?