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.

Problem -- Permalink Structure Changes

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 -- Mod_Rewrite and Permalink Redirect Plugin

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.


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 :)