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
David Hedley says
Hi,
Having difficulty making this work for a hierarchical category structure. Would you consider working with me on this as a paid task?
Basically I have 2 custom post types: ecp and clw (in short), each with a ‘product type’ taxonomy, and in each single custom post URL I need to add the category slug, whilst leaving the standard wordpress ‘Blog’ post URLs in tact.
Thanks
David
ShibaShake says
Hello David,
Sounds like it may be a permalink conflict issue.
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict
Two ways to debug permalink conflicts –
1. Add a unique keyword (e.g., ‘clw’) into the custom post type permalink, e.g. //mysite.com/clw/product_type/product_name.
2. Hook into the request filter and see which rewrite rule has fired and which query variables are being passed to the wordpress loop.
This WordPress Loop article has an example of the request filter.
David Hedley says
Thanks for this. As I mentioned, would you be interested in quoting to deploy the correct permalinks onto the site for me?
Thanks
David
ShibaShake says
Hello David,
At the moment, I am not taking on any external projects.
In terms of the permalinks, it is possible to have multiple objects share the same permalink rule, but you would have to resolve them yourself within the request filter function and that could get a bit messy. Usually it is much easier to just insert in a unique keyword and that would solve the permalink conflict issues.
David Hedley says
Hi, thanks for this. It’s not actually the conflict that’s the problem (I inserted an additional keyword) just cannot get the permalinks to appear correctly at all. In the custom post types I have set the taxonomies to REWRITE and have the slug left blank – is this correct?
Thanks again
David
ShibaShake says
I can probably give the code a quick look through if you want. Just post or email me the link.
http://shibashake.hubpages.com/_srec/contact
CincauHangus says
Hey many thanks on the post, truly helpful.
I did run into problems however. I have a page with /current/ and /current/members/
And a custom taxonomy for state. (eg: /current/members/state/)
Next I want to do a custom post type with the members name in it (/current/members/%state%/%member_name%/).
While testing I noticed that when I set my custom post type slug to /current/members/%member_name% it works fine without the %state%, but when I added it in, I get a page not found error.
I read your permalink conflicts and this articles and the comments, but I could not get much info to how to solve this. Is there anything I missed? If it is the permalink conflict, how do I debug?
ShibaShake says
It would depend on whether your slugs ‘/current/members/’ are unique to just a single post type. If you are using it for multiple post types, then there will likely be conflicts.
To debug, try hooking into the ‘request’ filter and see what query arguments are being passed on. This will show which permalink rule actually fired, and why you are getting a 404.
Adam says
Hey, many thanks for the comprehensive tutorials! Your site has been by far the only place where I’ve found good info on the exact subjects I’ve been looking for – your articles about custom columns and input panels have been great.
However, I’ve been having a problem getting my permalinks to work as I want them to. I hope you find my problem to be an interesting puzzle, and perhaps help me out with finding the solution.
I have a custom post type, ‘songs’, and taxonomy, ‘bands’. I want my URLs to be of the format /lyrics/%bandname%/%songname%. Two different songs can have the same title, so if I have two different posts – “Song 1” by “Band 1”, and “Song 1” by “Band 2” – /band1/song1 and /band2/song1/ would point to them. However, one song can also be covered by multiple artists, so if I have a single post called “Song 1” tagged with both “Band 1” and “Band 2”, both permalinks would redirect to the same post.
I think that this is perfectly possible with hierarchical posts and taxonomies. However, the exact details of the implementation have eluded me for a while. Maybe you could provide me with a few pointers? Sorry if I’m asking too much, I really want to get this out of my hair.
ShibaShake says
Hello Adam,
It sounds like what you describe is more of a parse_request or parse_query issue. As long as the songname is unique, I think both permalinks will work. If you have problems, then hook into the ‘request’ filter and check out what is being passed in the query arguments. There is an example of the request filter here –
http://shibashake.com/wordpress-theme/mastering-the-wordpress-loop
The tutorial outlined here is for generating the proper permalinks for a particular songname. In particular, the permalink generated will only include a single band, e.g. Band 1.
Manny Fleurmond says
Is there a way to use this with hierarchical taxonomies?? For example, if I had a taxonomy of release_type that had the following structure:
DVD
-Region 1
-Region 2
etc…
Would it be possible with a variation of your code?
and I wanted the permalinks to be as such:
site.com/dvd/region-1
ShibaShake says
Yeah, you can replace your tag with anything you want. However, there may with permalink conflict issues with that permalink structure-
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict
AskerGuy says
I have a traveling blog where I post images and video of the place I visit. I want my blog to have a structure like http://domain.com/2011/new-york/my-trip.html
2011 – I need it for WordPress to work faster with the databse
new-york – that’s like the category, although I think it should be a taxonomy?!
my-trip.html = that’s my post name
I also want to have posts identified as videos/photo gallery/hotel review, etc.
What should I use (custom posts? , taxonomies?) I also want the best structure (permalink) for my URL.
please help me out, working days on this with no results yet.
Thanks in advance guys.
ShibaShake says
Hello AskerGuy,
It seems that you can achieve what you want with just existing post_tags and categories. However, it is difficult to say for sure without knowing all the details.
Niraj says
I have a question, I am using custom taxonomies on my website, which works fine, but is it possible to have custom taxonomies tag or in other words the entire permalink structure on my title tag?
Is it possible to have my custom permalink structure on title tag of my blog?
my current permalink structure is this
`/%postname%/%location%/%mba_courses%/`
where my location and mba_courses are custom taxonomies
Now I want this on my title tag, can I write something like this in title tag?
“
I know this is a wrong code, and it won’t work, but is their any way, where I can have this kind of title tag?
ShibaShake says
This would likely depend on your theme templates. Look in your theme templates for the title tags and then you can modify its contents to whatever you want.
Niraj says
I didn’t get you,
I have my current URL in this format
/%postname%/%location%/%mba_courses%/
which means
/mba-in-insead-university/mba-in-france/mba-in-accounts/
So same I want in my title tag, so therefore, it will be something like this:-
MBA In Insead University | MBA In France | MBA In Accounts
Which is same as the URL, so how can I get this
remember in permalink location and mba_courses are my custom taxonomies
Niraj says
hey how can I do this?
I am really stumped
Joe says
Noob here Trying to wrap my head around add_action and add_filter… what PHP files are we to be placing this code into?
ShibaShake says
Two common places –
1. Your theme functions.php file. This file is commonly found in …/wp-content/themes/[theme directory]/functions.php
2. The main plugin file. This file is commonly found in ../wp-content/plugins/[plugin slug]/[plugin slug].php
Joe says
Very cool, nice work. Thank you much!
Paul says
Just noticed that using your code exactly as you have it, kills my pages for some reason. Posts work fine, just pages throw a 404 error. Any ideas?
ShibaShake says
Sounds like a permalink conflict issue –
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict