Feb 19 2007

How To Change WordPress Permalink Structure with Permalink Redirect Plugin

It has to be one of the most frequently asked questions here. “I have changed my WordPress Permalink Structure, and now all my internal/external links are broken. My most popular posts have dropped off from the Google SERP completely, and I am loosing thousands of dollars per day! How can I fix them?” Well, maybe not the thousands of dollar part (I am trying to exaggerate as most people do on the Internet), but you get the issues associated with permalink changes. It seems that some people have pointed to my Permalink Redirect plugin as “the solution”, but it is actually not that straight forward. I shall try to look at the problem and the solution in this post.

People change their mind. It might be a mis-configuration in the beginning, or semantic change of the site structure, or just for the sake of trying out something new. The fact is, people do change their permalink structure in WordPress, which introduces many issues after the change. For example,

  • All internal links to older posts are broken. It might be fixable by re-editing these posts with internal links.
  • All external links to older posts are broken. It might not be as easy to change as you do not have control over the sites on the providing side of links.
  • Search engines will start to hate you because of all these broken links. Especially the hard earned ones from trusted sources.

So, how can we change the permalink structure and keep all your links intact?

Solution involves a bit of Apache mod_rewrite and the permalink redirect plugin. The principle is simple.

  1. Use mod_rewrite to convert the old URL into query string URL.
  2. Use Permalink Redirect plugin to redirect the 2nd request to the new permalink.

For example, we are changing from /%year%/%monthnum%/%postname%/ to /%category%/%postname%.html, and a visitor requesting /2007/02/this-is-a-test/ would get:

  1. Initial request: http://wpsite/2007/02/this-is-a-test/
  2. 1st redirect: http://wpsite/?name=this-is-a-test
  3. 2nd redirect: http://wpsite/foo-bar/this-is-a-test.html

Implementation Details

Some assumptions so I don’t need to explain basic concepts:

  • Setting up permalink structure in WordPress.
  • Editing .htaccess file inside your WP installation.
  • Understanding of mod_rewrite rules and regular expression.

First of all, you need to identify the structure tag that uniquely identify each individual post in your old permalink structure. It is either %post_id% or %postname%. Do note that from the database level, wp_posts.post_name does not have to be unique, although WP forces a suffix when post name is not unique (in app, not enforced by DB).

For example, /%year%/%monthnum%/%postname%/ would be the %postname%, and /archives/%post_id%.html would be the %post_id%. The first task would be writing a mod_rewrite rule to capture these structure tags and redirect to default query string URL.

Permalink Structure /%year%/%monthnum%/%postname%/ /archives/%post_id%.html
Redirect To /?name=%postname% /?p=%post_id%
Mod_Rewrite Rule RewriteRule /[0-9]{4}/[0-9]{2}/([^/]+)/? /?name=$1 [R,L] RewriteRule /archives/([0-9]+)\.html /?p=$1 [R,L]

You might wish to test whether your Mod_Rewrite rule is working by going to the old URL. It should then redirect you to the new query-string-based URL. It should also be possible to achieve the same with other web servers like Lighty or Nginx. YMMV.

The next step is easy — just install the Permalink Redirect plugin and activate it. What it does is, whenever a page/post is requested with a different permalink than the one defined in the permalink structure option, it will redirect the request to the canonical permalink. So when the post is loaded with query-string-based URL, it will then redirect the visitor to the new URL based on the new permalink structure.

Conclusion

Sorry I have to apologise for this rough draft on solving the permalink issue. It might make sense to some but not to others as I have left out details such as mod_rewrite syntax, regular expression syntax, etc. The functionality could have been implemented in a plugin and WP has already provided most of the functionalities (in wp-include/rewrite.php), however I do not see burdening WP for things Apache mod_rewrite could do very quickly a good solution.

Again, your mileage may vary. It’s also a good idea to come up with a suitable permalink structure right from the beginning to avoid all this mess :)

39 Comments

  1. Pingback: SDAC Inc: SDAC Recommends: WordPress Plugin: Permalink Redirect Plugin

  2. Mega Millions on 23 Jul 2007 at 10:08 pm #

    Hey,

    Try the permalinks migration plugin. You don’t need to use mod rewrite to get that working.

    Here’s my experience with changing wordpress permalinks

  3. Pingback: Get multiple DMOZ links and use Wordpress to do it | Needless Productions

  4. Enrique Bergemann on 8 Sep 2007 at 5:00 pm #

    Dear Scott,

    just two little words for a great (permalink-)solution: Thank You!

    Enrique

  5. Ryan on 1 Dec 2007 at 8:27 am #

    “… Try the permalinks migration plugin. You don’t need to use mod rewrite to get that working.”

    Ironically, the link you provided gives a 404!

  6. Malaiac on 5 Feb 2008 at 6:35 am #

    Just FYI, the actuel wp_redirect of WP 2.3.2 is bugged
    Function is
    function wp_redirect($location) {…}
    I had to manually add a 301 header to get things right
    file is /wp-includes/pluggable-functions.php, around line 248

    your plugin is not involved, nice work btw ;)

  7. Dunn on 26 Mar 2008 at 6:39 pm #

    I use your plugin to redirect from my old permalink /%year%/%monthnum%/%postname%.html to the new one without .html /%year%/%monthnum%/%postname% but it’s not working. Any suggestion?

  8. patoune on 5 Apr 2008 at 10:15 am #

    I have problem to redirect from my old permalink with .htm

    Only old permalink with .htm does not work.
    Any idea?

  9. John-Henrique on 24 Apr 2008 at 7:56 am #

    I have a problem with permalink migration on wordpress

    I always used permalink struture /%postname%/ but I have to use /%category%/%postname%
    Its works correctly, but, users from Google Search seem page not found (error 404) How to avoid it?

    Falopa!

  10. rohit on 11 Jun 2008 at 1:54 am #

    I guess to make permalink structure change work, you need to have mod_rewrite php function enabled on your server. My website (rohitblog.com) is hosted on Windows/ PHP/ WordPress- where mod_rewrite is not enabled. Any solution? thanks in advance.

  11. Richard on 13 Jun 2008 at 1:13 pm #

    Scott, I really like the article and the clear explanation of the situations that arise. I am currently changing my permalink structure (i was using a windows host that required an “index.php” but now I am not) and find this info very helpful.

    I am going to try to do this tonight…hope it works :)

    Thanks for the article,
    Richard

  12. Abhinav Sood on 14 Aug 2008 at 7:32 am #

    I am on a Windows IIS based server but I somehow managed to set up Pretty Permalinks over the default ugly permalinks that I have been using for quite some time now!

    I am using your plugin to 301 redirect my old links to new links, but I am facing a weird problem.

    My homepage keeps on refreshing in a loop, automatically?

    Can you please help me with it, as its increasing my bill for the excessive bandwidth consumption!

    If you can reply by email, that would be great…

    Regards,
    Abhinav Sood.

  13. graphic art on 3 Sep 2008 at 5:17 pm #

    I tried using it but I got a 404 error/page not found.

    I used the /%postname%/ sa the new permalink from the default permalink in wordpress. Im hosting my wordpress with godaddy and I dont have access to my .htaccess

  14. Pingback: 关于Wordpress重定向及相关插件 | Riku

  15. Rob on 23 Nov 2008 at 5:33 am #

    I’m trying to go from from /archives/%post_id% to /%year%/%monthnum%/%postname%/

    I get a redirect to this instead: /%year%/%monthnum%/%postname%/%post_id%

    So, the redirect has both postname and id, is there any way around this?

  16. rarali on 18 Dec 2008 at 1:14 am #

    Hi, I´m having the same problem Abhinav Sood, the index page just loops in refresh. the other sites work fine. Do you have any suggestions to this? I´m desperate, can´t find a solution to this!

  17. Daniel Molano on 4 Mar 2009 at 3:31 am #

    This is a wonderful plugin, it works almost flawlessly, EXCEPT:

    The tag archives are not being redirected with the trailing slash, there is still /tag/%tag% and also /tag/%tag%/ so the SEs are indexing them both stll causing duplicate content.

    I tried fixing it using the path from to option but it didn’t work.

    As for the rest it’s working fine.

  18. scotty on 8 Mar 2009 at 8:39 pm #

    @Daniel Molano — tag actually works in the Subversion version of Permalink Redirect. Try to download that instead (ylsy_permalink_redirect.php). I should have made it into a ZIP file…

  19. Matteo on 7 Apr 2009 at 5:31 pm #

    Hi Scotty,

    excuse me for my bad english.

    I want change directly in htaccess without plugin, from permalink structure:

    /%year%/%monthnum%/%day%/%postname%/

    in

    /%category%/%postname%.html

    How can i do ?

    Many thanks.

  20. abhi on 9 Jun 2009 at 11:58 pm #

    great to see someone trying to tackle the problem !

    what are the issues of unig just %postname% ? as wordpress suggests against it ..

    http://techtadka.net/tutorials/web-tutorials/202-how-to-change-wordpress-post-url-permalinks.html

  21. Andrew on 10 Sep 2009 at 12:40 am #

    Hi Scott.

    I am new to wordpress and I am trying to set up the permalink plugin but I am getting an endless loop in the main page.

    I got the latest wp(2.8.4) and your permalink plugin 2.0.1 and still gives me the error. I am hosting the blog in IIS7.

    I hope you can help.

    thanks for the great plugin.

    A.

  22. tora-san on 24 Dec 2009 at 5:49 am #

    This plugin is very nice.
    But, I have one problem.
    It is this plugin does not work with qTransrate.

    So, I have checked your source code(ylsy_permalink_redirect.php).
    I found one matter.
    I resolved my problem by adding the following codes to line-133rd of your source code.

    // add tora-san
    $req_path = apply_filters( ‘the_permalink’,$req_path);
    $permalink['path'] = apply_filters( ‘the_permalink’,$permalink['path']);

    I am wishing that it wants you adding this action to the following release.

    Best regard,.

  23. mike on 29 Jan 2010 at 11:49 am #

    have changed to ngnix server. Is there a re-write rule for ngnix that can be used?

    ngnix is running fine but my Google liks are 404 now because ngnix needs to add the /index.php/ into the URL

  24. Adal Design on 17 Mar 2010 at 8:11 am #

    I have changed my primary domain from a .net to a .com. All I want to do is make all domain.net/category/post links point to domain.com/category/post. Yet I can’t seem to find ANY help on redirecting the domain only and keeping the permalink after it.

    IE: person types or clicks on link to domain.net/fun/how-to-have-it
    and is redirected to domain.com/fun/how-to-have-it, knowing that these are simply wordpress permalinks, not files names or folders.

    Any help anyone?

  25. Kamal Hasa on 28 Apr 2010 at 5:56 pm #

    Well with the migration plugin for wordpress the 404 problem is just history ;)

  26. Pingback: wordpress建站,网站优化URL固定链接设置 - 拓宽seo网站优化服务公司

  27. Pingback: 用WordPress进行网页文件名优化 at 81mb–建站指导

  28. Shoaib Hussain on 5 Jul 2010 at 12:09 am #

    Well m using the migration plugin did the job for me ,even though this is a nice n informative post.

  29. Cheshmehregi on 28 Jul 2010 at 12:48 pm #

    wonderful plugin ! many thanks to you !

  30. pixels design on 26 Aug 2010 at 5:43 pm #

    Fantastic plugin. Works perfectly.

  31. Pingback: 优化WordPress博客 最佳化设置固定链接构造 | 杭州seo,企业网络营销顾问-陈继柔的企业网站推广博客

  32. Brian Abella on 20 Feb 2011 at 3:52 am #

    how about ? category.html instead of /category/ anyone has solution for this one ? thanks .

  33. Grant on 25 Jul 2011 at 4:35 am #

    Hi, could use some help, what would my redirect rule look like if my old permalink looks like this:

    domainname.com/YYYYMMDD-title-name/

    or

    domainname.com/YYYY/MM/DD/title-name.html/

    Thanks!

  34. Anuj@WordPressSEO on 22 Sep 2011 at 12:17 pm #

    I think using /%postname% is absolutely essential for SEO purposes. Another great move that resulted in a huge trafic increase it to install All in One SEO and remove %blog-title% from pages and posts. I guess that makes your page more focused to it’s particular term

  35. djtechwork on 10 Oct 2011 at 8:54 pm #

    I’ve implemented /%postname%.html to my site and so far so good. Now I’m interested to use All in One SEO as Anuj suggested..

  36. Nabeel on 17 Oct 2011 at 8:25 am #

    won’t regex on every incoming request make server “loaded” ?

  37. Nabeel on 17 Oct 2011 at 8:26 am #

    im not sure about how much, but i assume regex does bother server.. ?

  38. JB on 1 Dec 2011 at 10:05 pm #

    Hi.
    help pls
    I have default structure http://myblog.com/?p=123
    I want http://myblog.com/postname
    To migrate permalink need insert old permalink structure (/?p=123)
    %post_id% not work.
    What permalink structure /?p=123 ??????

  39. Ekendra on 16 Jan 2012 at 2:05 pm #

    Any way to achieve this change in permalink structure from
    /%category%/%postname%-%post_id%.html to /%category%/%postname%.html

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may 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>