The WordPress custom taxonomy system allows you to create your own grouping of WordPress objects (e.g. posts, pages, and custom post types). Tags and categories, for example, are taxonomy objects that are native to the WordPress system. With the custom taxonomy framework, you can create your own tags and categories.
In the article Custom Post Type Permalinks (Part 2), Lane and Andrew asked the very good question of how we can add custom taxonomy tags to WordPress permalinks.
For example, if we have a custom taxonomy called rating we might want to set our WordPress permalink structure to –
/%rating%/%postname%
Here we consider how to insert custom taxonomy tags into the WordPress permalink structure.
1. Create a Custom Taxonomy
First, we create a custom taxonomy object called rating with the register_taxonomy WordPress function.
add_action('init', 'my_rating_init'); function my_rating_init() { if (!is_taxonomy('rating')) { register_taxonomy( 'rating', 'post', array( 'hierarchical' => FALSE, 'label' => __('Rating'), 'public' => TRUE, 'show_ui' => TRUE, 'query_var' => 'rating', 'rewrite' => true ) ); } }
Setting the rewrite argument to true (Line 10) will automatically add the tag %rating% to our WordPress system.
However, if we try to set our blog permalink structure to –
/%rating%/%postname%
Our new post permalinks will look like this
http://shibashake.com/wordpress-theme/%rating%/test-1
As a result we will get a 404 file not found error. This is because our %rating% tag was not properly translated.
2. Translate Our Custom Taxonomy Tag
To translate our new %rating% tag, we must hook into the permalink generation function – get_permalink.
The post_link hook allows us to translate tags for regular post objects and the post_type_link hook allows us to translate tags for custom post type objects.
Note that both filter hooks accept exactly the same arguments, so we can tie both hooks to the same function.
add_filter('post_link', 'rating_permalink', 10, 3); add_filter('post_type_link', 'rating_permalink', 10, 3); function rating_permalink($permalink, $post_id, $leavename) { if (strpos($permalink, '%rating%') === FALSE) return $permalink; // Get post $post = get_post($post_id); if (!$post) return $permalink; // Get taxonomy terms $terms = wp_get_object_terms($post->ID, 'rating'); if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug; else $taxonomy_slug = 'not-rated'; return str_replace('%rating%', $taxonomy_slug, $permalink); }
Line 5 – If the permalink does not contain the %rating% tag, then we don’t need to translate anything.
Line 12 – Get the rating terms related to the current post object.
Line 13 – Retrieve the slug value of the first rating custom taxonomy object linked to the current post.
Line 14 – If no rating terms are retrieved, then replace our rating tag with the value not-rated.
Line 16 – Replace the %rating% tag with our custom taxonomy slug.
Our new post permalinks will look like this –
http://shibashake.com/wordpress-theme/rated-a/test-1
Darshan Saroya says
I want to access two different types of taxonomies like city and room, how can I access it via wp permalink?
Owais says
Great tutorial for custom taxonomies. I have found another one for Non-hierarchical Custom taxonomies.
My site plan says
Wow Amazing this customer taxonomy is great, I will give it a try and put my guest posts under this section.
Haripal says
Thanks ShibaShake for sharing this article, I have added the code for custom post type for taxonomy links in permalink. For costom post type it works fine, But when i check pages and posts the permalink is not working shows 404 error. Please give reply how to solve this issue.
David says
thanks for your code really solved lots of my permalink structured, could if be possible for me to print /%rating%/ using conditional statement like
[code]
if(!empty(rating)):
echo "/%rating%/ ";
[code]
instead of printing not-rated. thanks
Carlos says
Awesome!
I did not know that just adjusting those settings it could also be used!
I use CustomPress for custom post types management, and I just needed to see how to use my custom taxonomy in the URL.
To think that I just had to use it like that, %custom_taxonomy_name%!
You are such a life saver, thanks!
Javier says
When you use the same rewrite as the custom taxonomy, it works for posts, but not for pages like domain.com/archive or domain.com/search
If your slug for custom taxonomy is at this example “rating”, it will work
Marc Getter says
It looks like with 4.5.2 this no longer works.
This is my code:
add_filter(‘post_link’, ‘locale_permalink’, 10, 3);
add_filter(‘post_type_link’, ‘locale_permalink’, 10, 3);
function locale_permalink($permalink, $post_id, $leavename) {
if (strpos($permalink, ‘%locale%’) === FALSE) return $permalink;
// Get post
$post = get_post($post_id);
//print_r($post_id);
if (!$post) return $permalink;
// Get taxonomy terms
$terms = wp_get_object_terms($post->ID, ‘locale’);
if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
else $taxonomy_slug = ‘no-locale’;
return str_replace(‘%locale%’, $taxonomy_slug, $permalink);
}
I’m using /%locale%/%postname% as the custom permalink.
The urls are rewriting fine, and if I check the post id, it’s returning the correct value. The problem is that wordpress is returning a 404 whereas this worked before upgrading to 4.5.2. Before I go through the process of downgrading back to 4.4, is there something I’m missing?
Bree says
I have the same problem -_-
Remko says
I’ve applied the code and its working. But all pages returns 404’s. How to fix this?
Saulo says
I have the same issue. Did you find the fixing?
JB says
You need to modify the request due to the permalink conflict.
I am doing an explicit look for my custom tag values and if I don’t find them then I’m adding in the page_id and post _id using a custom function I built to get the if from the urls slug (which WP does not have a function for).
Saulo Padilha says
This code on functions.php fixed for me.
add_filter(‘rewrite_rules_array’,’remove_bare_folder_rule’);
function remove_bare_folder_rule( $rules )
{
unset($rules[‘([^/]+)/?$’]);
return $rules;
}
JB says
This didn’t work for me unfortunately. 🙁
Anonymous says
This worked for me – thank you!!!!!
Jesse says
Try adding your replacement tag with add_rewrite_tag(), eg. using the example ‘%rating%’:
function rating_rewrite_tag() {
add_rewrite_tag( ‘%rating%’, ‘(.+)’, ‘rating=’ );
}
add_action( ‘init’, ‘rating_rewrite_tag’, 10, 0 );
Darshan Saroya says
Update permalinks. Go to settings > permalink and just save it.