--- title: useHead() description: API reference for the useHead composable. --- The `useHead()`{lang="ts"} composable is for managing the document head. It provides a type-safe, reactive API to define, update, and remove head elements like title, meta tags, scripts, and more. It's the core composable used across all frameworks in the Unhead ecosystem. ```ts import { useHead } from '@unhead/dynamic-import' const entry = useHead({ title: 'My Page', }) // update entry.patch({ title: 'new Title' }) // remove entry.dispose() ``` ### How It Works The composable works by queuing your input to be resolved when the head is rendered: 1. It registers your head configuration in a queue 2. When the document head is being rendered (client-side or during SSR), all queued entries are: - Resolved (including any functions, promises or reactive values) - Deduplicated (removing redundant tags) - see [Handling Duplicates](/guides/handling-duplicates) - Sorted (based on tag priority) - see [Tag Positions](/guides/positions) - Merged when appropriate 3. The resolved tags are then rendered to the document head This queue-based approach enables powerful features like deduplication, async resolution, and priority-based rendering while maintaining optimal performance. ::note You won't know the final state of the head until the rendering is complete. :: ### Reactivity Model `useHead()`{lang="ts"} provides reactivity through two main mechanisms: 1. **Framework Integration**: When used with frameworks it automatically integrates with the framework's reactivity system 2. **Manual API**: The returned `ActiveHeadEntry` object with `patch()` and `dispose()` methods lets you manually update or remove head entries ## API Reference ```ts function useHead(input: UseHeadInput, options?: HeadEntryOptions): ActiveHeadEntry ``` ### Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `input` | `Head` | Yes | The head configuration object | | `options` | `HeadEntryOptions` | No | Configuration options for the head entry | ### Returns ```ts interface ActiveHeadEntry { /** * Update the head entry with new values */ patch: (input: Partial<UseHeadInput>) => void /** * Remove the head entry */ dispose: () => void } ``` ## Input Schema The input object accepts the following properties: ```ts interface Head<E extends MergeHead = SchemaAugmentations> { // Document title title?: string | Promise<string> // Title template (function or string with %s placeholder) titleTemplate?: string | null | ((title?: string) => string | null) // Template parameters for dynamic replacements templateParams?: { separator?: string } & Record<string, string | Record<string, string>> // HTML tag collections base?: Base<E['base']> link?: Link<E['link']>[] meta?: Meta<E['meta']>[] style?: (Style<E['style']> | string)[] script?: (Script<E['script']> | string)[] noscript?: (Noscript<E['noscript']> | string)[] // Element attributes htmlAttrs?: HtmlAttributes<E['htmlAttrs']> bodyAttrs?: BodyAttributes<E['bodyAttrs']> } ``` The input is deeply resolved allowing you to provide any value as a function. This can be useful for lazily resolving values when the head tags are being rendered. ::tip Lazy resolving values can improve performance for complex or computed values that aren't needed until the head is actually rendered. :: ```ts import { useHead } from '@unhead/dynamic-import' const title = useMyTitle() useHead({ // just works title: () => 'Dynamic Title', meta: [ () => ({ name: 'description', content: () => `Description for ${title.value}` }), ] }) ``` ## Options The `options` parameter allows you to configure the behavior of the head entry: ```ts export interface HeadEntryOptions { // Whether to process template parameters in the input // - Requires the TemplateParams plugin processTemplateParams?: boolean // Priority of tags for determining render order tagPriority?: number | 'critical' | 'high' | 'low' | `before:${string}` | `after:${string}` // Where to position tags in the document tagPosition?: 'head' | 'bodyClose' | 'bodyOpen' // Custom head instance head?: Unhead } ``` Setting any of these will apply that rule to all tags within the entry. For example if we want to push several meta tags with low priority, we can do: ::tip Learn more about using [Tag Priorities](/guides/positions) and [Template Parameters](/plugins/template-params) in their dedicated guides. :: ```ts import { useHead } from '@unhead/dynamic-import' useHead({ meta: [ { name: 'description', content: 'fallback description' }, { name: 'author', content: 'fallback author' } ] }, { tagPriority: 'low' }) ``` ::note The `tagPriority`{lang="ts"} option is particularly useful for controlling render order when you have multiple head entries that might contain similar tags. :: ## Reactivity ::VueOnly ### Automatic Reactivity The `useHead()`{lang="ts"} composable automatically integrates with your framework's reactivity system: ```ts // Vue example with reactive data import { useHead } from '@unhead/dynamic-import' import { computed, ref } from 'vue' const title = ref('Dynamic Title') useHead({ title, meta: [ { name: 'description', content: computed(() => `Description for ${title.value}`) } ] }) ``` Framework integrations like Vue automatically: - Track reactive data changes with `watchEffect` - Resolve refs, computed props, and reactive objects - Clean up head entries on component unmount - Handle special cases like keep-alive components :: ### Manual Control For more granular control, you can use the returned API: ```ts import { useHead } from '@unhead/dynamic-import' // Create the head entry const headControl = useHead({ title: 'Initial Title' }) // Later update specific fields headControl.patch({ title: 'Updated Title', meta: [ { name: 'description', content: 'New description' } ] }) // Remove the entry entirely when needed headControl.dispose() ``` **Use cases for manual control:** - Updating head after asynchronous data loading - Conditional changes based on user interactions - Managing head from global state - Creating temporary modifications For framework-specific reactivity details, see the guides for each specific framework. ## Security Considerations ::warning The `useHead()`{lang="ts"} function applies minimal sanitization to improve developer experience. **Do not** use this function with untrusted or third-party input. It cannot guarantee safety when handling unknown content. :: For XSS protection, either: 1. Sanitize your input before passing it to `useHead()`{lang="ts"} 2. Use the safer alternatives: - [useSeoMeta()](/docs/head/api/composables/use-seo-meta) for SEO metadata - [useHeadSafe()](/docs/head/api/composables/use-head-safe) for general head management ## Advanced Examples ### Title Template ```ts import { useHead } from '@unhead/dynamic-import' useHead({ titleTemplate: title => `${title} - My Site`, title: 'Home Page' }) // Results in: "Home Page - My Site" ``` For more details on title templates, see the [Titles guide](/guides/titles). ### Combining Multiple Head Entries ```ts import { useHead } from '@unhead/dynamic-import' // Global site defaults useHead({ titleTemplate: '%s | My Website', meta: [ { name: 'og:site_name', content: 'My Website' } ] }) // Page-specific entries (will be merged with globals) useHead({ title: 'Product Page', meta: [ { name: 'description', content: 'This product is amazing' } ] }) ``` ::tip This pattern is commonly used to implement layouts with defaults and page-specific overrides. :: ### Async Data Loading ```ts import { useHead } from '@unhead/dynamic-import' import { computed, ref } from 'vue' // Initial setup const data = ref(null) const loading = ref(true) const error = ref(null) const headControl = useHead({ title: computed(() => data.value ? `${data.value.name} - Product` : loading.value ? 'Loading...' : 'Product Not Found') }) // Fetch data and update head async function fetchProduct(id) { try { loading.value = true data.value = await api.getProduct(id) } catch (err) { error.value = err } finally { loading.value = false } } ``` ::note This pattern works well with data fetching libraries and state management solutions. :: ### Priority-Based Tag Ordering ```ts import { useHead } from '@unhead/dynamic-import' // Critical meta tags (early in <head>) useHead({ meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' } ] }, { tagPriority: 'critical' }) // Default priority tags (middle of <head>) useHead({ meta: [ { name: 'description', content: 'My website description' } ] }) // Low priority tags (end of <head>) useHead({ meta: [ { name: 'author', content: 'Jane Doe' } ] }, { tagPriority: 'low' }) ``` ## Common Use Cases Here are some common use cases for `useHead()`{lang="ts"}: - Setting page-specific metadata for SEO (consider using [useSeoMeta()](/docs/head/api/composables/use-seo-meta) for a more convenient API) - Managing document title and favicon (see [Titles guide](/guides/titles)) - Adding external scripts and stylesheets (consider using [useScript()](/docs/head/api/composables/use-script) for scripts) - Setting Open Graph and Twitter card tags For ready-to-use implementations of common patterns, see our [Starter Recipes](/guides/starter-recipes).