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.
- Use mod_rewrite to convert the old URL into query string URL.
- 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:
- Initial request:
http://wpsite/2007/02/this-is-a-test/ - 1st redirect:
http://wpsite/?name=this-is-a-test - 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
.htaccessfile 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 :)
Pingback: SDAC Inc: SDAC Recommends: WordPress Plugin: Permalink Redirect Plugin
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
Pingback: Get multiple DMOZ links and use Wordpress to do it | Needless Productions
Dear Scott,
just two little words for a great (permalink-)solution: Thank You!
Enrique
“… 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!
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 ;)
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?
I have problem to redirect from my old permalink with .htm
Only old permalink with .htm does not work.
Any idea?
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!
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.
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
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.
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
Pingback: 关于Wordpress重定向及相关插件 | Riku
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?
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!
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.
@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…
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.
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
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.
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,.
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
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?
Well with the migration plugin for wordpress the 404 problem is just history ;)
Pingback: wordpress建站,网站优化URL固定链接设置 - 拓宽seo网站优化服务公司
Pingback: 用WordPress进行网页文件名优化 at 81mb–建站指导
Well m using the migration plugin did the job for me ,even though this is a nice n informative post.
wonderful plugin ! many thanks to you !
Fantastic plugin. Works perfectly.
Pingback: 优化WordPress博客 最佳化设置固定链接构造 | 杭州seo,企业网络营销顾问-陈继柔的企业网站推广博客
how about ? category.html instead of /category/ anyone has solution for this one ? thanks .
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!
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
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..
won’t regex on every incoming request make server “loaded” ?
im not sure about how much, but i assume regex does bother server.. ?
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 ??????
Any way to achieve this change in permalink structure from
/%category%/%postname%-%post_id%.html to /%category%/%postname%.html