I have created a few custom taxonmies in Wordpress (e.g. author, book, comic..). I also have a few categories using the built-in category system (e.g. news, review,...).

I try to get a permalink structure like /taxonomy-base/taxonomy/category/post-title/

So if you tag a regular post with author-taxonomy Stephen King and put it into the wordpress category, you'd get /author/stephen-king/news/post-title/. If you tag it with Under the Dome (from books) and review, you'll get /book/under-the-dome/review/. In the end, we'll use just one taxonomy and one category for each regular post.

I read a few answers regarding adding a custom taxonomy to your permalink sturcture, but I think they build on having just one taxonomy that is used all the time. But we're using more than just one taxonomy. How can you do that?

  • It would work the same as something like this, except you'd just add in the extra rewrite tag and taxonomy term substitution instead of just the single one. have you tried any of the solutions you've found yet?
    – Milo
    Dec 2, 2013 at 23:27
  • Yeah, I tried those solutions, but they were using just one predetermined taxonmy (something like this link. Thanks for your link though, I think it might indeed help me. I will try it later.
    – user43420
    Dec 2, 2013 at 23:52
  • ok, I see the difference, you want a varying taxonomy base prefixing the post slugs. that may be tricky. I'll try to play around with that if I have some time over the next few days.
    – Milo
    Dec 3, 2013 at 3:05

1 Answer 1


Assuming 2 posts:

  • "News about Stephen King" | Category: "News" | "Author": "Stephen King"
  • "Review for Under the Dome" | Category: "Reviews" | "Book": "Under the Dome"

where "Book" and "Author" are custom taxonomy.

If I understand well you want that the link for first will be:

  • /author/stephen-king/news/news-about-stephen-king

and the url for the second:

  • /book/under-the-dome/reviews/review-for-under-the-dome

If so, using WordPress standard rewrite API this is a very tricky task. However, for cases like this, I wrote a plugin, Clever Rules, you can find it here.

Docs are here.

After you have downloaded, put in your plugin folder and activate it.

Now you have to register your rule. To do this, you need to write a simple plugin (or add code to an existing plugin).

Create a new php file an in it put something like:

 * Plugin Name: WPSE #125186 Tricky Rule

add_action('plugins_loaded', 'register_my_tricky_rule'); 

function register_my_tricky_rule() {
if ( ! function_exists('register_clever_rule') ) return;
  $args = array(
    'id' => 'my_custom_rule',
    'route' => '/%s/%s/%s/%s',
    'query' => array('name'=>'[3]')
  register_clever_rule( $args );

Save it in your plugin folder and activate it.

At this moment the links you want just works, but it will fuck up any other WordPress link composed by 4 "pieces" e.g. a-parent-tax/a-child/a-granchild/something.

To avoid this, you can run the rule only if the pieces are the right ones. This can be done using the filter hook skip_clever_rule.

In the plugin file, add something like:

add_filter('skip_clever_rule', 'skip_my_tricky_rule', 10, 3);

function skip_my_tricky_rule( $skip, $rule, $pieces ) {
  if ( $rule['id'] == 'my_custom_rule' ) {
    $custom_taxes = get_taxonomies(
      array('public'=> true,'_builtin' => false, 'object_type'=> array('post') )
    if ( ! in_array( $pieces[0], $custom_taxes ) ) return true;
    // one of or both next two lines can be removed for performance reasons
    if ( ! get_terms($pieces[0], array('fields'=>'ids', 'slug'=>$pieces[1]))) return true;
    if ( ! get_terms('category', array('fields'=>'ids', 'slug'=>$pieces[2]))) return true;

Thanks to this filter you run the custom rule only if the first 3 pieces of the url are valid:

  1. if the first is a valid custom taxonomyname, e.g. 'author'
  2. if the second is a valid term of this taxonomy, e.g. 'stephen-king'
  3. if the third is a vali category term, e.g. 'news'

This 3 checks are done one by one (see the 3 if in the function). However this cost in term of performace, so probably you can remove the last 2 checks, but in this way any url like:


will open the news-about-stephen-king post.

For a compromise between accuracy and performance you can remove one of the 2 checks and leave the other.

If you put the two code blocks in the new plugin file and save, your links just works, however, at this moment, you have to manually write the urls in the address bar...

Next step is to filter the post link creation to create the url in the way you want. add the following code in the same plugin file:

add_filter( 'post_link', 'my_tricky_post_link', 10, 2 );

function my_tricky_post_link( $url, $post ) {
  if ( $post->post_type == 'post' ) {
    $custom_taxes = get_taxonomies(
      array('public'=>true, '_builtin'=>false, 'object_type'=>array('post'))
    if ( empty($custom_taxes) ) return $url;
    $newurl = '';
    while( empty($newurl) && ! empty($custom_taxes) ) {
      $tax = array_shift( $custom_taxes );
      $terms = get_the_terms( $post->ID, $tax );
      if ( ! empty($terms) ) {
        $term = array_shift( $terms );
        $newurl = $term->taxonomy .'/' . $term->slug;
    if ( empty($newurl) ) return $url;
    $categories = get_the_category( $post->ID );
    if ( ! empty($categories) ) {
      $cat = array_shift( $categories );
      $newurl .= '/' . $cat->slug;
      $url = home_url( $newurl . '/' . $post->post_name );
  return $url;

That's all. note that this will work with any custom taxonomy, without changing a line of code.

Full plugin code can be downloaded here.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.