How to Fix Next.js Router Query String in Sitecore JSS
Remove that annoying _site that is appended to your Sitecore URLs.
Start typing to search...
Next/Router is a primary hook within Next.js. This hook is pretty close to mandatory when you want to neatly manage your URLs. This is especially prevalent when you are trying to update or obtain a query string from your URLs! However, once you attempt to update your URLs with Next/Router while working with Sitecore, you're going to come across a couple of issues, mainly: _site being included in your dynamically pushed & replaced URLs.
The main use case that I see this issue appear in is managing forms. If you want to include a query string to navigate a user between the different steps of a complex multi-page form, any code that is used to update the query string will have this issue.
Any code that is trying to preserve a query string, or reuse a value from router, may potentially have issues.
This code:
router.push({query: {...router.query})
Provides this output:

This is added to your URLs because of how Sitecore parses the url data. It pulls and includes your site name in the url. This is to ensure that the correct data from the correct site is being sent to your user, however is results in the ugly urls we can see in the above screenshot.
The fix for this is actually quite simple, we just need to override and set the url manually each time we update a router value; but this needs to be done without pulling the url data from router. This is actually quite simple, and can be done by utilizing the sitecoreContext value that Sitecore JSS provides us from the useSitecoreContext() hook.
sitecoreContext.itemPath provides us with the value of the current page, without the _site value! This mean that we can manually set that to the pathname and format it to ensure it's always lowercase.
// Old
router.replace({query: {...router.query})
// New
router.replace(
{
pathname: (sitecoreContext.itemPath as string).toLowerCase(),
query: { stage: '1' },
},
undefined,
{ shallow: true }
);
If you update your code to utilize the incoming value from sitecoreContext, then your urls will display correctly without the _site. You can see in the example below that we updated our router.replace with the new pathname. This allows us to easily update the query parameter in the url without the _site being added to the path.
