Useful 301 Redirects for SEO using .htaccess

It is well known that 301 Redirects are vital for recovering link equity from URLs that are no longer existing on our current website but were available on a previous version.

This usually occurs when migrating a website from one domain to another or perhaps even updating a website to use a new system or framework where the previous URL structure cannot be effectively replicated.

These changes can result in a sharp rise in the number of 404 responses on our new website as the pages now no longer exist. Typically we wouldn’t want to serve our visitors 404 pages if we can help it – especially if the website has been updated and the page they were supposed to be visiting has simply moved to a new location.

Instead we’d prefer to automatically redirect them to the new URL and preserve a good user experience.

Typically we wouldn’t want to serve our visitors 404 pages if we can help it – especially if the website has been updated and the page they were supposed to be visiting has simply moved to a new location

In terms of SEO and preserving links, using a 301 Redirect to do this is best practice. However depending on the structure of the old URL there may be different ways to achieve this.

The following is a quick guide to using 301 Redirects in a number of ways by using an .htaccess file, the different types of redirect that are available and examples uses for each. We’ll even include a few tips and tricks that can also be beneficial for SEO.

Disclaimer: Caution is always advised when editing .htaccess files on a live domain. Improper editing will result in a 500 error and force the website to go down. Please make all appropriate backups etc before editing.

301 Redirect Entire Domain

Typically if you are re-branding you may wish to transfer your current website to a new domain. If this is the case then you would wish to preserve your current URL structure but replace the domain part of the URL.

Depending on your server setup this may potentially require both domains being accessible. On the old domain (in this case www.mydomain.com) you would place the following in your .htaccess file:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.my-new-domain.com$ [NC] 
RewriteRule ^(.*)$ http://www.my-new-domain.com/$1 [R=301,L]
</IfModule>

With the above code the following URL:

http://www.mydomain.com/my-page.html

Would redirect to:

http://www.my-new-domain.com/my-page.html

In English: If the website I have just landed on is not “www.my-new-domain.com” please redirect anything (.*) I have entered to the end of “www.my-new-domain.com/” and redirect me using the 301 header for search engines [R=301].

Redirect 301 (the simple one)

Rather than redirecting an entire domain, this 301 Redirect – simply named “Redirect 301” is a single-line, single-page redirect.

For example:

# Redirect [CODE] [OLD PATH] [NEW PATH]
Redirect 301 /my-page.html /my-new-page.html

This would redirect the URL:

http://www.mydomain.com/my-page.html

To:

http://www.mydomain.com/my-new-page.html

If you wish to 301 redirect to another domain name you can simply add the domain to the destination URL:

Redirect 301 /my-page.html http://www.my-new-domain.com/my-new-page.html

Note: The 301 part of the above code can be changed to represent any http status code you wish to use e.g. 301, 503 etc.

RedirectMatch 301 (the flexible one)

RedirectMatch 301 is slightly different to “Redirect 301” in that it can take a condition to match against the current URL. It is still a single-line redirect but when used smartly, can redirect multiple URLs with a single line.

For example:

# RedirectMatch [CODE] [OLD PATH WITH REGEX] [NEW PATH]
RedirectMatch 301 /parts/spanner-(.*).html /metal/parts/spanner-$1.html

This would redirect the following URL:

http://www.mydomain.com/parts/spanner-1996.html

To:

http://www.mydomain.com/metal/parts/spanner-1996.html

In fact – because we’ve used a regular expression (.*) to describe the section after “spanner-” and before “.html” we can have anything in this gap and it will be redirected to within the /metal/ folder in it’s current format. This way we can add this one RedirectMatch line to our .htaccess and redirect any number of spanner-X.html pages to their new folder structure.

We could even use this – if we wanted to simplify our new website to a single spanners.html page – to simply Match the value (spanner-X.html) but not use it in the redirect:

# RedirectMatch [CODE] [OLD PATH WITH REGEX] [NEW PATH]
RedirectMatch 301 /parts/spanner-(.*).html /spanner.html

Pretty useful!

RewriteCond & RewriteRules (the beast!)

When complex conditions are required (RewriteCond) we would use the Mod_Rewrite apache module to perform our 301 redirects.

These are pretty much the daddy of all 301 redirects – any of the above should be possible using RewriteCond and RewriteRule. The best resource to learn this module is to visit the official documentation.

Although RewriteRule can be used on it’s own as a single-line redirect (similar to RedirectMatch) it is usually paired with RewriteCond (a check we perform before applying the redirect).

The typical format of this pairing is as follows:

RedirectCond [SERVER_VARIABLE] [CONDITION] [FLAGS]
RedirectRule [PATTERN] [SUBSTITUTION] [FLAGS]

When using the Mod_Rewrite module we should always make sure that we are writing our own rules within nodes. Not only that but we would also add the RewriteEngine On line – just to ensure that Rewrites are actually enabled.

<IfModule mod_rewrite.c>
RewriteEngine On
// our rewrite code here
</IfModule>

There are too many uses for RewriteRule’s to list here but a few favourites of mine are:

– Removing index.php

Within websites pages may exist where the directory index is accessible via the directory (/my-folder/) and also the index file itself for that directory (/my-folder/index.php).

In order to remedy this (and prevent search engines from confusing the two identical pages) the most common method is to remove the index.php from the URL by using the following RewriteRule.

RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ http://www.mydomain.com/$1 [R=301,L]

In English: If my “request” (url) contains anything leading up to an “/index.php” then fetch everything before “index.php” and put it at the end of my URL (minus the index.php).

– Remove Query Strings from a re-written URL

If we wanted to completely remove query strings (?this=that) from our URL when rewriting we can simply perform the following:

RewriteCond %{REQUEST_URI} ^/my-file.php$ [NC]
RewriteRule ^(.*)$ my-new-file.php? [R=301,L]

This would rewrite the following URL:

http://www.mydomain.com/my-file.php?page_id=56

To:

http://www.mydomain.com/my-new-file.php

The important part to notice here is the “?” after our rewrite – that’s it!

– Force HTTPS for a particular area of the website

In this example we have a folder called secure – we first of all check whether we are already HTTPS (secure) if not we’ll perform a rewrite for anything within /secure/.

RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/secure/(.*)$ [NC]
RewriteRule ^(.*)$ https://www.mydomain.com/$1 [R=301,L]

This would result in the URL:

http://www.mydomain.com/secure/my-secure-page.php

To be re-written to:

https://www.mydomain.com/secure/my-secure-page.php

– Stacking RewriteCond’s

Another important fact about RewriteCond is that you can stack them up using the [OR] flag.

RewriteCond %{REQUEST_URI} ^/my-file.php [OR]
RewriteCond %{REQUEST_URI} ^/my-other-file.php [NC]
RewriteRule ^(.*)$ http://localhost:8888/my-awesome-file.php [R=301,L]

In this case checking for either “my-file.php” or “my-other-file.php” to redirect to “my-awesome-file.php”.

Quick Recap

That’s a lot of information above and it can be quite confusing deciding which Rewrite to apply to a particular scenario. Here’s a quick usage-guideline that you can follow:

For your convenience we have a couple of .htaccess files available for Magento and WordPress. These include all of our speed tweaks and other common SEO-related tweaks too!

I hope you found the above helpful – any typo’s or Errata please let me know!