sitemap.xml file gives search engine crawlers an index of the pages on your site. In a headless Kibo storefront, your front-end application generates the sitemap, not the platform. If you only need to replace the sitemap on a Kibo-hosted storefront, see Upload a Custom Sitemap instead.
This guide shows how to build a sitemap from Kibo’s Storefront Catalog APIs. It uses a sitemap index that links to sub-sitemaps for categories and for batches of products, so it covers the whole catalog even when the catalog holds hundreds of thousands of products.
Sitemap Architecture
A sitemap for a large catalog uses the index format from the Sitemap Protocol:- The root
sitemap.xmlis asitemapindexdocument that lists the URL of every sub-sitemap. - The categories sub-sitemap is a
urlsetdocument with one entry per category page. - Each product batch sub-sitemap is a
urlsetdocument with the product page URLs for one slice of the catalog. Splitting products into batches keeps each sub-sitemap within the protocol’s 50,000 URL and 50 MB limit.
Key APIs
Why Use Random Access Cursors
Paging through search results withstartIndex and pageSize can miss products in a large catalog. When products are added, removed, or reordered between calls, items can be skipped or returned twice.
The Random Access Cursor API returns a set of stable cursor marks in a single call. Each cursor mark covers a fixed slice of the catalog, and you can retrieve each slice independently, in any order or in parallel, without missing products.
When you call the Random Access Cursor API,
pageSize can be up to 2,000. This sets how many products each cursor mark covers. For example, a catalog of 100,000 products with pageSize=2000 returns about 50 cursor marks.Step 1: Generate the Sitemap Index
Call the Random Access Cursor API to get the cursor marks for your catalog. Each cursor mark becomes one product batch sub-sitemap.
Response:
filter that matches nothing returns an empty cursorMarks array. Handle that case rather than publishing an index with no product sitemaps.
Build the sitemap index from the cursor marks:
Step 2: Generate the Category Sub-Sitemap
Call the Category Tree API to get the storefront categories, then build aurlset with one entry per category.
Response (abbreviated):
items holds only the top level of the tree. Subcategories are nested under childrenCategories at every level. Walk the tree recursively; iterating over items alone publishes only your root categories. Skip categories where isDisplayed is false so that hidden categories are not published.content.slug and categoryCode to build each category URL:
/category/{slug}/{categoryCode} here) depends on your storefront’s routes. Adjust it to match your application.
Step 3: Generate the Product Batch Sub-Sitemaps
For each cursor mark from Step 1, call the Search Products API with thecursorMark parameter to get the products in that batch.
Response (abbreviated):
content.seoFriendlyUrl and productCode to build each product URL:
/product/{seoFriendlyUrl}/{productCode} here) depends on your storefront’s routes. seoFriendlyUrl and the category slug are only populated when SEO content has been entered, so fall back to the product or category code rather than publishing undefined in a URL.
Escape every value you insert into the XML. Slugs and SEO URLs are entered by merchandisers and can contain &, <, or quotes, and a single unescaped & makes the whole sitemap invalid.
GraphQL Alternative
If your storefront uses the Kibo GraphQL API, you can implement the same logic with these root query fields:
Use
categoriesTree, not categories, to get the hierarchy in one call.
Get random access cursors:
nextCursorMark as described in Step 3:
childrenCategories at least as deep as your deepest category level, or use the REST categories/tree endpoint, which returns the whole tree in one call.
Next.js Implementation Example
This example uses the Next.js Pages Router withgetServerSideProps to generate the XML on each request.
Shared Helpers: src/lib/sitemap.ts
Sitemap Index: src/pages/sitemap.xml.ts
Category Sub-Sitemap: src/pages/sitemap.xml/categories.ts
Product Batch Sub-Sitemap: src/pages/sitemap.xml/productBatch/[…productBatchId].ts
Verify Coverage
Before you submit the sitemap, confirm that it covers the catalog. Call the search API once withpageSize=1&responseFields=totalCount, and compare totalCount with the total number of loc entries across all product batch sub-sitemaps. The numbers should match. A large shortfall almost always means the nextCursorMark loop is missing or stops early.
Running the same logic as a one-off script against your tenant, for example with the TypeScript SDK, is a quick way to check your catalog data (in particular, whether seoFriendlyUrl and slug are populated) before you build the storefront routes.
robots.txt
Add arobots.txt file to your application’s public directory that points crawlers to the sitemap and excludes pages that should not be indexed:
Disallow rules to match your application’s routes.
Best Practices
Performance
- Cache sitemap responses. Cursor marks and the category tree change infrequently. Cache them at the CDN or in your application for 1 to 24 hours to reduce API calls.
- Generate sub-sitemaps on demand. Build a product batch sub-sitemap only when a crawler requests it, rather than generating every batch in advance.
- Request only the fields you need. Use
responseFieldson search calls to return onlynextCursorMark,productCode, andcontent.seoFriendlyUrl. - Expect about ten calls per batch. With 2,000 products per cursor and 200 per search call, each product batch takes about ten search calls. Limit concurrency if you generate many batches in parallel.
Completeness
- Always use random access cursors to list products.
startIndexandpageSizepaging alone can skip products in an active catalog. - Follow the
nextCursorMarkchain. This is the most common reason a Kibo sitemap silently leaves out most of the catalog. See Step 3. - Walk the full category tree.
categories/treereturns root categories with subcategories nested inchildrenCategories. - Include other page types. Consider sub-sitemaps for content pages, blog posts, and other routes in your storefront.
SEO
- Add
lastmodwhere you can. Use the product or categoryupdateDateto help crawlers decide what to recrawl. - Don’t spend time tuning
changefreqandpriority. Google ignores both.lastmodis the tag that affects recrawling. - Submit the sitemap to Google Search Console and Bing Webmaster Tools after you deploy it.
Multiple Sites
If you run several storefronts on the same tenant, for example for different locales or brands, generate a separate sitemap for each site. Each site has its own category tree and product set, and is bound to a specific catalog within a master catalog. Scope requests to the correct site with a site-specific host or with thex-vol-site, x-vol-catalog, and x-vol-master-catalog headers. A mismatched combination returns 409 Conflict.

