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:
- Redirects set in existing page items and content items (custom code)
- Next.js configured dynamic redirects & mass redirects (configuration)
- SXA-based redirects in XM Cloud (content)
Redirects From Existing Sitecore Page Items
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.
Redirect Fields in the Sitecore Item
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.
The Code to Redirect From Sitecore Item
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
- We return the existing
route
which contains page-level fields into aPageRedirect
object - Check the object for the required values
- If our item has the required fields, we return a redirect object for Next.js to process
If you’re curious about this approach, please look into the getStaticProps
documentation and see
what else you can do.
Dynamic Redirects in XM Cloud Using Next.js
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.
Mass Redirects
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.
Redirects Managed in XM Cloud
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:
- Set the type of redirect (301 vs 302)
- Preserve the query string
- Add any amount of URL paths in a key-value structure for direction
- You can organize your redirects into logical groups by item for easy management.
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:
- Removes leading and trailing slashes from the source
- Remove leading
^
and trailing$
if they exist - Encapsulate the pattern within
/^...$/
, turning it into a regular expression string that matches the entire value
A few other things are happening as well:
- It does a GraphQL call to fetch about redirects for your site
- Evaluates only the path for the request against the source pattern URL
- It matches the incoming path against the source pattern with and without the locale
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.
Final Word on Redirects
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.