harlan-zw / nuxt-seo

The complete SEO solution for Nuxt.
https://nuxtseo.com
1.03k stars 64 forks source link

Conditionally allow runtime logic to prevent dynamic sitemap creation from defineSitemapEventHandler #237

Closed adamdehaven closed 2 months ago

adamdehaven commented 4 months ago

Clear and concise description of the problem

Using Product routes as an example, I would like to do a check at runtime inside the defineSitemapEventHandler for the Products sitemap if each product is public or private.

  1. If the product route should be public, I add to the sitemap.
  2. If the product route is private, it is excluded from the sitemap.

After parsing all of the product routes, if there are zero product routes added to the array, I would like to prevent the products_sitemap.xml from being created rather than just returning an empty array.

Suggested solution

Ideally, returning an empty array (or undefined) from defineSitemapEventHandler should prevent the sitemap from being created, and in a multiple sitemap app, it should prevent this sitemap from being linked from the sitemap_index.xml

Alternative

Returning an empty array from defineSitemapEventHandler works for not indexing the routes, but you are left with an empty sitemap.

Additional context

I don't want to disable indexing for the whole site, just for individual sitemaps, e.g. the pages sitemap should exist, products sitemap should be empty/not exist if the array of routes is empty, but this cannot be determined until in the event handler at runtime.

harlan-zw commented 4 months ago

I've added a low-level way to solve in v5.2.0, you can use the new sitemap:index-resolved hook to manually modify the output of the index sitemap.

Some pseudo code to guide you:

import { defineNitroPlugin } from 'nitropack/dist/runtime/plugin'

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('sitemap:index-resolved', (ctx) => {
    const products = fetchProductsCached()
    if (!products.length) {
      ctx.sitemaps = ctx.sitemaps.filter(s => s.sitemap.includes('products')
    }
  })
})

Let me know if this doesn't solve the issue and if some other implementation is needed.

adamdehaven commented 3 months ago

I understand the logic; however, I'm not sure this would work.

I generate the sitemap in the defineSitemapEventHandler, so how would I go about determining if the sitemap has any entries in a separate Nitro plugin?

In your example here, I see you have const products = fetchProductsCached() but what would this actually look like in an example implementation where the sitemap is created via defineSitemapEventHandler?

harlan-zw commented 2 months ago

Moving this here https://github.com/nuxt-modules/sitemap/issues/314