How to create sitemaps for dynamic pages

Looking at Wix Corvid API, I had the impression I could use the routers.js file to create a sitemap for my dynamic pages. This is what I did (my dynamic pages have the goals prefix).

import {WixRouterSitemapEntry} from "wix-router";
export function clothes_SiteMap(sitemapRequest) {
	// Creates the sitemaps for the clothes prefix.
	let siteMapEntries = [];
	let fixedPaths = {
		"Women": {
			pageName: "Women clothes",
			title: "Women clothes",
			url: "women",
			changeFrequency: "weekly",
			priority: 0.5
		},
		"Men": {
			pageName: "Men clothes",
			title: "Men clothes",
			url: "men",
			changeFrequency: "weekly",
			priority: 0.5
		}
	}
	for (let key in fixedPaths){
		let entry = new WixRouterSitemapEntry(key);
		entry.pageName = fixedPaths[key].pageName;
		entry.title = fixedPaths[key].title;
		entry.url = "/clothes/" + fixedPaths[key].url;
		entry.changeFrequency = fixedPaths[key].changeFrequency;
		entry.priority = fixedPaths[key].priority;
		siteMapEntries.push(entry);
	}
	return siteMapEntries;
}

But when I visit mywebsite.com/clothes/sitemap.xml, instead of getting the two entries I created using the code above, I only get the standard sitemap.xml file that I would get from mywebsite.com/sitemap.xml. In other words, instead of getting a sitemap.xml with my entries, I got the standard one with all the other entries from my site.
Was anyone able to create sitemaps for your dynamic pages?

I have tried using the afterSitemap hook instead as described here in the documentation, but to no avail. Still not working.

I get it now. The routers.js file is used only by pages that are created using the router feature. It doesn’t apply to dynamic pages.

I almost answered my question myself. I was doing it wrong though. I was trying to create a sitemap using a router type page function for a dynamic page. Since I created the dynamic page first, the router function I was trying to create wasn’t working as I wanted. The solution was simple and the code is almost identical to what I wrote in my question.

The only catch is that instead of creating a router function with the same prefix as the one used by my dynamic pages, I had to create a dummy router page (which I called sitemap ) and then I used its sitemap function to create my custom sitemaps.

To make it even more clear, I have placed below a summarized version of the code I am using to create my own sitemap for my dynamic pages using route pages.

In my case, I had three types of dynamic pages:

  • Two that are in fact static (they only have the connection to the database) and have the following prefixes: /kolekcja/damska and /kolekcja/meska

  • One that is fully dynamic and take the product slug in its url: /kolekcja/{slug}

The hard part here was to create the sitemap for the dynamic pages related to the products, since there is a limit to the amount of products the ‘wix-data’ queries can return (100 products). Hence, for the sitemap function, instead of returning the sitemap list, we need to return a function that will chain multiple promises together to retrieve all products from the database.

Now, although my dynamic pages prefixes is “kolekcja”, I had to create a set of route pages with a different prefix; for that I used the “sitemap” prefix. I am not using any of the actual route pages, hence the page that gets created is a dummy page that I am not using and any request to that prefix is redirected to the main page (you can see that below on the route function).

import { redirect, WixRouterSitemapEntry } from "wix-router";
import wixData from 'wix-data';

export function sitemap_Router(request) {
	// Used to redirect any request to this prefix to the main page.
	return redirect("/");
}

export function sitemap_SiteMap(sitemapRequest) {
	let siteMapEntries = [];
	// Fixed paths
	let fixedPaths = {
		"Damska": {
			pageName: "Kolekcja Damska",
			title: "Kolekcja Damska",
			url: "damska",
			changeFrequency: "monthly",
			priority: 0.5
		},
		"Męska": {
			pageName: "Kolekcja Męska",
			title: "Kolekcja Męska",
			url: "meska",
			changeFrequency: "monthly",
			priority: 0.5
		}
	}
	for (let key in fixedPaths) {
		let entry = new WixRouterSitemapEntry(key);
		entry.pageName = fixedPaths[key].pageName;
		entry.title = fixedPaths[key].title;
		entry.url = "/kolekcja/" + fixedPaths[key].url;
		entry.changeFrequency = fixedPaths[key].changeFrequency;
		entry.priority = fixedPaths[key].priority;
		siteMapEntries.push(entry);
	}
	// Dynamic paths
	let query = wixData.query("Stores/Products").limit(100).include("collections");
	let queryOptions = {
		"suppressAuth": true,
		"suppressHooks": true
	}
	let results = query.find(queryOptions);
	return results.then((products) => {
		return getData(products, siteMapEntries);
	}).catch((error) => {
		console.log(error);
	});
}

function getData(resultsPromise, entries = []) {
	// Function to asynchronously and recursevely retrieve the
	// products from the database.
	let converted = itemsToSitemap(resultsPromise);
	if (converted.length !== 0){
		entries = entries.concat(converted);
	}
	let hasNext = resultsPromise.hasNext();
	if (!hasNext){
		return entries;
	} else {
		let nextPromise = resultsPromise.next();
		return nextPromise.then((products) => {
			return getData(products, entries);
		}).catch((error) => {
			console.log(error);
		});
	}
}

function itemsToSitemap(results) {
	// Converts a product item to a sitemap entry
	return filtered.map((item) => {
		let entry = new WixRouterSitemapEntry(item.slug);
		entry.pageName = "Okulary " + item.name;
		entry.title = "Okulary " + item.name;
		entry.url = "/kolekcja/" + item.slug;
		entry.changeFrequency = "monthly";
		entry.priority = 0.5;
		return entry;
	});
}

Hope it helps others.

Were you ever able to get it to work?