Learn how to handle redirects correctly to avoid losing rankings and help search engines understand the changes you have made on your site.
Websites change structure, delete pages and often move from one domain to another. Handling redirects correctly is crucial in order to avoid losing rankings and help search engines understand the changes you have done.
Redirects have a status code starting with number three (i.e., 3XX). There are 100 different possible status codes but only a few are implemented to carry certain information.
In this guide, we will cover 3XX redirects relevant to SEO.
301: Moved Permanently
This well-known redirect indicates to a client* that the resource was changed to another location and that it should use the new URL for future requests. When search engines see a 301 redirect, they pass the old page’s ranking to the new one.
Before making a change, you need to be careful when deciding to use a 301 redirect. This is because if you change your mind later and decide to remove the 301 redirect, your old URL may not rank anymore.
Even if you swap the redirects, it will not help you get the old page back to its previous ranking position. So the main thing to remember is that there’s no way to undo a 301 redirect.
(*For beginners who may get confused with generic name client is used instead of browser since not only browsers are able to browse URLs but also search engine bots which are not browsers.)
307: Temporary Redirect
In HTTP 1.1, a 301 redirect means the resource is temporarily moved and the client should use the original resource’s URL for future requests.
For SEO, this means the client should follow a redirect but search engines should not update their links in the SERPs to the new, temporary page.
In a 307 redirect, PageRank is not passed from the original resource to the new one – contrary to a 301 redirect.
302: Found
This means that the resource a client is looking for was found on another URL in the HTTP 1.1 version but was temporarily moved in HTTP 1.0.
302 vs. 307
In almost all cases, 302 and 307 redirects will be treated the same. But a 302 status code doesn’t necessarily mean the client must follow a redirect and it is not considered an error if it decides to stay there.
Modern clients will most likely follow the new destination but some old clients may incorrectly stay on the same URL.
Contrary to a 302 status code, the 307 status code guarantees that the request method will not be changed. For instance, the GET request must continue to GET and POST to POST.
With a 302 status code, some old or buggy clients may change the method which may cause unexpected behavior.
For temporary redirects, you can use either 302 or 307 – but I do prefer 307.
For routine redirect tasks, 301 (permanent redirect) and 307 (temporarily redirect) status codes should be used depending on what type of change you are implementing on your website. In both cases, the syntax of redirects doesn’t change.
You may handle redirect via server config files .htaccess on Apache, example.conf file on Nginx, or via plugins if you are using WordPress.
In all instances, they have the same syntax for writing redirect rules. They differ only with commands used in configuration files. For example, redirect on Apache will look like this:
Options +FollowSymlinks RewriteEngine on RedirectMatch 301 ^/oldfolder/ /newfolder/
On Nginx servers, it will look like:
rewrite ^/oldfolder/ /newfolder/ permanent;
The commands used to tell servers status code of redirect and the action command differ. For instance:
- Servers status code of redirect: “301″ vs. “permanent”
- Action command: “RedirectMatch” vs. “rewrite”.
But the syntax of the redirect ( ^/oldfolder/ /newfolder/ ) is the same for both.
On Apache, make sure on your server mod_rewrite and mod_alias modules (which are responsible for handling redirects) are enabled.
Since the most widely spread server types is Apache, here are examples for .htaccess apache files. Make sure that the .htaccess file has these two lines:
Options +FollowSymlinks RewriteEngine on
above the redirect rules and put the rules below them.
To understand the examples below, you may refer to the following table below on RegExp basics.
* | zero or more times |
+ | One or more times |
. | any single character |
? | Zero or one time |
^ | Start of the string |
$ | End of the string |
a|b | OR operadn “|” a or b |
(z) | remembers the match to be used when calling $1 |
Redirect a Single URL
The most common and widely used type of redirect that is used when deleting pages or changing page URLs. For instance, say you changed URL from /old-page/ to /new-page/. The redirect rule would be:
RewriteRule ^old-page(/?|/.*)$ /new-page/ [R=301,L]
OR
RedirectMatch 301 ^/old-page(/?|/.*)$ /new-page/
The only difference between the two methods is that the first one uses Apache mod_rewrite module and the second one uses mod_alias. It can be done using both methods.
Regular expression “^” means URL must start with “/old-page” while (/?|/.*)$ indicates that anything that follows “/old-page/” with slash “/” or without exact match must be redirected to /new-page/.
We could also use (.*) i.e., ^/old-page(.*), but the problem is, if you have another page with a similar URL like /old-page-other/, it will also be redirected when we only want to redirect /old-page/.
The following URLs will match and directed to a new page:
/old-page/ | /new-page/ |
/old-page | /new-page/ |
/old-page/?utm_source=facebook.com | /new-page/?utm_source=facebook.com |
/old-page/child-page/ | /new-page/ |
It will redirect any variation of the page URL to a new one. If we use redirect in the following form:
Redirect 301 /old-page/ /new-page/
…without regular expressions then all URLs that had UTM query string e.g. /old-page?utm_source=facebook.com ( which is common since URLs are used to be shared over social network), it would end up as 404s.
Even /old-page without trailing slash “/” would end up as a 404.
Redirect All Except
Let’s say we have bunch of URLs like /category/old-subcategory-1/, /category/old-subcategory-2/, /category/final-subcategory/ and want to merge all subcategories into /category/final-subcategory/. We need the “all except” rule here.
RewriteCond %{REQUEST_URI} !/category/final-subcategory/ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(category/). /category/final-subcategory/ [R=301,L]
Here, we want to redirect all under /category/ on the third line except if it is /category/final-subcategory/ on the fourth line. We also have “!-f” rule on the second line which means to ignore any file like images, CSS or javascript files.
Otherwise, if we have some assets like “/category/image.jpg” it will be also redirected to “/final-subcategory/” and cause an image break.
Directory Change
In case you did a category restructuring and want to move everything under the old directory to the new one, you can use the rule below.
RewriteRule ^old-directory$ /new-directory/ [R=301,NC,L] RewriteRule ^old-directory/(.*)$ /new-directory/$1 [R=301,NC,L]
I used $1 in the target to tell the server that it should remember everything in the URL that follows /old-directory/ (i.e., /old-directory/subdirectory/) and pass it (i.e., “/subdirectory/” ) onto the destination. As a result, it will be redirected to /new-directory/subdirectory/.
I used two rules: one case with no trailing slash at the end and the other one with a trailing slash.
I could combine them into one rule using (/?|.*)$ RegExp at the end, but it would cause problems and add “//” slash to the end of URL when the requested URL with no trailing slash has a query string (i.e., “/old-directory?utm_source=facebook” would be redirected to “/new-directory//?utm_source=facebook”).
Remove a Word from URL
Let’s say you have 100 URLs on your website with city name “chicago” and want to remove it.
Example, for the URL http://yourwebiste.com/example-chicago-event/, the redirect rule would be:
RewriteRule ^(.*)-chicago-(.*) http://%{SERVER_NAME}/$1-$2 [NC,R=301,L]
If the example URL is in the form http:// yourwebiste.com/example/chicago/event/, then redirect will be:
RewriteRule ^(.*)/chicago/(.*) http://%{SERVER_NAME}/$1/$2 [NC,R=301,L]
Canonicalization
Having canonical URLs is the most important part of SEO.
If it is missing, you might endanger your website with duplicate content issues because search engines treat URLs with “www” and “non-www” versions as different pages with the same content.
Therefore, it is mandatory to make sure you run the website only with one version you choose.
If you want to run your website with “www” version, use this rule:
RewriteCond %{HTTP_HOST} ^yourwebsite\.com [NC] RewriteRule ^(.*)$ http://www.yourwebsite.com/$1 [L,R=301]
For a “non-www” version:
RewriteCond %{HTTP_HOST} ^www\.yourwebsite\.com [NC] RewriteRule ^(.*)$ http://yourwebsite.com/$1 [L,R=301]
Trailing slash is also part of canonicalization since URLs with a slash at the end or without are also treated differently.
RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
This will make sure /example-page is redirected to /example-page/. You may choose to remove the slash instead of adding then you will need the other rule below:
RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)/$ /$1 [L,R=301]
HTTP to HTTPS Redirect
After Google’s initiative to encourage website owners to use SSL, migrating to HTTPS is one of the commonly used redirects that almost every website has.
The rewrite rule below can be used to force HTTPS on every website.
RewriteCond %{HTTP_HOST} ^yourwebsite\.com [NC,OR] RewriteCond %{HTTP_HOST} ^www\.yourwebsite\.com [NC] RewriteRule ^(.*)$ https://www.yourwebsite.com/$1 [L,R=301,NC]
Basically, you can combine www or non-www version redirect into one HTTPS redirect rule using this.
Redirect from Old Domain to New
This is also one of the most used redirects when you decide to do rebranding and you need to change your domain. The rule below redirects old-domain.com to new-domain.com.
RewriteCond %{HTTP_HOST} ^old-domain.com$ [OR] RewriteCond %{HTTP_HOST} ^www.old-domain.com$ RewriteRule (.*)$ http://www.new-domain.com/$1 [R=301,L]
It uses two cases: one with “www” version of URLs and another “non-www” because any page for historical reasons may have incoming links to both versions.
Most site owners use WordPress and may not need to use .htaccess file for redirects but use a plugin instead.
Handling redirects by using plugins may be a little different from what we discussed above and you may need to read their documentation in order to be able to handle RegExp correctly for the specific plugin.
From the existing ones, I would recommend a free plugin called Redirection which has many parameters to control redirect rules and many useful docs.
Redirect Bad Practices
1. Redirecting All 404 Broken URLs to the Home Page
This case often happens when you are lazy to investigate all of your 404 URLs and map them to the appropriate landing page.
According to Google, they are still all treated as 404s.
If you have too many pages like this, you should consider creating beautiful 404 pages and engage users to browse further or find something other than what they were looking for by displaying a search option.
It is strongly recommended by Google that redirected page content should be equivalent to the old page. Otherwise, such redirect may be considered as soft 404 and you will lose the rank of that page.
2. Wrong Mobile Page Specific Redirects
If you have different URLs for desktop and mobile websites (i.e., “yoursite.com” for desktop and “m.yoursite.com” for mobile), you should make sure to redirect users to the appropriate page of the mobile version.
Correct: “yoursite.com/sport/” to “m.yoursite.com/sport/”
Wrong: “yoursite.com/sport/” to “m.yoursite.com”
Also, you have to make sure that if one page is a 404 on desktop, it should also be a 404 on mobile.
If you have no mobile version for a page, you can avoid redirecting to the mobile version and keep them on the desktop page.
3. Using Meta Refresh
It is possible to do redirect using meta refresh tag like the example below:
<meta http-equiv=”refresh” content=”0;url=http://yoursite.com/new-page/” />
If you insert this tag in /old-page/ it will redirect the user immediately to /new-page/. This redirect is not prohibited by Google but they clearly don’t recommend using it.
4. Too Many Redirects
This message displays when you have a wrong regular expression setup and it ends up in an infinite loop.
Usually, this happens when you have a redirect chain.
Let’s say you redirected page1 to page2 a long time ago. Now you might have forgotten that page1 is redirected and decide to redirect page2 to page1 again.
As a result, you will end up with a rule like this:
RewriteRule ^page1 /page2 [R=301,NC,L] RewriteRule ^page2 /page1 [R=301,NC,L]
This will create an infinite loop and produce the error shown above.
Conclusion
When you initiate a permanent redirect it can’t be changed back easily (the word permanent means hard permanent) by removing the redirect.
This is because once Google detects such a redirect, it will pass PageRank to the new page and change the URL in the SERPs to use the new one.
In case you are migrating a big website with tens of thousands of pages from an old domain to a new one or even from HTTP to HTTPS, it is advised to do a 302 temporarily redirect first and make sure all redirect rules work properly and look Google Analytics data to make sure there are no unexpected outcomes (i.e., some syntax error that causes massive 404 pages) then switch 302 redirect to 301 permanent.
In case you did a mistake with the destination of the 301 permanent redirect and want to switch to another URL, it is advised to avoid chaining redirects and to change all links to the new URL.