From 07ad84ebed4c67079aebcefe20ac5b304a8f71b4 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Tue, 1 Jul 2025 17:06:57 +0200 Subject: [PATCH 1/2] Added pages list support and multilang support to sitemap.xml --- core/app/sitemap.xml/route.ts | 137 ++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 6 deletions(-) diff --git a/core/app/sitemap.xml/route.ts b/core/app/sitemap.xml/route.ts index 5a385eda7c..e26fbcb9b5 100644 --- a/core/app/sitemap.xml/route.ts +++ b/core/app/sitemap.xml/route.ts @@ -1,16 +1,141 @@ /* eslint-disable check-file/folder-naming-convention */ -/* - * Proxy to the existing BigCommerce sitemap index on the canonical URL - */ import { getChannelIdFromLocale } from '~/channels.config'; import { client } from '~/client'; import { defaultLocale } from '~/i18n/locales'; +import { routing } from '~/i18n/routing'; +import { client as makeswiftClient } from '~/lib/makeswift/client'; -export const GET = async () => { - const sitemapIndex = await client.fetchSitemapIndex(getChannelIdFromLocale(defaultLocale)); +export function replaceSitemapUrls(xml: string, origin: string): string { + return xml + .replace(/(https?:\/\/[^/]+)([^<]*)<\/loc>/g, (_match, _oldOrigin, path) => { + const fixed = `${origin}${path}`; - return new Response(sitemapIndex, { + return `${fixed}`; + }) + .replace(/xmlsitemap\.php/g, 'sitemap.xml'); +} + +export function addHreflangAnnotations(xml: string, origin: string): string { + const { locales } = routing; + + if (!xml.includes('/, + ``, + ); + + const urlPattern = /([\s\S]*?)<\/loc>/g; + + return intlXml.replace(urlPattern, (_, urlContent: string) => { + const urlObj = new URL(urlContent); + const basePath = urlObj.pathname; + + const hreflangLinks = locales + .map((locale) => { + const localePath = locale === defaultLocale ? basePath : `/${locale}${basePath}`; + const localeUrl = `${origin}${localePath}`; + + return ``; + }) + .join('\n'); + + return `${urlContent}\n${hreflangLinks}`; + }); +} + +export function addSitemapNode(xml: string, newLoc: string): string { + const newSitemap = ` + + ${newLoc.replace(/&/g, '&')} + `; + + return xml.replace('', `${newSitemap}\n`); +} + +export async function getIndexSitemap(origin: string): Promise { + const sitemapIndex = replaceSitemapUrls( + await client.fetchSitemapIndex(getChannelIdFromLocale(defaultLocale)), + origin, + ); + + return addSitemapNode(sitemapIndex, `${origin}/sitemap.xml?type=pages`); +} + +const getCanonicalUrl = (): string => { + const storeHash = process.env.BIGCOMMERCE_STORE_HASH ?? ''; + const channelId = getChannelIdFromLocale(defaultLocale); + const graphqlApiDomain = process.env.BIGCOMMERCE_GRAPHQL_API_DOMAIN ?? 'mybigcommerce.com'; + + return `https://store-${storeHash}-${channelId}.${graphqlApiDomain}`; +}; + +export async function getMappedSitemap(origin: string, request: Request): Promise { + const canonicalUrl = getCanonicalUrl(); + const sourceUrl = request.url + .replace(origin, canonicalUrl) + .replace('sitemap.xml', 'xmlsitemap.php'); + + const sourceSitemap = await fetch(sourceUrl); + const sourceSitemapText = await sourceSitemap.text(); + + return addHreflangAnnotations(replaceSitemapUrls(sourceSitemapText, origin), origin); +} + +export async function getPagesSitemap(origin: string): Promise { + const pages = await makeswiftClient.getPages(); + const pageNodes = pages.data.map((page) => { + return ` + ${origin}${page.path} + ${page.updatedAt} + weekly + `; + }); + + return ` +${pageNodes.join('\n')} + `; +} + +export function getSitemap( + origin: string, + type: string | undefined, + request: Request, +): Promise { + switch (type) { + case 'products': + case 'categories': + return getMappedSitemap(origin, request); + + case 'pages': + case 'news': + return getPagesSitemap(origin); + + default: + return getIndexSitemap(origin); + } +} + +export const GET = async (request: Request) => { + const url = new URL(request.url); + const origin = url.origin; + + const type = url.searchParams.get('type'); + + return new Response(await getSitemap(origin, type ?? '', request), { headers: { 'Content-Type': 'application/xml', }, From 50dc4caec1e555055c73e2592535c63a1f281bb7 Mon Sep 17 00:00:00 2001 From: Riccardo Tempesta Date: Tue, 1 Jul 2025 17:14:14 +0200 Subject: [PATCH 2/2] Added changeset --- .changeset/tired-boats-hunt.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tired-boats-hunt.md diff --git a/.changeset/tired-boats-hunt.md b/.changeset/tired-boats-hunt.md new file mode 100644 index 0000000000..63965a3ab6 --- /dev/null +++ b/.changeset/tired-boats-hunt.md @@ -0,0 +1,5 @@ +--- +"@bigcommerce/catalyst-makeswift": patch +--- + +Added Makeswft pages and multilang support to sitemap.xml