Being able to redirect a post to another URL is a common need of any WordPress-based Web Master: there are a number of good reasons for doing that, such as: splitting your blog, moving a post from a website to another or to a sub-domain, and so on. Luckily enough, there are a lot of good plugins that can help you to do that, such as:
- Redirection by John Godley
- Redirect by Get on Social
- Safe Redirect Manager by Taylor Lovett
... and so on.
Unfortunately, most of them are either working with an SourceURL > RedirectURL static list or by adding a widget in the Edit Post page where you can insert the target redirect URL and some additional parameters, such as the redirect type (301 or 302).
What if we need to redirect all posts matching a certain condition? Here are some examples:
- Redirect all posts in one or more categories.
- Redirect all posts having one or more tags.
- Redirect all post within a list on given IDs.
... And so on.
Luckily enough we can do all even without a plugin, thanks to the template_redirect native action hook. This action hook executes just before WordPress determines which template page to load, hence it's the ideal choice if we need to issue redirects based upon any post-based property: all we need to do is to use the add_action() WP native method to hook it with a custom method that will perform the actual redirect.
Here's a snippet that will 301-redirect all the post in the Test1, Test2 and/or Test3 category:
1 2 3 4 5 6 7 8 9 10 11 |
add_action('template_redirect', 'post_redirect_by_custom_filters'); function post_redirect_by_custom_filters() { global $post; // this array can contain category names, slugs or even IDs. $catArray = ['Test1','Test2','Test3']; if (is_single($post->ID) && has_category($catArray, $post)) { $new_url = "http://www.newurl.com/{$post->post_name}/"; wp_redirect($new_url, 301); exit; } } |
Place the snippet in the function.php file of your current Worpdress Theme, replacing the sample category names with your actual ones, and test it out. As we can see, we used the WP-native has_category() helper function, which will return TRUE if the post is contained in one or more of the categories identified by the given names, slugs and/or IDs.
IMPORTANT: be sure to properly configure the $new_url string variable to match your current Permalinks configuration: you might have to add a .html suffix instead of the trailing slash we used in the above sample.
If we want to use Tags instead, we can use the same identical code with the has_tag() helper function, which will return TRUE if the post has one or more tags identified by their names, slugs. and/or IDs:
1 2 3 4 5 6 7 8 9 10 11 |
add_action('template_redirect', 'post_redirect_by_custom_filters'); function post_redirect_by_custom_filters() { global $post; // this array can contain tag names, slugs or even IDs. $tagArray = ['Test1','Test2','Test3']; if (is_single($post->ID) && has_tag($tagArray, $post)) { $new_url = "http://www.newurl.com/{$post->post_name}/"; wp_redirect($new_url, 301); exit; } } |
Needless to say, we can alter the conditional statement in the above code to configure more complex rules, such as:
1 2 3 4 5 6 7 8 9 10 11 12 |
$catArray = ['Test1','Test2','Test3']; $catArrayToExclude = ['Test4','Test5']; $tagArray = ['tag1','tag2','tag3']; $tagArrayToExclude = ['tag4','tag5']; if (is_single($post->ID) && has_category($catArray, $post) && !has_category($catArrayToExclude, $post) && has_tag($tagArray, $post) && !has_tag($tagArrayToExclude, $post)) { /* TODO: perform the redirect as shown above */ } |
As we can easily see, the above code is versatile enough to configure the post filter in any possible way: we can mix categories and tags, check up the post ID against a list of given IDs and more.
That's it for now... happy coding!
Hi Ryan,
How could I act if my category posts URL’s goes like this:
domain.com/YEAR/month/PostName.html and now goes to
NewDomain.com/YEAR/month/PostName.html
I’ve tried every single way but your code only takes me to:
NewDomain.com/PostName
Hello there,
try the following:
Hi!
How to simplify the code? It is required to make a redirect from 100 categories on 100 pages.
In order not to repeat a hundred times the code:
add_action(‘template_redirect’, ‘post_redirect_by_custom_filters’);
function post_redirect_by_custom_filters() {
global $post;
// this array can contain category names, slugs or even IDs.
$catArray = [‘ID1’];
if (is_single($post->ID) && has_category($catArray, $post)) {
$new_url = “https://syte.com/?page_id=1{$post->post_name}/”;
wp_redirect($new_url, 301);
exit;
}
}
How to specify 100 redirect in one code ???
Thanks in advance.
I don’t understand your issue, the given sample already give you all the basic info to implement any common scenario (including having to rewrite 100 categories and/or 100 posts).
If you have 100 categories to redirect, just specify 100 category IDs within the $catArray variable.
If you have 100 pages to redirect, just create a $postIDs array variable, put the 100 post IDs inside, and rewrite the IF accordingly taking into consideration the $postIDs variable.
It goes without saying that you need to know PHP at least a bit to implement this, you won’t be able to pull it off by copy/pasting code samples here and there: if you don’t know how to do that, get yourself a PHP coder, make him/her read this post + these comments, and he/she will fix your issue in 2 minutes.
I meant it
add_action(‘template_redirect’, ‘post_redirect_by_custom_filters’);
function post_redirect_by_custom_filters() {
global $post;
$catArray = [‘297’];
if (is_single($post->ID) && has_category($catArray, $post)) {
$new_url = “syte.com/?page_id=2230{$post->post_name}/”;
wp_redirect($new_url, 301);
exit;
}
$catArray = [‘298’];
if (is_single($post->ID) && has_category($catArray, $post)) {
$new_url = “syte.com/?page_id=2232{$post->post_name}/”;
wp_redirect($new_url, 301);
exit;
}
$catArray = [‘299’];
if (is_single($post->ID) && has_category($catArray, $post)) {
$new_url = “syte.com/?page_id=2234{$post->post_name}/”;
wp_redirect($new_url, 301);
exit;
// And so on to infinity
}
}
Is it possible to simplify – to minimize the code?
Or is this the best solution?
I perfectly understood what you meant, and my answer is the same: this is a trivial problem, just instantiate an associative array (catID -> postID) with all the catIDs and postIDs you have, and then iterate our sample code through it. This is something that any decent PHP developer can pull off in 10 minutes by reading these comments. Just get one and deal with it.
Hi Ryan,
I have thousands of tags (in my WP website) which are used just one time and I’m going to delete them and redirect each of them to respective posts.
I googled it and find below code, but I don’t know which types of redirects (301, 302) it does.
//////
function redirect_to_post(){
global $wp_query;
if( is_archive() && $wp_query->post_count == 1 ){
the_post();
$post_url = get_permalink();
wp_redirect( $post_url );
}
} add_action(‘template_redirect’, ‘redirect_to_post’);
/////
Could you please let me know, which code should I use
In line 6, replace
wp_redirect($post_url);
withwp_redirect($post_url, 301);
(or 302 if you do want 302). That’s it. If you don’t type anything, the default value is 302.ref.: https://developer.wordpress.org/reference/functions/wp_redirect/
Thanks a lot ♥
Hello
Mine problem is that on 2nd site i converted posts to pages due to some reasons. So is it possible to redirect pages to post ?
i’m asking because i tried with above code and didnt work
I attached all pages on 2nd site to a category with the help of plugin
Post permalink structure on first site and page permalink sturcture on 2nd site is same .
Thanks for any help (:
You need to replace
is_single($post->ID)
withis_page($post->ID)
in the above snippet to make it work with pages.Hi Ryan!
That snippet is great for people like me to learn about how wordpress and php works.
I have tried to adapt it to work with a CPT and custom taxonomies but I haven’t been able to. Would you be able to adapt it in a simple way for that purpose?
Thank you in advance.
Daniel
Unfortunately we can’t provide such kind of assistance for free :(