This post isn’t about why you should have a canonical URL, but about how best to implement one.

Let’s start with a simple example. You own example.com and you have decided that you want to make www.example.com your canonical URL. One valid approach to do this would be to add a RewriteRule to your .htaccess file testing the incoming request’s host name and if it is example.com, then redirect to www.example.com. This works, but it is not the best way to do it.

A better approach is to reverse the RewriteRule’s logic. Instead of testing for a specific host name you want to redirect, test that the incoming request’s host name is NOT your canonical URL. If you only have one domain, you may not see the benefit to this approach, but let’s say you have example.com, example.net and example.org and you want them to ALL funnel to the canonical www.example.com. With the first approach, you’d be writing 5 rules. With the second approach, you still only need the one rule. Even better, if you continue to buy additional domains, you don’t have to remember to alter your rewrite rules to keep up with your domain addiction.

Enough theory, let’s look at the specific rules you can use in your .htaccess file:

RewriteCond "%{HTTP_HOST}" "!^www.example.com" [NC]
RewriteRule "(.*)" "http://www.example.com/$1" [R=301]

First, I assume you already have RewriteEngine on in your Apache configuration or .htaccess file.

The RewriteCond line is testing the incoming request and evaluating the host header to see what domain the user is requesting. Note the ! at the front of the rule. This means we will redirect if the incoming host header is NOT www.example.com. The [NC] flag just means that we don’t care if any capitalization is used. It will evaluate true whether it is Example.com or EXAMPLE.com.

The RewriteRule simply does a permanent redirect to our canonical URL, preserving the page name in the process.

Depending on your server configuration, you may also want to test SERVER_NAME. In practice on our server, I find this is not necessary, but your mileage may vary. If you’re curious, check out this explanation of the difference between HTTP_HOST and SERVER_NAME on Stack Overflow.

If you’re really curious, you can dig in to the Apache documents on mod_rewrite and learn more than you ever wanted to know on the topic.