Managing Redirects in Sitecore

One of the most important aspects if not the most important aspect to managing a website is SEO. It doesn’t matter how good your website is, it doesn’t really matter if nobody can find it. Creating good SEO is a lot about having pages match what users are searching for, which then results in a high ranking for those pages. However, a second part to this formula is what happens with a page when it no longer exists. For instance, one day this blog post may no longer be relevant to have on our site, but up until that point search engines will have crawled it, people will have posted links to it and all of this adds to its value which we would to lose should it be removed. An even simpler scenario could be that we rename the blog section to something else and the page still exists under a different URL, but links to it no longer work.

Fortunately, the internet has a way of dealing with this and it’s in the form of a 301 redirect. 301 redirect are an instruction to anyone visiting the URL that the page has permanently moved to a different URL. When you set up a 301 redirect it achieves two things. Firstly, users following a link to your site end up on a relevant page rather a generic page not found message. Secondly search engines recrawling your site update their index with the new page and transfer all the associated value. So, to avoid losing any value associated with a page, whenever you move, rename or remove a page you should also set up a redirect.

Sitecore

Given how important redirects are it’s then surprising that an enterprise CMS platform like Sitecore doesn’t come with a universal way to set redirects up out of the box.

Typically, when we’ve taken over a site one of the support requests we will eventually receive is a question surrounding setting up a redirect from a marketer who’s ended up on Sitecore’s documentation site and is confused why they can’t find any of the things in this article https://doc.sitecore.com/users/sxa/17/sitecore-experience-accelerator/en/map-a-url-redirect.html.

The article appears to suggest that creating redirects is a feature that is supported, however it’s only available to sites built using Sitecore Experience Accelerator rather than the traditional approach.

More often that not, the developers who created the site will have added 301 redirect functionalities but will have done it using the IIS Redirect module, which while serves the purpose of creating redirects does not provide a Sitecore interface for doing so.

301 Redirect Module

Fortunately, there are some open source modules available which add the missing feature to Sitecore. The one we typically work with is neatly named 301 Redirect Module.

Once installed the module can be found in the System > Modules folder. Clicking on the Redirects folder will give you the option to either create another Redirect Folder to help group your redirect into more manageable folders, Redirect URL, Redirect Pattern or Redirect Rule.

Redirect URL

This is by far the most common redirect to be set up. You specify an exact URL that is to be redirected and set the destination as either another exact URL or a Sitecore item. There’s even an option to choose if it should be a permanent or temporary redirect.

Redirect Pattern

Redirect patterns are slightly more complex and require some knowledge of being able to write regular expressions. However, these are most useful if you ever want to move an entire section of your site. Rather than creating rules for each of the pages under a particular page, one rule can redirect all of them. Not only does this save time when creating the redirects, but it also makes your list of redirects far more manageable.

Auto Generated Rules

One of my favourite features of the 301 Redirect Module is that it can auto generate rules for any pages you move. For instance, if you decide a sub-page should become a top-level page moving it will result in a rule automatically being generated without you having to do a thing.

Summary

A marketer’s ability to manage 301 Redirect is as important as them being able to edit the content on the site and while traditional Sitecore sites may be missing this functionality it can easily be added using 3rd party modules, best of all they’re free!

Sitecore Alias as Redirect

One feature of Sitecore that I have always disliked is Alias’s. On each page of a site, content editors have the ability to click an alias button on the presentation tab and add alternative urls for the page.

Alias Toolbar

Once added these will appear in the Aliases folder under system.

Alias

However all this accomplishes is multiple URLs existing for one page which is a big SEO no no.

Content editors like to do this in order to create simple URLs for things like landing pages. e.g. himynameistim.com/Sitecore but search engines hate it as they see multiple pages with the exact same content. As a result the value of each page gets lowered and appears lower in search engine results. What Content editors really want is to set up a 301 redirect so that they can have the simple URL but redirect users to the actual page on the site.

Aliases as Redirects

One solution is to updated the aliases functionality to cause a redirect to it’s linked item rather than resolve the page.

To do this we need to create a pipeline processor that inherits from AliasResolver.

using Sitecore;
using Sitecore.Configuration;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;
using System.Net;
using System.Web;
using AliasResolver = Sitecore.Pipelines.HttpRequest.AliasResolver;

namespace HiMyNameIsTim.Pipelines
{
    public class AliasAsRedirectResolver : AliasResolver
    {
		public override void Process(HttpRequestArgs args)
		{
			if (!Settings.AliasesActive)
			{
				return; // if aliases aren't active, we really shouldn't confuse whoever turned them off
			}

			var database = Context.Database;

			if (database == null)
			{
				return; // similarly, if we don't have a database, we probably shouldn't try to do anything
			}

			if (!Context.Database.Aliases.Exists(args.LocalPath))
			{
				return; // alias doesn't exist
			}

			var targetID = Context.Database.Aliases.GetTargetID(args.LocalPath);

			// sanity checks for the item
			if (targetID.IsNull)
			{
				Tracer.Error("An alias for \"" + args.LocalPath + "\" exists, but points to a non-existing item.");
				return;
			}
			var item = args.GetItem(targetID);

			if (database.Aliases.Exists(args.LocalPath) && item != null)
			{
				if (Context.Item == null)
				{
					Context.Item = item;
					Tracer.Info(string.Concat("Using alias for \"", args.LocalPath, "\" which points to \"", item.ID, "\""));
				}

				HttpContext.Current.Response.RedirectLocation = item.Paths.FullPath.ToLower()
					.Replace(Context.Site.StartPath.ToLower(), string.Empty);
				HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
				HttpContext.Current.Response.StatusDescription = "301 Moved Permanently";
				HttpContext.Current.Response.End();
			}
		}
    }
}

And patch in in place of the regular Alias Resolver.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor type="HiMyNameIsTim.Core.Pipelines.AliasAsRedirectResolver, LabSitecore.Core" 
                   patch:instead="*[@type='Sitecore.Pipelines.HttpRequest.AliasResolver, Sitecore.Kernel']"/>
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

The above code is adapted from a solution given by Jordan Robinson but with a bug fixed to stop every valid URL without an alias writing an error to the log file.

Creating 301 redirects in web.config

For various reasons at times you may need to create a 301 redirect to another URL. This could be as a result of a page moving or you just need to create some friendly URLS.

As a developer you may be tempted to do something like this in code…

private void Page_Load(object sender, System.EventArgs e)
{
    Response.Status = "301 Moved Permanently";
    Response.AddHeader("Location","http://www.new-url.com");
}

But do you really want your project cluttered up with files who’s only purpose is to redirect to another page!

You may also be tempted to try doing something with .NET’s RouteCollection. This would certainly solve an issue on creating a redirect for anything without a file extension, but there is a better way.

In your web.config file under the configuration node create something like this

  <location path="twitter">
    <system.webServer>
      <httpRedirect enabled="true" destination="http://twitter.com/TwitterName" httpResponseStatus="Permanent" />
    </system.webServer>
  </location>

The location path specifies that path on your site that this redirect will apply to. The destination value in the httpRedirect is where the redirect will go to. As well as setting Permanent for the httpResponseStatus you can also specify Found or Temporary depending on your needs.