Latest Tweets404 Fix: Block Nuisance Requests for Non-Existent Files: perishablepress.com/block-nuis…
Perishable Press

htaccess Combo Pack: WordPress Permalinks and non-www Redirect

WordPress users employing permalinks via htaccess to optimize their dynamic URLs transform complicated-looking links such as:

http://example.com/blog/index.php?page=33

..into search-engine friendly links such as:

http://example.com/blog/post-title/

Every rewritten URL relies on a common set of htaccess rules to transform the links. The htaccess rules for all WordPress permalinks look like this for root WP installations:

# BEGIN WordPress
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</ifmodule>
# END WordPress

..and like this for subdirectory WP installations:

# BEGIN WordPress
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /subdirectory/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /subdirectory/index.php [L]
</ifmodule>
# END WordPress

Unfortunately, although this default htaccess code affects all WordPress-generated URLs, it does not take into consideration the basic canonicalization issue of the infamous www prefix.

As visitors navigate through your WordPress-powered site, each and every page is accessible via at least two (and probably several more) distinctly different URL addresses: one with the www prefix and one without.

This of course presents duplicate content issues that tend to lower the ranking effectiveness of your pages. Fortunately, it is relatively easy to eliminate duplicate content generated via identical www and non-www content.

Given the previously defined, default WordPress htaccess rules for permalinks, simply insert the following code after the line RewriteEngine On:

RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
RewriteRule ^(.*)$ http://domain.tld/$1 [R=301,L]

So, to clarify, let’s say your WordPress installation is located in the root html directory of your domain. In this case, replace the default permalink htaccess code with this:

WordPress installed in site root

# BEGIN WordPress
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
RewriteRule ^(.*)$ http://domain.tld/$1 [R=301,L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</ifmodule>
# END WordPress

Now, all visitors will be directed to the non-www version of the permalink URL for your pages. Similarly, when your blog is installed in a subdirectory of the html root, replace the default code with this:

WordPress installed in subdirectory

# BEGIN WordPress
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
RewriteRule ^(.*)$ http://domain.tld/subdirectory/$1 [R=301,L]
RewriteBase /subdirectory/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /subdirectory/index.php [L]
</ifmodule>
# END WordPress

This code will ensure that all pages within the subdirectory are served with non-www permalinks. To rewrite all pages above the subdirectory level, such as pages located “above” the blog in the root html directory, add a copy of the following code to your site’s root htaccess file:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
RewriteRule ^(.*)$ http://domain.tld/$1 [R=301,L]

One final note: if you would rather employ the www-versions of your site’s pages as the official canonicalized URLs, replace these two lines:

RewriteCond %{HTTP_HOST} ^www\.domain\.tld$ [NC]
RewriteRule ^(.*)$ http://domain.tld/$1 [R=301,L]

..with these:

RewriteCond %{HTTP_HOST} ^domain\.tld$ [NC]
RewriteRule ^(.*)$ http://www.domain.tld/$1 [R=301,L]

And that should do it. With our new and improved WordPress permalink rules, we eliminate duplicate content, serve search-engine friendly permalinks, and thus preserve more link equity and SEO value for our pages. Nice! ;)

Jeff Starr
About the Author Jeff Starr = Web Developer. Security Specialist. WordPress Buff.
Archives
34 responses
  1. Jeff Starr

    @Jessica Bosari: Good question — this is the first that I’ve heard about it not working. Have you tested on a clean install of WordPress?

    @Rudy: Awesome! Great to hear it. Thanks for following up with your solution.

  2. hi, thanks for your great post. I wanted to make my wordpress blog adress working from http://www.domain.org to domain.org I set an appropriate options in the admin area and it works on the main page. But when to use

    www.domain.org/2010/04/21/post-name-here

    instead of

    domain.org/2010/04/21/post-name-here instead it’s not working.

    There is a problem with / – when I manualy put the adress

    www.domain.org/2010/04/21/post-name-here

    instead of

    domain.org/2010/04/21/post-name-here in the browser,

    I get

    domain.org2010/04/21/post-name-here in the browser

    my .httaccess

    # BEGIN WordPress
    RewriteEngine On
    # Redirect www to non-www
    RewriteCond %{HTTP_HOST} ^www\.(.*)
    RewriteRule (.*) http://%1/$1 [R=301,L]
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
    # END WordPress

    I have tried to use your solution, but it’s not working here. I use WP 2.9.2. Thanks for help!

  3. Jeff Starr

    @mw: unless I am missing something, there is no reason you need to use any htaccess at all for canonicalization. Just enter the desired URLs in the General Settings in the Admin and WordPress will handle the rest.

  4. Well one would help her,

    My website: http://www.dotamania.com.br

    sum subdirectory I created and installed wordpress on it for me to use separate from buddypress: http://dotamania.com.br/clan/

    but only that the permalinks are not working on the 2nd installation generating a 404 and from buddypress work, permalinks has to be enabled …

    be able to help me there, thx!

  5. Sumber Skripsi October 12, 2011 @ 6:08 am

    Hello,can you post about how to change default post wordpress (-) to (+) ?

    example :

    http://www.domain.com/post/google-panda
    to
    http://www.domain.com/post/google+panda

  6. Hey Jeff,

    Will this work as a generic redirect (so that you don’t have to keep putting in the domainname.com for each and every site you set up). Note: the “subdirectory” is the subdirectory folder of the WordPress installation… Thanks for reviewing this code…

    # BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteRule ^(.*)$ http://%1/$1 [R=301,L] RewriteBase /subdirectory/ RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /subdirectory/index.php [L] </IfModule> # END WordPress

    Does this look alright? Could anything be better, cleaner?

    • Jeff Starr

      Yes that looks awesome, but keep in mind that WordPress automatically handles www-canonicalization based on the URL used for the site address in the General Settings. Even so, the technique itself looks pretty clean :)

  7. Haha, so basically what I did above is not needed? LOL… Cool.

[ Comments are closed for this post ]