How to Update Your WordPress Permalinks Without Causing Link Rot

by Rick Beckman on January 18, 2008 · 30 comments

in Journal

If you are changing your permalinks structure differently than what is described below (e.g., going from name-based permalinks back to name and date-based permalinks), there is a WordPress plugin that can take care of you. If all you want to do is change from name and date-based permalinks to name-based permalinks, the method described below should be a bit faster, as the redirect is handled at the server level rather than at the PHP level.

This is a follow-up to my earlier post Seamless Permalink Updating. The problem I faced was that I wanted to change my WordPress permalink settings from being date and name based to something which was simply name based.

Why did I want to do this?

  1. Permalinks would be shorter; removing the date information results in URIs which are eleven characters shorter.
  2. Permalinks would not only be more readable, they would be more meaningful to humans; dates aren’t as important as the content the page itself contains. If presented with a list of permalinks from this site, users should have a good idea of what they’ll get when they click them. There’s no reason to muddy those waters by injecting date information into the mix, diluting the impact of the domain and post slug.
  3. The content part of the permalinks (domain name + post slug) would carry more impact in various search engines, without date information (that may or may not be recognized as dates by search engine algorithms) diluting the value of whatever keywords may be present.
  4. Yes, this is a blog, and yes information is posted chronologically; however, this isn’t a novel, and the material here need not be read in a chronological manner in order to understand it. Having date-based permalinks creates the illusion that the date the material was posted is more important than it really is. Besides, posts are displayed with the date anyway; why give it to the user twice when I’m betting the date included with the post is glanced over by most users.

Great reasons, I think, which should suffice for now. So I wanted to change my permalinks; what did I do about it?

WordPress makes the process ridiculously simple.

  1. Visit the Permalinks page of the administration panel (/wp-admin/options-permalink.php).
  2. Select the button labeled “Custom, specify below.”
  3. In the box labeled “Custom structure,” enter the text /%postname%/
  4. Submit the change via the “Update Permalink Structure »” button.
  5. Visit your site and verify that posts are not being given permalinks in the style example.com/post-name-here/. Beautiful, no?

Like I said, ridiculously easy!

But consider: What happens to all the links out there on the Internet to your blog which make use of the previous style of permalinks? Try it out for yourself; find an old permalink in your browser’s history that still makes use of “Date and name based” permalinks and visit it.

404! You broke the Internet! File not found! It’s the end of the world as you know it!

But don’t worry, you can feel fine about it because I have a solution, provided that you are using Apache as your server environment (chances are, you are) and mod_alias is enabled (I’m unsure how common it is). We’ll be fixing our problem using the RedirectMatch directive of mod_alias.

  1. Download your blog’s primary .htaccess file; most likely, it’ll be in the same directory as your blog’s wp-config.php file.
  2. Open it up, and find WordPress’ permalinks code. If you’ve never edited your .htaccess file before, it will most likely be the only code present. The code looks like this, give or take a line break:

    # BEGIN WordPress
    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
    </IfModule>
    # END WordPress
  3. Before that WordPress code, you’ll want to add one of the following:
    • If your WordPress is installed in your domain’s root directory (e.g., example.com/wp-config.php), add this code, adjusting example.com to your proper domain name:

      RedirectMatch permanent ^/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) http://example.com/$1
    • If your WordPress is installed in a subdirectory of your domain (e.g., example.com/blog/wp-config.php), add this code, adjusting example.com/blog to your proper domain name and directory:

      RedirectMatch permanent /blog/[0-9]{4}/[0-9]{2}/[0-9]{2}/([a-z0-9\-/]+) http://example.com/blog/$1
  4. Save & upload the .htaccess file, and revisit one of your older date-based permalinks. If all went according to plan, you should be seamlessly redirected to your new name-based permalinks.

That’s all there is to it! If anyone can provide a better means, I’m open to it, but I’ve tested this out, and it works exactly as I want it to — posts work, paged posts work, pages work, and so on. I can’t promise this won’t break any WordPress plugins, so be prepared to give up this method (which is as easy as deleting whatever you add to .htaccess and switching your permalink structure back).

For the curious, this is what the code above does, piece by piece:

RedirectMatch
Begins the call to Apache’s mod_alias module.
permanent
Sends the client (i.e., the user, whether human or robot) instruction that this redirect is a permanent redirect and that the old address is invalid and should be from now on replaced with the new.
^/[0-9]{4}
The address which we’re trying to match begins with a four-digit year stamp, so we first look for a slash followed by four numbers.
/[0-9]{2}
The address will next have a two-digit month stamp, so we check for another slash followed by two numbers.
/[0-9]{2}
The address will next have a two-digit day stamp, so we check for yet another slash followed again by two numbers.
/([a-z0-9\-/]*)
The address will then have the post slug, which can consist of a variety of lowercase letters, numbers, and dashes. So we look for any number of those. A post slug may include additional information after it, such as a page number on paged posts, so we include any number of slashes in our search as well. It’s enclosed in parentheses so we can capture that data and use it in the next section.
http://example.com/$1
This is the location of where we want to redirect to. The $1 at the end will be replaced by whatever was matched by the code in parentheses in the previous statement.

Edit: Whoops! Using the above RedirectMatch code prevented viewing of day archives (e.g., /2008/01/01/); swapping the asterisk (*) out for a plus sign (+) resolved the issue and allows day archives to be viewed. The code above has been corrected.

Enhance Your Blog with Thesis

What do you look for in a WordPress theme? Loads of options? Unsurpassed support? A beautiful base style?

Look no further than Thesis, the premier WordPress theme framework from the one and only Chris Pearson.

Rock solid semantics. Bulletproof search engine optimization. Crystal clear typography. And more options than you can shake a stick at. What are you waiting for? Get Thesis today!

2 linkbacks

The Necessities of Life » Monthly Update about the Blog and My Life
August 15, 2008 at 2:46 pm
Leaving the Dates Out of Your URLs [Blogging Tip]
May 26, 2009 at 3:50 pm

28 responses in this conversation. Join in!

1 Jeff_ January 20, 2008 at 11:54 am

Excellent post, Rick.

I am seriously (re-)considering removing the date portion of my permalinks. One of the last (logical) reasons I can think of to avoid this change involves the ability to display posts via year, month, and day views. To what extent are the archive pages working with this method in place? And finally, have you noticed any conflicts with plugins, etc.?

Also, you may be amused to know that in an attempt to solve this mystery, I had discovered the same htaccess technique and even wrote a (remarkably similar) article explaining the implementation process.. I was ready to roll with it, but by the time I had finished my work week and returned to the computer, you had already devised a solution and published an article — doh!

2 Rick Beckman January 20, 2008 at 2:22 pm

Jeff_ — Using the above method, all of the following work:

None of those archive permalinks match the RedirectMatch regex, and so that directive is skipped and the address is parsed by the WordPress-added .htaccess directives.

3 Rick Beckman January 25, 2008 at 11:45 am

Looks like there’s actually a WordPress plugin that allows for redirecting old permalinks to new ones. I added a note at the beginning of the post above with a link to it.

4 Chris January 27, 2008 at 1:05 pm

Ran across this post and thought you might be interested in reading it: http://thuledingles.com/?p=191

5 Rick Beckman January 27, 2008 at 1:17 pm

Chris — Saw that linked to earlier from Weblog Tools Collection. I only read the excerpted quote then, but followed your link and read it in full.

He’s absolutely right when he implies that permalink design is very site specific.

However, it would be interesting to tinker around and see how much pull a permalink has on how Google indexes — for instance, if the above post had a permalink which referenced Britney Spears, Paris Hilton, and so on, how long would it take for traffic to show up looking for that kinda stuff, if at all?

It’d make for an interesting experiment, I think!

6 Chris January 27, 2008 at 4:58 pm

Lol, I’ll leave the tinkering and experimenting to you :-) I had a post and poll about credit cards a while back, and I noticed a big change in amount and type of spam…

7 Rick Beckman January 27, 2008 at 9:10 pm

Oh I’m sure. I might try it a bit further down the road when I’m more confident in the wall of protection in place here against spam!

8 Rick Beckman January 30, 2008 at 5:24 pm

Hehe, just got this in my stats: A referral from search results for britney spears roots rot

9 ryan woodrum March 15, 2008 at 11:37 pm

Great post, worked like a charm for converting my wordpress permalinks from the default ?p=\d+ format to the /%postname%/ format. Thanks!

Latest from ryan woodrum: H&R Block TaxCut bogus “password protection”

10 amy March 24, 2008 at 7:40 pm

We want to thank you for this simple, easy-to-follow instructions on the redirection. We’ve been trying to do this for weeks now and, because of your post, I just fixed it in 2 minutes! We’re bookmarking this!! Thanks so much.

Amy and Jonny – http://www.weareneverfull.com

11 Rick Beckman March 24, 2008 at 7:57 pm

ryan woodrum & amy — I’m glad both of you were able to benefit from this guide! If you have any problems related to permalinks as a result of following any of the above advice, just drop a comment, and I’ll do my best to sort out your issue(s)!

12 James May 19, 2008 at 5:11 pm

Hi, I tried the htaccess rule you suggest, of course I change example.com to my website, but all I get is an error page about server configuration and additional 500 error. My WP installation is in my domain’s root. Any Idea?

Thanks you :-)

13 Rick Beckman May 19, 2008 at 5:30 pm

Could you post the contents of the modified .htaccess you are using? You can paste it onto this site [ http://pastebin.com/ ] and give me the link to the resulting code page.

A Server Configuration problem could be caused by any number of things, unfortunately, but I’ll take a look for ya!

14 James May 19, 2008 at 5:47 pm

That was fast :-)
Right now I set up a cpanel redirect but that’s for a couple of old posts. I haven’t actually change the permalink structure in WP, I just change some posts date and since then I’m seeing few errors caused by visitors coming from search engines.
Anyway, here’s my htaccess http://pastebin.com/d3ad3a557

15 Rick Beckman May 19, 2008 at 6:45 pm

James: Try adding the lines I added — they should be highlighted:
http://pastebin.com/f3d55d0a9

If the server error goes away and the redirecting does not work, then the cause is because Mod_Alias is not configured on your server and a solution using Mod_Rewrite will need to be used.

For more information on Mod_Alias:
http://httpd.apache.org/docs/1.3/mod/mod_alias.html

Jeff over at Perishable Press presents the Mod_Rewrite rules if you want to try them out.

16 Miles August 13, 2008 at 11:33 am

Thank you so much for the information. The plugin that many people use doesn’t work for converting from default pages, but luckily I stumbled upon your solution, and it works perfectly. Thanks again for your helpful article.

17 Alexander - StrategieVincenti August 17, 2008 at 5:28 pm

Hi Rick,

I had the month and name structure for the permalinks of my blog. Recently, due to other problems, I deleted the whole WP installation and did a new clean one, then I re-imported all my posts and now I’ve set directly the permalink structure to /%postname%/.

So now I’ve the problem that in the old blogs I’ve still internal links with the old “month and name” permalink structure. I thought to fix the problem with your redirection, but it doesn’t work: I get an 404 error.

Take a look at my .htaccess file http://pastebin.com/m15779b1e and please help me to find where I fail.

Thanks in advance & ciao

alexander

18 Rick Beckman August 17, 2008 at 8:49 pm

Alexander – StrategieVincenti: Troubleshooting HTAccess problems is not something at which I’m at all skilled. If my solution above doesn’t work for you, try out this one from a friend of mine. We were both working at solving the problem of shortening permalinks at the same time. I’m pretty sure his solution will work in a wider variety of cases as it uses the same technology as WordPress permalinks. My solution uses a different Apache module than the WordPress rewrite rules do; it may not be present or enabled on all systems.

19 Alexander - StrategieVincenti August 18, 2008 at 7:12 am

Hi Rick,
finally I installed the plugin you mentioned in the post and that fixed my problem.

Thanks & ciao

20 Rick Beckman August 18, 2008 at 4:07 pm
21 Max Forlani August 25, 2008 at 4:17 am

Hi Rick,

very interesting article.

Over the weekend, I actualy did a double change. I switched from a windows based server to the Apache version, to get rid of the stupid index.php

And on top of that, I wanted to get rid of the day in the url, but keep the year and month.

To do all this, I used the tool that you mention and that may have a security breach. So I’m certainly willing to give your suggestion a go, but how would that string look like in my case?

Original url:
http://www.domain.com/index.php/%year%/%monthnum%/%day%/%postname%/

Current URL:
http://www.domain.com/%year%/%monthnum%/%postname%/

Beside the already mentioned plugin, I also use the Objection Redirection plugin (http://www.biggnuts.com/objection-redirection-wordpress-plugin/). I read about this in an article on a Permalink Change by DoshDosh. Does this still make sense if I apply the .htaccess tool?

Kind regards,
Max

22 Michelle September 19, 2008 at 2:18 pm

I just did a hellish move from an extremely outdated Movable Type installation to Wordpress. All I wanted was to redirect my old permalink format:
/blog/archives/123456.php

to my new format:
/blog/archives/123456

I Googled for hours and tried all sorts of redirect rules, and nothing worked until your Redirect Match tip. THANK YOU!

Latest from Michelle: Mouldy Speeches

23 jgoode January 2, 2009 at 6:41 pm

Awesome, exactly what I was looking for. Thank you so much for your fantastically clear information, your help pointing me to this article and your willingness to share additional outside links for further insight. I ended up having to go with the mod-rewrite version, but it works perfectly!

24 bongkersz April 3, 2009 at 12:07 am

Awesome! Thanks a lot dude. You made my day, after searching up and down in the internet, trying few plugins which needs more tweaking works.. this one piece of code save the day!!!!!!!!!!!!!! :D

25 Money Off Shop April 30, 2009 at 3:05 pm

Hi Rick – just wanted to say a HUGE thank you for your clear and concise instructions. They worked a treat when I changed my permalink structure and the search engines love it!

Thanks again – you’re a genius :-)

26 Ari Herzog May 25, 2009 at 9:42 pm

You rock, Rick! But you already knew that, right? :)

I switched around my permalink structure last night–courtesy of http://www.keenerliving.com/leaving-the-dates-out-of-your-urls-blogging-tip/ — but the RedirectMatch line wasn’t working correctly.

After emailing back and forth with Bruce, I had it down to

RedirectMatch 301 /([0-9]+)/([0-9]+)/(.*)$ http://ariwriter.com/$3

That solved the posts, but created a conflict with date-based archive pages and uploaded images in date-based wp-content folders. One link led to another–and I came across this. I now have:

RedirectMatch 301 ^/[0-9]{4}/[0-9]{2}/([a-z0-9\-/]+) http://ariwriter.com/$1 and it works great!

Better to use htaccess than plugins I figure; cleaner!

27 Joel K June 25, 2009 at 1:45 pm

When you say add it BEFORE the wordpress code, do you mean before the line that starts “# BEGIN WordPress” or just after that??

Thanks

28 Rick Beckman June 25, 2009 at 4:46 pm

Before it. :)

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Previous post: “American Pie”: An Intro to Ron Paul

Next post: RickBeckman.org » Kingdom Front