Believe it or not but changing WordPress permalink structure can actually temporarily remove your site from Google index. Also changing single page slug can do the same for that page. By default WordPress doesn't forgive these kind of changes and following old permalinks would usually result in "404 Not Found". In this article I'm bringing you WordPress plugin that enables you to redirect old permalinks to new ones after changing permalink structure or slug. This WordPress plugin will also send "301 Moved Permanently" headers to search engines and that would instruct Google and others to change their search index.
This plugin is based on excellent Change Permalink Helper WordPress plugin idea. I've changed this plugin to use WordPress build in functions where possible and I've added slug mapping to support slug changes. So here's the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | <?php /** Plugin Name: Change Permalink or Slug Helper Plugin URI: http://www.techytalk.info/ Description: Redirect and send "301 Moved Permanently" when permalink structure or slug has been changed WordPress plugin Version: 1.0 Author: Marko Martinović Author URI: http://www.techytalk.info/ Copyright 2012. Marko Martinović (email : marko AT techytalk.info) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ if ( !function_exists('add_action') ) { header('Status: 403 Forbidden'); header('HTTP/1.1 403 Forbidden'); exit; } if ( !class_exists('ChangePermalinkHelper') ) { class ChangePermalinkHelper { private $slugRedirect = array('old-slug' => 'new-slug'); function ChangePermalinkHelper() { add_action( 'plugins_loaded', array( &$this, 'onLoad' ) ); } function onLoad() { if ( is_admin() ) return; add_action( 'template_redirect', array( &$this, 'is404Permalink' ) ); add_action( 'template_redirect', array( &$this, 'is404Slug' ) ); } function is404Permalink() { global $wpdb; if ( !is_404() ) return; $slug = htmlspecialchars( basename( $_SERVER['REQUEST_URI'] ) ); $id = $wpdb->get_var( $wpdb->prepare( " SELECT ID FROM $wpdb->posts WHERE post_name = '%s' AND post_status = 'publish' ", $slug ) ); if ($id) { wp_redirect(get_permalink($id), 301); exit; } else { return true; } } function is404Slug() { global $wpdb; if (!is_404()) return; $slug = htmlspecialchars(basename($_SERVER['REQUEST_URI'])); if(!array_key_exists($slug, $this->slugRedirect)) return; $id = $wpdb->get_var( $wpdb->prepare( " SELECT ID FROM $wpdb->posts WHERE post_name = '%s' AND post_status = 'publish' ", $this->slugRedirect[$slug] ) ); if ($id) { wp_redirect(get_permalink($id), 301); exit; } else { return true; } } } $ChangePermalinkHelper = new ChangePermalinkHelper(); } ?> |
This plugin activates right before 404 page is displayed. It first checks database for valid page with given slug (to detect permalink structure changes) and if that is not successful then it checks slugRedirect array for given slug (to detect page slug changes). If any of those two checks is successful this plugin redirects to correct permalink and sends "301 Moved Permanently". Permalink structure changes doesn't require anything besides installing and activating this plugin. Slug changes require you to add old slug - new slug pairs to slugRedirect array before you change your page slug inside your WordPress admin interface. For example if my WordPress site had valid URL http://www.techytalk.info/second-old-slug
and I want to change it to http://www.techytalk.info/second-new-slug
, before doing that I'll modify my slugRedirect array like this:
private $slugRedirect = array('old-slug' => 'new-slug', 'second-old-slug' => 'second-new-slug'); |
After doing that I can safely change my page slug without worrying about search engines hitting "404 Not Found" for http://www.techytalk.info/second-old-slug
. In the future I might add some GUI to make it possible to add slug mapping pairs without editing code. That's it, hope you find it useful.
Really useful
Thanks Nick,
I’m glad you found it useful 😉
Thanks a lot for this great post. I was confused about the changes in slug of a particular page.
Great idea, great plugin. But doesn’t work for me 🙂
I changed permalinks from /%postname%/ to /%postname%/%post_id%/
Both pages give good old 200 OK
zeleneet.com/gibkie-solnechnye-batarei/
zeleneet.com/gibkie-solnechnye-batarei/1577/
Is it feature of the server or something else?
Hi Alex,
both URLs work because WordPress has built in redirection that works when when middle part of URL hasn’t changed like in your case. This plugin takes care of the other cases when you change for example:
into:
and this is something WordPress built in redirection could not handle. The only weired thing is that WordPress sends 200 OK instead of 301.
Ah so… 🙂
Any ideas, how can it be fixed? Which WordPress file to dig in?
Look wp_old_slug_redirect() and source code link is at the bottom of that page you should check that out.
Thanks for pointing.
Strangely, the file also contains wp_redirect( $link, 301 );
Now when I look at it, yes, my thoughts exactly.
That’s what I was looking for!
Thanks mate this should be in the core! Slug mapping in already in – you can take it out.