Migrating to XM Cloud, we’ll be creating new sites with new pages and new URLs.
In Sitecore XM / XP redirects were handled in Sitecore’s Http request pipelines, a web.config file (ugh) or at an infrastructure point in-front of Sitecore. Now where and how we deal with redirects are quite different. We’ll look at a few ways:
This is the classic scenario. A content author can add a redirect item in the tree or use fields in existing page items to have them behave as a redirect. This is used when a page has been moved or deleted but we still want the previous URL to still work.
Below is a screenshot of the fields being referenced in this example.
This is a custom solution but fields like these are typically used in any redirect solution.
We will need to customize the /src/pages/[[...path]].tsx
file to implement this redirect solution.
Scroll down to you getStaticProps
function. Here is a sample of the code.
export const getStaticProps: GetStaticProps = async (context) => {
const props = await sitecorePagePropsFactory.create(context);
// Free code starts here (DC)
const redirectItem: PageRedirect = props.layoutData?.sitecore?.route;
// Simplify redirect condition checks
const isRedirectEnabled = redirectItem?.fields?.['Redirect Enabled']?.value;
const redirectUrl = redirectItem?.fields?.['Redirect Url']?.value?.href;
// Proceed with redirect if enabled and URL is available
if (isRedirectEnabled && redirectUrl) {
return {
redirect: {
destination: redirectUrl,
// Ensure boolean for permanent redirect, default to false if not specified
permanent: redirectItem?.fields?.['Permanent Redirect']?.value,
},
props: {},
};
}
// Free code ends here (DC)
// Rest of the pre-existing function code goes here
return {...};
}
type PageRedirect = null | {
fields?: {
'Redirect Enabled'?: {
value: boolean;
};
'Redirect Url'?: {
value: {
href: string;
};
};
'Permanent Redirect'?: {
value: boolean;
};
};
};
Let’s break down these changes
route
which contains page-level fields into a PageRedirect
object
If you’re curious about this approach, please look into the getStaticProps
documentation and see
what else you can do.
To configure dynamic redirects, find your next.config.js
file. In my file I have a
nextConfig
object that is exported. We need to find (or newly define) a redirects
function.
const nextConfig = {
// other stuff
async redirect() { return []; } // <- this guy
// other stuff
};
Now that we’re oriented here is a working sample of a dynamic redirect.
const nextConfig = {
// other stuff
async redirects() {
return [
{
source: '/blog/:slug',
destination: '/insights/:slug', // Matched parameters can be used in the destination
permanent: true,
},
{
source: '/page-a',
destination: '/new-page-a', // Matched parameters can be used in the destination
permanent: true,
},
{
source: '/page-b',
destination: '/new-page-b', // Matched parameters can be used in the destination
permanent: true,
},
]
},
// other stuff
};
You can find further documentation on redirects to see everything you can do. There are some very advanced features that you can leverage.
If you have a large number of redirects this is the best place in the XM Cloud stack to define them. Create a JSON
file, import it into next.config.js
and add them to the array.
Under your site in XM Cloud you can insert a Redirect Map
item underneath the
{Site}/Settings/Redirects
item. See a screen below of what this looks like.
This gives you with the ability to:
Sitecore’s code that runs the redirect can be found on Github and is definitely worth looking at when you’re trying to understand how it works.
Let’s take a peek at the all important getExistsRedirect
function (as written at the time of this
article):
private async getExistsRedirect(
req: NextRequest,
siteName: string
): Promise<RedirectInfo | undefined> {
const redirects = await this.redirectsService.fetchRedirects(siteName);
return redirects.length
? redirects.find((redirect: RedirectInfo) => {
const pattern = `/^/${redirect.pattern
.toLowerCase()
.replace(/^\/|\/$/g, '')
.replace(/^\^|\$$/g, '')}$/`;
return (
(regexParser(pattern).test(req.nextUrl.pathname.toLowerCase()) ||
regexParser(pattern).test(
`/${req.nextUrl.locale}${req.nextUrl.pathname}`.toLowerCase()
)) &&
(redirect.locale
? redirect.locale.toLowerCase() === req.nextUrl.locale.toLowerCase()
: true)
);
})
: undefined;
}
While it says it supports regular expressions it makes a few modifications to the redirect pattern of the source in Sitecore:
^
and trailing $
if they exist/^...$/
, turning it into a regular expression string that matches the
entire valueA few other things are happening as well:
One last note - and this may have changed - but redirects set in XM Cloud are only checked if the URL in the request
is not found. So if you have a redirect for /blog
but also have an item published for
/blog
the redirect will not fire.
Thanks for reading. A lot has changed in handling redirects from MVC Sitecore XP to XM Cloud. Hopefully this post has given you an idea of the different approaches available. These approaches will also work on Sitecore Headless (SXA + JSS) if you’re not using XM Cloud.
Thanks for reading.