Nitro Hooks · Nuxt Sitemap · Nuxt SEO

[NuxtSEO](https://nuxtseo.com/ "Home")

- [Modules](https://nuxtseo.com/docs/nuxt-seo/getting-started/introduction)
- [Tools](https://nuxtseo.com/tools)
- [Pro](https://nuxtseo.com/pro)
- [Learn SEO](https://nuxtseo.com/learn-seo/nuxt) [Releases](https://nuxtseo.com/releases)

[1.4K](https://github.com/harlan-zw/nuxt-seo)

[Nuxt SEO on GitHub](https://github.com/harlan-zw/nuxt-seo)

[User Guides](https://nuxtseo.com/docs/sitemap/getting-started/introduction)

[API](https://nuxtseo.com/docs/sitemap/api/config)

[Releases](https://nuxtseo.com/docs/sitemap/releases/v8)

Sitemap

- [Switch to Sitemap](https://nuxtseo.com/docs/sitemap/getting-started/introduction)
- [Switch to Nuxt SEO](https://nuxtseo.com/docs/nuxt-seo/getting-started/introduction)
- [Switch to Robots](https://nuxtseo.com/docs/robots/getting-started/introduction)
- [Switch to OG Image](https://nuxtseo.com/docs/og-image/getting-started/introduction)
- [Switch to Schema.org](https://nuxtseo.com/docs/schema-org/getting-started/introduction)
- [Switch to Link Checker](https://nuxtseo.com/docs/link-checker/getting-started/introduction)
- [Switch to SEO Utils](https://nuxtseo.com/docs/seo-utils/getting-started/introduction)
- [Switch to Site Config](https://nuxtseo.com/docs/site-config/getting-started/introduction)
- [Switch to Skew Protection](https://nuxtseo.com/docs/skew-protection/getting-started/introduction)
- [Switch to AI Ready](https://nuxtseo.com/docs/ai-ready/getting-started/introduction)

Search…```k`` /`

v8.0.12

- Playgrounds
- [Discord Support](https://discord.com/invite/275MBUBvgP)

### Nuxt API

- [nuxt.config.ts](https://nuxtseo.com/docs/sitemap/api/config)
- [Nuxt Hooks](https://nuxtseo.com/docs/sitemap/api/nuxt-hooks)

### Nitro API

- [Nitro Hooks](https://nuxtseo.com/docs/sitemap/nitro-api/nitro-hooks)

Nitro API

# Nitro Hooks

[Copy for LLMs](https://nuxtseo.com/docs/sitemap/nitro-api/nitro-hooks.md)

Nitro hooks can be added to modify the output of your sitemaps at runtime.

## [`'sitemap:input'`](#sitemapinput)

**Type:** `async (ctx: { event: H3Event; urls: SitemapUrlInput[]; sitemapName: string }) => void | Promise<void>`

Triggers once the raw list of URLs is collected from sources.

This hook is best used for inserting new URLs into the sitemap.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:input', async (ctx) => {
    // SitemapUrlInput is either a string
    ctx.urls.push('/foo')
    // or an object with loc, changefreq, and priority
    ctx.urls.push({
      loc: '/bar',
      changefreq: 'daily',
      priority: 0.8,
    })
  })
})
```

## [`'sitemap:resolved'`](#sitemapresolved)

**Type:** `async (ctx: { event: H3Event; urls: ResolvedSitemapUrl[]; sitemapName: string }) => void | Promise<void>`

Triggered once the final structure of the XML is generated, provides the URLs as objects.

For new URLs it's recommended to use `sitemap:input` instead. Use this hook for modifying entries or removing them.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:resolved', async (ctx) => {
    // single sitemap example - just add the url directly
    ctx.urls.push({
      loc: '/my-secret-url',
      changefreq: 'daily',
      priority: 0.8,
    })
    // multi sitemap example - filter for a sitemap name
    if (ctx.sitemapName === 'posts') {
      ctx.urls.push({
        loc: '/posts/my-post',
        changefreq: 'daily',
        priority: 0.8,
      })
    }
  })
})
```

## [`'sitemap:index-resolved'`](#sitemapindex-resolved)

**Type:** `async (ctx: { event: H3Event; sitemaps: { sitemap: string, lastmod?: string }[]}) => void | Promise<void>`

Triggered once the final structure of the sitemap index is generated, provides the sitemaps as objects.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:index-resolved', async (ctx) => {
    // add a new sitemap to the index
    ctx.sitemaps.push({
      sitemap: 'https://mysite.com/my-sitemap.xml',
      lastmod: new Date().toISOString(),
    })
  })
})
```

## [`'sitemap:output'`](#sitemapoutput)

**Type:** `async (ctx: { event: H3Event; sitemap: string; sitemapName: string }) => void | Promise<void>`

Triggered before the sitemap is sent to the client. It provides the sitemap as a XML string.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:output', async (ctx) => {
    // append a comment credit to the footer of the xml
    ctx.sitemap = \`${ctx.sitemap}\n<!-- Sitemap output test-->\`
  })
})
```

## [`'sitemap:sources'`](#sitemapsources)

**Type:** `async (ctx: { event: H3Event; sitemapName: string; sources: SitemapSourceInput[]}) => void | Promise<void>`

Triggered before resolving sitemap sources. This hook allows you to:

- Add new sources dynamically
- Remove sources
- Modify source configurations including fetch options and headers

This hook runs before sources are resolved, providing full control over the source list.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:sources', async (ctx) => {
    // Add a source that will be fetched
    ctx.sources.push('/api/dynamic-urls')

    // Add a source with fetch options
    ctx.sources.push(['/api/authenticated-urls', { headers: { 'X-Api-Key': 'secret' } }])

    // Add a resolved source with URLs directly (no fetch needed)
    ctx.sources.push({
      context: { name: 'my-custom-source' },
      urls: ['/page-1', '/page-2', { loc: '/page-3', priority: 0.8 }],
    })

    // Modify existing sources to add headers
    ctx.sources = ctx.sources.map((source) => {
      if (typeof source === 'object' && 'fetch' in source && source.fetch) {
        const [url, options = {}] = Array.isArray(source.fetch) ? source.fetch : [source.fetch, {}]

        // Add headers from original request
        const authHeader = ctx.event.node.req.headers.authorization
        if (authHeader) {
          options.headers = options.headers || {}
          options.headers.Authorization = authHeader
        }

        source.fetch = [url, options]
      }
      return source
    })

    // Filter out sources
    ctx.sources = ctx.sources.filter((source) => {
      if (typeof source === 'string')
        return !source.includes('skip-this')
      return true
    })
  })
})
```

## [Recipes](#recipes)

### [Modify Sitemap `xmlns` attribute](#modify-sitemap-xmlns-attribute)

For some search engines, you may need to add a custom `xmlns` attribute to the sitemap. You can do this with a simple search and replace in the `sitemap:output` hook.

server/plugins/sitemap.ts

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:output', async (ctx) => {
    ctx.sitemap = ctx.sitemap.replace('<urlset ', '<urlset xmlns:mobile="http://www.baidu.com/schemas/sitemap-mobile/1/" ')
  })
})
```

### [Modify Video Entries For Host](#modify-video-entries-for-host)

Sometimes you'll want to include the videos from your markup automatically but exclude some of them based on the host.

```
import { defineNitroPlugin } from 'nitropack/runtime'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:resolved', (ctx) => {
    ctx.urls.map((url) => {
      if (url.videos?.length) {
        url.videos = url.videos.filter((video) => {
          if (video.content_loc) {
            const url = new URL(video.content_loc)
            return url.host.startsWith('www.youtube.com')
          }
          return false
        })
      }
      return url
    })
  })
})
```

[Edit this page](https://github.com/nuxt-modules/sitemap/edit/main/docs/content/5.nitro-api/nitro-hooks.md)

[Markdown For LLMs](https://nuxtseo.com/docs/sitemap/nitro-api/nitro-hooks.md)

Did this page help you?

### Related

[Data Sources](https://nuxtseo.com/docs/sitemap/getting-started/data-sources) [Dynamic URL Endpoints](https://nuxtseo.com/docs/sitemap/guides/dynamic-urls) [Multi Sitemaps](https://nuxtseo.com/docs/sitemap/guides/multi-sitemaps)

[Nuxt Hooks Build-time Nuxt hooks provided by @nuxtjs/sitemap.](https://nuxtseo.com/docs/sitemap/api/nuxt-hooks) [v8.0.0 Release notes for v8.0.0 of Nuxt Sitemap.](https://nuxtseo.com/docs/sitemap/releases/v8)

On this page

- ['sitemap:input'](#sitemapinput)
- ['sitemap:resolved'](#sitemapresolved)
- ['sitemap:index-resolved'](#sitemapindex-resolved)
- ['sitemap:output'](#sitemapoutput)
- ['sitemap:sources'](#sitemapsources)
- [Recipes](#recipes)

[GitHub](https://github.com/harlan-zw/nuxt-seo) [ Discord](https://discord.com/invite/275MBUBvgP)

### [NuxtSEO](https://nuxtseo.com/ "Home")

- [Getting Started](https://nuxtseo.com/docs/nuxt-seo/getting-started/introduction)
- [MCP](https://nuxtseo.com/docs/nuxt-seo/guides/mcp)

Modules

- [Robots](https://nuxtseo.com/docs/robots/getting-started/introduction)
- [Sitemap](https://nuxtseo.com/docs/sitemap/getting-started/introduction)
- [OG Image](https://nuxtseo.com/docs/og-image/getting-started/introduction)
- [Schema.org](https://nuxtseo.com/docs/schema-org/getting-started/introduction)
- [Link Checker](https://nuxtseo.com/docs/link-checker/getting-started/introduction)
- [SEO Utils](https://nuxtseo.com/docs/seo-utils/getting-started/introduction)
- [Site Config](https://nuxtseo.com/docs/site-config/getting-started/introduction)
- [Skew Protection](https://nuxtseo.com/docs/skew-protection/getting-started/introduction)
- [AI Ready](https://nuxtseo.com/docs/ai-ready/getting-started/introduction)

### [NuxtSEO Pro](https://nuxtseo.com/pro "Home")

- [Getting Started](https://nuxtseo.com/pro)
- [Dashboard](https://nuxtseo.com/pro/dashboard)
- [Pro MCP](https://nuxtseo.com/docs/nuxt-seo-pro/mcp/installation)

### [Learn SEO](https://nuxtseo.com/learn-seo "Learn SEO")

Nuxt

- [Mastering Meta](https://nuxtseo.com/learn-seo/nuxt/mastering-meta)
- [Controlling Crawlers](https://nuxtseo.com/learn-seo/nuxt/controlling-crawlers)
- [Launch & Listen](https://nuxtseo.com/learn-seo/nuxt/launch-and-listen)
- [Routes & Rendering](https://nuxtseo.com/learn-seo/nuxt/routes-and-rendering)
- [Staying Secure](https://nuxtseo.com/learn-seo/nuxt/routes-and-rendering/security)

Vue

- [Vue SEO Guide](https://nuxtseo.com/learn-seo/vue)
- [Mastering Meta](https://nuxtseo.com/learn-seo/vue/mastering-meta)
- [Controlling Crawlers](https://nuxtseo.com/learn-seo/vue/controlling-crawlers)
- [SPA SEO](https://nuxtseo.com/learn-seo/vue/spa)
- [SSR Frameworks](https://nuxtseo.com/learn-seo/vue/ssr-frameworks)
- [SEO Checklist](https://nuxtseo.com/learn-seo/checklist)
- [Pre-Launch Warmup](https://nuxtseo.com/learn-seo/pre-launch-warmup)
- [Backlinks & Authority](https://nuxtseo.com/learn-seo/backlinks)

### [Tools](https://nuxtseo.com/tools "SEO Tools")

- [Social Share Debugger](https://nuxtseo.com/tools/social-share-debugger)
- [Robots.txt Generator](https://nuxtseo.com/tools/robots-txt-generator)
- [Meta Tag Checker](https://nuxtseo.com/tools/meta-tag-checker)
- [HTML to Markdown](https://nuxtseo.com/tools/html-to-markdown)
- [XML Sitemap Validator](https://nuxtseo.com/tools/xml-sitemap-validator)
- [Schema.org Validator](https://nuxtseo.com/tools/schema-validator)
- [Keyword Idea Generator](https://nuxtseo.com/tools/keyword-generator)
- [Keyword Research](https://nuxtseo.com/tools/keyword-research)
- [SERP Analyzer](https://nuxtseo.com/tools/serp-analyzer)
- [Domain Rankings](https://nuxtseo.com/tools/domain-rankings)

Copyright © 2023-2026 Harlan Wilton - [MIT License](https://github.com/harlan-zw/nuxt-seo/blob/main/license) · [mdream](https://mdream.dev)