Sitemaps
A sitemap provides search engines with information about the pages on your site and their relationships. Search engines like Google read sitemaps to crawl your site more efficiently, helping to improve search engine optimization. By default, search engines look for the sitemap at {your-website}/sitemap.xml
.
Your commercetools Frontend project is pre-configured with sitemap generation that automatically generates the sitemap whenever you build your project using the yarn build
command.
In this article, you'll learn how commercetools Frontend generates the sitemap for all the pages on your website.
Configuring a sitemap
commercetools Frontend uses the next-sitemap package to create sitemaps. The next-sitemap
package generates a sitemap for your Next.js website using the sitemap configuration provided in the next-sitemap.config.js
file.
The next-sitemap.config.js
file provides next-sitemap
with the configuration to build the sitemap using the following options:
Property | Description |
---|---|
siteURL | Your website's origin URL used for creating the full paths. |
exclude | List of relative paths to exclude from the sitemap. |
generateRobotsTxt | If true then the robots.txt file will be generated for web crawlers. |
robotsTxtOptions | List of policies for the robots.txt file, and a list of all sitemaps (see Generating the sitemap). |
alternateRefs | List of language-specific alternative URLs. |
You can provide different values to these configuration options by following the next-sitemap
configuration documentation. For example, if you want to add a new locale to the sitemap, you need to update the languageMapper
object.
/* Website URL */const { languageMapper } = require('./project.config');const siteUrl = process.env.SITE_URL;const alternateRefs = [];for (const [key] of Object.entries(languageMapper)) {alternateRefs.push({href: `${siteUrl}/${key}`,hreflang: key,});}/* Site map generator configuration *//** @type {import('next-sitemap').IConfig} */const config = {siteUrl,exclude: ['/sitemap-static.xml','/sitemap-categories.xml','/sitemap-products.xml','/verify','/__preview',],generateRobotsTxt: true,robotsTxtOptions: {policies: [{userAgent: '*',allow: '/',},{userAgent: '*',disallow: '/api',},{userAgent: '*',disallow: ['/__preview'],},],additionalSitemaps: [`${siteUrl}/sitemap-static.xml`,`${siteUrl}/sitemap-categories.xml`,`${siteUrl}/sitemap-products.xml`,],},alternateRefs: alternateRefs,};module.exports = config;
Generating the sitemap
To generate the sitemaps, we need to fetch the list of all available paths, create a standard sitemap structure by adding necessary fields such as loc
and lastmod
to the sitemap response, and return the response in the XML format.
We use the helper methods from the frontastic
package to get the list of paths and generate 3 sitemaps one for each: static pages, product pages, and category pages for easier maintenance.
Sitemap for static pages
To generate the sitemap for all the static pages created using the Studio, we create a new file, sitemap-static.xml/route.tsx
, in the frontend/app/
directory. In this file, we implement the GET
route handler method of Next.js that returns the sitemap response.
In the following code, we get the static pages structure using the sdk.page.getPages()
method and convert the received data into ISitemapField
structure required by next-sitemap
. Then we pass the sitemap data fields
to the generateSiteMap
method of the next-sitemap
package and return the response.
The generated sitemap is made available on {your-site}/sitemap-static.xml
.
import { SiteMapField, generateSiteMap } from 'helpers/sitemap';import { sdk } from 'sdk';export async function GET() {const locale = 'en';const siteUrl = process.env.SITE_URL;sdk.defaultConfigure(locale);const fields = [] as SiteMapField[];const path = '/';const depth = 1;const res = await sdk.page.getPages({ path, depth });if (res.isError) return new Response(null, { status: 500 });const data = res.data;if (data?.pageFolderStructure) {fields.push(...data.pageFolderStructure?.map((pageFolderStructureValue) => ({loc: `${siteUrl}/${locale}${(pageFolderStructureValue as any)._url}`, //eslint-disable-linelastmod: new Date().toISOString(),changefreq: 'daily' as const,})));}return new Response(generateSiteMap(fields), {status: 200,headers: {'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate','Content-Type': 'application/xml',},});}
Sitemap for products
To generate the sitemap for all product pages created using the Studio, we create a new file sitemap-products.xml/route.tsx
in the frontend/app/
directory. In this file, we implement the GET
route handler method of Next.js that returns the sitemap response.
In the following code, we get a list of all products by calling the extensions.product.query
method and convert the received data into the ISitemapField
structure required by next-sitemap
. Then we pass the sitemap data fields
to the generateSiteMap
method of the next-sitemap
package and return the response.
The generated sitemap is made available on {your-site}/sitemap-products.xml
.
import { Product } from 'shared/types/product/Product';import { SiteMapField, generateSiteMap } from 'helpers/sitemap';import { sdk } from 'sdk';export async function GET() {const locale = 'en';const siteUrl = process.env.SITE_URL;sdk.defaultConfigure(locale);const fields = [] as SiteMapField[];let nextCursor: string | undefined;do {const extensions = sdk.composableCommerce;const response = await extensions.product.query({cursor: nextCursor,limit: 12,});const items = (response.isError ? [] : response.data.items) as Product[];fields.push(...items.map((product) => ({loc: `${siteUrl}/${locale}${product._url}`,lastmod: new Date().toISOString(),changefreq: 'daily' as const,})));nextCursor = !response.isError ? response.data.nextCursor : undefined;} while (nextCursor);return new Response(generateSiteMap(fields), {headers: {'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate','Content-Type': 'application/xml',},});}
Sitemap for categories
To generate the sitemap for all category pages created using the Studio, we create a new file sitemap-categories.xml/route.tsx
in the frontend/app/
directory. In this file, we implement the GET
route handler method of Next.js that returns the sitemap response.
In the following code, we get a list of all categories by calling the extensions.product.queryCategories
method and convert the received data into the ISitemapField
structure required by next-sitemap
. Then we pass the sitemap data fields
to the generateSiteMap
method of the next-sitemap
package and return the response.
The generated sitemap is made available on {your-site}/sitemap-categories.xml
.
import { Category } from 'shared/types/product/Category';import { SiteMapField, generateSiteMap } from 'helpers/sitemap';import { sdk } from 'sdk';export async function GET() {const locale = 'en';const siteUrl = process.env.SITE_URL;sdk.defaultConfigure(locale);const fields = [] as SiteMapField[];let nextCursor: string | undefined;const extensions = sdk.composableCommerce;do {const response = await extensions.product.queryCategories({cursor: nextCursor,limit: 12,});const items = ((response.isError ? [] : response.data.items) ??[]) as Category[];fields.push(...items.map((category) => ({loc: `${siteUrl}/${locale}${category._url}`,lastmod: new Date().toISOString(),changefreq: 'daily' as const,})));nextCursor = (!response.isError && response.data.nextCursor) as string;} while (nextCursor);return new Response(generateSiteMap(fields), {headers: {'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate','Content-Type': 'application/xml',},});}
Final sitemap
Now that we've set up sitemap generation for all our pages, the next-sitemap
package uses the sitemap configuration to generate an sitemap index that lists all the different sitemaps:
{your-site}/sitemap-static.xml
{your-site}/sitemap-products.xml
{your-site}/sitemap-categories.xml
The next-sitemap
package runs as a postbuild
script specified in the frontend/package.json
file and generates the sitemap after the next build
has finished.
After the build, the generated sitemap index is made available on {your-site}/sitemap.xml
. The sitemap index provides the URL to all three sitemaps we created, allowing search engines and web crawlers to index your website.
<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>{your-site}/sitemap-static.xml</loc></sitemap><sitemap><loc>{your-site}/sitemap-categories.xml</loc></sitemap><sitemap><loc>{your-site}/sitemap-products.xml</loc></sitemap></sitemapindex>