Add Custom Taxonomy Tags to Your WordPress Permalinks

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

Related Articles

If you enjoyed this article, please help support our site.

Comments

      • 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;
      }

    • 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 );

  1. says

    I hope this post is still active and i can get some advice.

    I successfully implemented the taxonomy into the rewrites however now my pagination doesn’t work.

    When i go to page 2 i get a 404.

    Any ideas why?

  2. says

    Hi ShibaShake,
    Thanks a lot for this article. This is almost exactly what I was looking for. You explain how you can add the tag %rating% in WordPress Admin permalinks. But If I want to use this structure only for 1 specific post type, how can I do that?

    Thanks!
    Robbert

    • ManiMills says

      function gl_cat_permalink($permalink, $post_id, $leavename) {
      if (strpos($permalink, ‘%gl_category%’) === FALSE) return $permalink;

      // Get post
      $post = get_post($post_id);
      if (!$post) return $permalink;

      // Get taxonomy terms
      $terms = wp_get_object_terms($post->ID, ‘gl_category’);
      if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
      else $taxonomy_slug = ‘not-gl-categoies’;

      return str_replace(‘%gl_category%’, $taxonomy_slug, $permalink);
      }

      /%gl_category%/%post_id%/%postname%/

  3. Code Is Poetry says

    Thank you very much for your post!
    You are the only site on the web that explains this subject clearly.
    I followed though all your example, and I successfully managed to create a custom taxonomy
    that allowed me to use multiple hierarchy in the url [It was a bit too hard, but without this it would have been impossible].
    By the way, your 3D arg is trully amazing. I like all your characters and your style. You are surely a very talented person.
    Thanks!

  4. says

    Hello! Thanks for your advice… I get the same error of ZAK, and a I get error 404 in pages.

    I used this code….

    add_filter(‘post_link’, ‘provincia_permalink’, 10, 3);
    add_filter(‘post_type_link’, ‘provincia_permalink’, 10, 3);

    function provincia_permalink($permalink, $post_id, $leavename) {
    if (strpos($permalink, ‘%provincia%’) === FALSE) return $permalink;

    // Get post
    $post = get_post($post_id);
    if (!$post) return $permalink;

    // Get taxonomy terms
    $terms = wp_get_object_terms($post->ID, ‘provincia’);
    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) $taxonomy_slug = $terms[0]->slug;
    else $taxonomy_slug = ‘general’;

    return str_replace(‘%provincia%’, $taxonomy_slug, $permalink);
    }

    I used the my_blog_reques function, but it gets in a page [provincia]=>….

    I don’t know why it gets the page rule and where it is.

    Regards. Thanks.

    Would you help me?

  5. avi says

    hello

    i see your post while searching for some solution, i am not wp expert not programming geek, but i need solution for my blog
    my question is – i want to create a new url structure with my categories and custom taxonomies,
    like example

    Custom Taxonomy “programs” with child taxonomies, fine art, communication design, graphic design, printmaking.

    In the main menu under the parent category “News” the child categories are, student news, faculty news, and alumni news
    now i want to show the student news for fine arts
    site.com/student-news/fine-arts/ and
    site.com/faculty-news/fine-arts/ and
    site.com/faculty-news/printmaking/ and
    site.com/alumni-news/fine-arts/ and so on

    can you help me please.
    many thanks

  6. Hasan Khan says

    I found this post while trying to modify the permalink structure for my new blog, but can’t make sense of it as I’m a PHP newbie. I bought a review theme, and it has custom post type “reviews” built in as well as categories for those reviews. The current permalink for reviews is “/reviews/postname/” however, I want it to be “/reviews/category/postname”.

    My category permalinks are “review-cats/category” but I want them to be just “reviews/category” and my tags permalinks are “review-tags/tag” and I want them to just be “reviews/tag”. Any idea how I can accomplish this? It would be AMAZING if you could help me out!

  7. says

    First off I want to thank you for writing this post. I’ve been researching this issue for days. It’ took my a long time to find this but so happy I finally did. Below I took your awesome function and made it fully dynamic. It should search through and replace as many un-translated customer slugs. I hope this helps everyone. Let me know what you think.

    add_filter('post_link', 'rating_permalink', 10, 3);
    add_filter('post_type_link', 'rating_permalink', 10, 3);

    function rating_permalink($permalink, $post_id, $leavename) {

    $matches = array();
    $t = preg_match_all('/\%(.*?)\%/', $permalink, $matches, PREG_SET_ORDER);

    // If no matches were found simply return the original permalink
    if (empty($matches)) return $permalink;

    // If matches were found translate them

    // Get post
    $post = get_post($post_id);
    if (!$post) return $permalink;

    foreach ($matches as $match) {

    // Get taxonomy terms
    $terms = wp_get_object_terms($post->ID, $match[1]);

    if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0]))
    {
    $taxonomy_slug = $terms[0]->slug;
    }
    else
    {
    $taxonomy_slug = $match[1];
    }

    $permalink = str_replace($match[0], $taxonomy_slug, $permalink);
    }

    return $permalink;
    }

  8. Rajan says

    hi admin,

    acc. to your tutorial i added a unique tag into custom permalink structure. for example i added :- /%categoryProperty%/%postname%/.

    but the permalink is still having post name only. /%categoryProperty%/ is not showing in permalink. can you suggest me what the wrong is happened?

  9. says

    Thanks a lot! I was afraid that this could ever be done. I built different permalinks for different depth:

    hotels/europe/france/paris/a-post-about-a-hotel

    and shallow itens such:

    places/europe/france/10-parks-you-should-visit
    places/europe/france/top-cheap-stores

    I just needed to build the link:
    $taxonomy_slug = $terms[0]->slug.'/'.$terms[1]->slug

    Thanks a lot!

  10. lance says

    any idea how to add a username in a link?
    for exampe. site url: http://mysite.com/
    now adding a username makes it http://mysite.com/username
    note. the username can be change e.g john, james or jones.

    now for example we have a username john -> our url now is http://mysite.com/john

    and if we visit other page like contact, the username should be ther on a link e.g http://mysite.com/john/contact.html

    but if theres no username on the link. e.g http://mysite.com/
    the contact page should only be http://mysite.com/contact.html

    hopefully you could help me. cheers!

  11. Ryan says

    I don’t follow this, I can’t tell what I’m suppose to leave the same and what I am suppose to replace with my custom post type name and taxonomy name.

  12. says

    I’ve tried this technique to help me migrate an old static-HTML web site to WordPress, without having to change any of the old page URLs. I created a custom taxonomy that corresponded to the directory structure of the old site. It works great, allowing me to give all my _posts_ the same URL that my static web pages used to have, except for one serious problem:

    All of my _page_ permalinks no longer work.

    Although this should not have affected page permalinks at all, it seems to have broken them. WordPress still thinks that they have not changed, but trying to go to them takes me to my 404 page instead. Does anyone have any ideas what might be wrong?

      • says

        Okay, thanks, that makes sense. It’s not clear to me how to resolve this though, since I can’t just insert a unique slug into the structure (since my goal is to make the page URLs exactly the same as they were on the static site, which did not contain that unique slug).

        • says

          Another solution is to just add a unique character instead of an entire slug, for example –

          $wp_rewrite->add_rewrite_tag("%mytax%", '_(.+?)', "mytax=" );
          

          Note the underscore added to the beginning of the regex structure. I haven’t looked into this in great detail but playing around with the regex associated with each of the terms may bring some interesting solutions. I have tried the underscore solution on taxonomies, and it does work.

          One can probably also change the regex structure for a ‘page’, but that is not something I have tried, so I don’t know how easy/difficult it is.

      • says

        One (less than ideal) solution I just found is to make _all_ of my pages children of some (never displayed) parent page. This effectively adds a slug to the beginning of each parent page permaling, thus making it no longer regex-match my custom post permalink structure. Suggestions for a better idea are still appreciated.

        • says

          Just found a fix that works!

          add_filter('rewrite_rules_array','remove_bare_folder_rule');
          function remove_bare_folder_rule( $rules )
          {
             unset($rules['([^/]+)/?$']);
             return $rules; 
          }
          

          This removes the rewrite rule that causes a bare page reference to be interpreted as a folder reference.

  13. Marius says

    I’ve tried it, it works perfectly, except for one thing: if the taxonomy is hierarchical, it only puts the first level in the URL. Can you tell me how to change the PHP so that it works on hierarchical taxonomies by having the path /parent/child/child/postname?

    Thx!

      • Steffen says

        First… thanks for your informative article.

        I tried your suggestion but i get always an 404.

        http://example.com/my-custom-post-type/taxo/child-of-taxo/post-title -> 404

        If i delete the slug ‘child-of-taxo’ manually from the adressbar everything works fine.

        http://example.com/my-custom-post-type/taxo/post-title -> 404

        This the code i’m using:


        add_filter('post_link', 'taxo_permalink', 10, 3);
        add_filter('post_type_link', 'taxo_permalink', 10, 3);

        function taxo_permalink($permalink, $post_id, $leavename) {
        if (strpos($permalink, '%taxo%') === FALSE) return $permalink;

        // Get post
        $post = get_post($post_id);
        if (!$post) return $permalink;

        // Get taxonomy terms
        $terms = wp_get_object_terms($post->ID, 'taxonomie');
        if (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) {
        $slug1 = $terms[0]->slug;
        $slug2 = $terms[1]->slug;
        $taxonomy_slug = $slug1 . '/' . $slug2;
        } else {
        $taxonomy_slug = 'other';
        }

        return str_replace('%taxo%', $taxonomy_slug, $permalink);
        }

        I’m sure you are a busy man but i would appreciate a suggestion how to fix this problem. Do you have an idea?

  14. says

    As before, Shibashake, I very much appreciate all your help and patience!

    1) While that didn’t result in an error, the links did not function properly. Posts within a Taxonomy, and their URLs, worked perfectly. Posts within a Category worked perfectly, but their URLs removed the category entirely, leaving two slashes in the title (e.g.; site.com//postname/

    2) I’ll have to dig further into this fix — or hire someone smarter than myself to help 😉 [I feel bad for hijacking your thread with my many comments, but if interested / available / affordable, I’d be honored if you took a stab! I sent you an email through your site with the same]

    • says

      Hello Rob,

      Sorry for the late reply. Have been busy with dog matters lately.

      I am currently not working on external projects, but will be happy to answer whatever questions that I can. Good luck with your site.

      • says

        no worries, shibashake – hope the dogs are well!! regarding my permalinks, i can’t thank you enough for getting me this far!! unfortunately, heading through the next steps is just a bit (a lot!) beyond my brain. i can’t quite get the “no taxonomy, then category” part working, and hooking into the request filter is an entirely foreign concept to me. if you had anything easy to further suggest, i’m happy to give it a try! but i don’t want to completely hijack your post with my dumbness :)

        • says

          Hi Rob,
          Your site looks very awesome!

          If you send me the file you use to modify your permalinks, I can probably play around with it some to get the category thing working. I will send you an e-mail.

  15. says

    i recently created a “cartoons” taxonomy, with all different cartoon names as part of the group: pokemon, smurfs, thundercats, etc. most of my posts have a “cartoon” that they are associated with. however, there are some posts that are not part of a cartoon taxonomy.

    without knowing the proper nerd speak (i’m only an unproper nerd), i’d love the permalink logic to act something like this:

    if this post has a taxonmy, make the url:
    /%cartoons%/%postname%/

    else this post does NOT have a taxonomy, make the url:
    /%category%/%postname%/

    is that feasible using your code, above…? and if so, what would i enter in SETTINGS > PERMALINK ?

    • says

      Hmmm, you could try using /%cartoons%/%postname%/ as your main permalink and then in the rating_permalink/cartooon_permalink function, insert in the post category instead of ‘not-rated’.

      • says

        hi shibashake – first off, you’re the best :)

        with that out of the way, i implemented as you detailed above, and it worked VERY well, but not perfectly. all of the posts within a cartoon taxonomy moved to their new URL without issue, which was awesome.

        however, i hit two issues with the rest:

        1) how do i change “else $taxonomy_slug = ‘no-rating’;” to force it to pull up the respective category slug? (as a quick fix, i’ve changed it to just the general term “cartoon”, which isn’t so bad!)

        2) i’ve run into the 404 issue with pages. reading through the comments, i saw that you link people to: http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict however, im hoping to avoid adding the extra portion of the slug (that’s the whole purpose of this change, for me, anyway). one page i have, for example, is “toonbarn.com/games” which results in the 404. even if i change the slug of that page to “toonbarn.com/gamessuperface” – which i did! :) – i still get the 404 upon entry. is that still part of the same issue…?

        • says

          Hello Rob –
          1. Try using get_the_category
          http://codex.wordpress.org/Function_Reference/get_the_category

          2. The 404 error occurs because 2 different objects share the same regular expression structure. Changing the actual name of the page or even changing the permalink tag names %my_taxonomy% will not solve the issue because the regular expression structure is still similar.

          You can quickly identify if it is a regular expression structure issue by adding in the slug and seeing if that solves the problem. Alternatively, you can hook into the ‘request’ filter and see what arguments are being passed into the query. There is an example of the request filter here –
          http://shibashake.com/wordpress-theme/mastering-the-wordpress-loop

          • says

            thanks again for the help, shibashake

            1) unfortunately, i couldn’t get this to work. i’m likely just not smart enough to get the proper php phrasing when replacing the “else $taxonomy_slug” with something like “get_the_category”. The closest I could get was the URL coming up with the term “Array” as that portion of the slug. In the meantime, seems like it’s just easiest for me to keep the “fake taxonomy” of just the simple “cartoon”

            2) as you said, I tried adding another term to the front of the permalink structure, and it had everything working again! the pages AND the posts with the new custom URL. Now that it is identified as an expression structure issue… does that mean its possible to bypass? I really only have three or four pages, so I’d love to be able to get to everything without the extra slug piece (though it wouldn’t be the end of the world if it had to be)

          • says

            Hello Rob,

            1. Try something like –

            else {
            $category = get_the_category($post->ID);
            $taxonomy_slug = $category->slug;
            }
            

            instead of else $taxonomy_slug = ‘not-rated’;

            2. You could solve the 404 issue by making the regular expression structure unique. For example we could add unique characters into the taxonomy name. Another possibility is to hook into the request filter and resolve it manually there. Both are fairly complex though.

  16. 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

    • 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

        • 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.

  17. 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?

    • 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.

  18. 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.

    • 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.

  19. 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

  20. 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.

  21. 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.

    • 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

  22. 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

  23. 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?

  24. says

    Thanks for the great article. I was wondering if there is some way to do this for categories too. I am building a site which has the same categories for several different cities. I have created a custom taxonomy called city, and have successfully gotten posts to use the structure:
    %city%/%postname%

    I would also like this for categories, so I could have
    %city%/%category%
    For example,
    domain.com/new-york/food/fine-dining
    would return all posts categorized as ‘fine-dining’ that also have the city term=’new-york’ (and fine-dining is a subcategory of food).

    Thanks in advance for any advice.

  25. Dave says

    Great article! In fact, you have lots of great articles on WordPress.

    I followed your method and my custom permalinks for several custom post types are working great. they replace %artist% in my URL with an artist name. However, whenever I try to view a page I get a ‘page not found’ error.

    Also, same thing happens for normal posts. I can get posts working if I set my permalink settings to /%artist%/%postname% but if I leave out %artist% I get a ‘post not found’ error.

    Any ideas where the conflict is occurring for pages and posts?

    Cheers

  26. says

    Hi there,
    There is a small typo in the following code:

    `add_filter(‘post_type_link’, ‘rating_permalink’), 10, 3);`

    Should be:

    `add_filter(‘post_type_link’, ‘rating_permalink’, 10, 3);`

    I removed a parenthesis.

  27. says

    I’m having an issue here too. I have adapted your code for my two taxonomies: ‘artist’ and ‘writer’. Also, I use a custom post type ‘story’.

    When I define the rules to /%artist%/%writer%/%postname% or /%artist%/%writer%/%story% I get a not found.

    • ShibaShake says

      In general, I find that it is best to go slowly –
      1. First, make sure the custom post type permalink is working, i.e. don’t include a taxonomy tag yet.
      2. Then only include one taxonomy tag.
      3. Once that works, add another one and so on.

      At this point, it is difficult to tell whether the issue is with the custom post type or with the taxonomy. To debug, you can also hook into the ‘request’ filter and see what the query arguments are.

  28. Homem Robô says

    Hi there, first, nice work! I learn some cool tricks with your tutorials. But can you help me? I try almost 2 days to get this structure to working:

    For custom post types:
    /%category%/%child_category/%post_type%/%postname%/
    /%category%/%post_type%/%postname%/

    For normal posts:
    /%category%/%child_category/%postname%/
    /%category%/%postname%/

    But no lucky. I’m using the default wordpres “categories” as taxonomies for posts and other post_types. But when I got the permalink right on admin, my template get 404.

    Thanks,

    homem robo

    • ShibaShake says

      For custom post types you need to use the custom post type tag. For example, if my custom post type = gallery, then I do
      /%category%/gallery/%gallery%/

      If you want to use your own tags, e.g. %child_category% or %post_type% you must first define them. Permalink tags can get created during taxonomy or custom post type creation, or you can create them yourself using add_rewrite_tag.

      Here is an article specific to setting the permalinks for custom post types –
      http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2

  29. Zak says

    I am designing a website for a newspaper. I used this tutorial to get the article permalinks to be http:…/article/[issue-date]/[section]/[article-headline]. It worked for a while but broke a few days later when I was working on something unrelated. I changed my code back but it still doesn’t work. It changes the permalinks correctly and the links lead to the correct place but I get a 404 page. Any ideas what could be wrong?

    • Zak says

      Sorry for posting again but I forgot to add an observation I had made. I found it pretty odd that it could somehow get the correct article information but not find the article. I mean it needed the article in the first place to get the proper taxonomies, right?

    • ShibaShake says

      My guess is that there is a conflict with some other permalink structure that you are using. If there is a conflict (i.e. two permalink rules that match the same address string), then only the first rule that matches will fire.

      It could also be that the permalink rules weren’t properly flushed before. Every time you change any permalink structure you want to flush your permalink rules so that you are sure that old permalink structures are fully cleared.

      • Zak says

        I flush the permalinks about every 30 sec (sometimes twice after I make changes just to make sure) and I don’t know what other permalink structure could be conflicting. I even restarted my computer multiple times since it happened and manually cleared out whatever caches I could find. It is not just a browser specific problem though.

        I honestly don’t remember anymore what changes I made when I first encountered this problem but the first thing I did when it happened was to revert the changes. Upon researching I saw a lot of people mention the .htaccess file, could there maybe be conflicting rewrite rules there because I can’t think of anywhere else where I have played with rewrite rules.

        I don’t think it is a conflicting name problem as the whole reason I created this long permalink structure was to avoid conflicts and also it happens with all articles…

        • ShibaShake says

          Try linking into the ‘request’ filter and print out the query arguments when you access the 404 page.

          For example –

          add_filter('request', 'my_blog_request');  // parse_request function
          
          function my_blog_request($q) {
          	if (is_admin()) return;
                  echo "";
                  return $q;
          }
          

          This will help you to identify which rewrite rule got fired and why the page did not get retrieved.

          • Zak says

            Thanks for the suggestion, I had been looking for some way to debug the request. I did it though and only got this output:
            (condensed to one line for space) Not sure where do go from there. Does this mean that it is directly calling a 404 error or that the problem is happening before the call. The site is locally hosted so unfortunately I can’t provide an address to show you but if there is any code or settings that might help I would be happy to provide them. Thanks for the attempt though.

            Oh and would it make any difference what my normal post rewrite rules are set to? I have /%postname%/%post_id% now, which works for normal posts and printed out the right info from the code above in a comment.

          • Zak says

            Sorry for the number of comments but I just noticed that in the above comment the output was cut off. Basically I got an array with “[error] => 404” in it.

          • ShibaShake says

            Hmmm, that seems to indicate that none of the rewrite rules fired. Is article-headline a custom post type? It could be an issue with the rewrite tag or an issue with the add_permastruct call.

            At this point I would just try the taxonomy tags in your regular posts just to make sure that they work. Then I would test out your custom post type permalinks with the regular WP structure. Then test it out with your own structure but with no taxonomy tags. Once that is all working, slowly add in 1 taxonomy tag at a time.

          • Zak says

            Well Article is the custom post type, article headline was what I was calling the title of the article. The odd thing is that it worked for a while so I know that it is possible to do. I will try adding the taxonomies back into regular posts and then seeing if it works with them.

            I feel like although it seems to not be firing the rewrite rules, it also seems like it has to be doing it. It changes the strings everywhere. When I go to edit an article the permalink displayed at the top will have the changes. All the links have the changes.

            I’ll keep looking through and try out your suggestions and post back whenever I have anything. Thanks.

          • Zak says

            I just realized that I forgot to include an important (I think at least) detail. I mentioned that I am dealing with the article post type but the rewrite slug of article is set to “article%issue%%section%” with issue and section being replaced. I did it that way so that if for some reason an article does not have an issue or section it replaces it with “” and if it does it replaces it with “/{whatever}.” This worked for a while so I know the method isn’t what is messing up.

  30. says

    The taxonomy retrieval function is what I don’t understand.

    Does it work the same as when you are retrieving taxonomy values on a single post page?

    e.g.

    $terms = get_the_terms($post->ID, 'speaker-name');
    
    • ShibaShake says

      Yeah you can do that. Now you just need to create a string out of the terms so that you may replace it into your permalink string at the %speaker-name% tag location. For example something like this –

      if (is_array($terms) && isset($terms[0]) && is_object($terms[0]))
      	return $terms[0]->slug;
      else return 'none';
      
      • says

        Sorry I didn’t reply on the previous comment – feel free to move it if you want to keep the conversation context.

        So this is what I have:

        add_filter('post_type_link', 'podcast_permalink', 10, 3);
         
        function podcast_permalink($permalink, $post_id, $leavename) {
        	if (strpos($permalink, '%speaker-name%') === FALSE) return $permalink;
         
        	// Must operate on current post id
        	$post = get_post($post_id);
                // Enter your own rating function here
        	$terms = get_the_terms($post->ID, 'speaker-name');
        		if (is_array($terms) && isset($terms[0]) && is_object($terms[0]))
        			return $terms[0]->slug;
        		else return 'none';
         
        	if (!$terms) return str_replace('%speaker-name%', 'no-speaker', $permalink);
         
        	$podcast_obj = get_term($terms, 'rating');
        	if ($podcast_obj && !is_wp_error($rating_obj)) 
        		$permalink = str_replace('%speaker-name%', $podcast_obj->slug, $permalink);
        	else 	
        		$permalink = str_replace('%speaker-name%', 'no-speaker', $permalink);
        	return $permalink;
        }
        

        Do I need to specify any parameters in my custom post type as it relates to the rewrite value? With the above code I tried this with the rewrite value:

        'rewrite' => array( 'slug' => '%speaker-name%', 'with_front' => false ),
        

        But the permalink comes back as: wp-admin/none
        When I don’t add any rewrite parameter nothing changes in the permalink.

        Any ideas?

        Thanks for all the help

        • ShibaShake says

          add_filter('post_type_link', 'podcast_permalink', 10, 3);
          
          function podcast_permalink($permalink, $post_id, $leavename) {
          if (strpos($permalink, '%speaker-name%') === FALSE) return $permalink;
          
          // Must operate on current post id
          $post = get_post($post_id);
          // From here onward you just want to get your taxonomy value, convert it into a string, and replace it into your speaker name tag
          
          $terms = get_the_terms($post->ID, 'speaker-name');
          if (is_array($terms) && isset($terms[0]) && is_object($terms[0]))
          $speaker_name = $terms[0]->slug;
          else $speaker_name =  'no-speaker';
          
          $permalink = str_replace('%speaker-name%', $speaker_name, $permalink);
          return $permalink;
          }
          

          Also your podcast rewrite permalink should be something like

          /%speaker-name%/%podcast%
          
          • says

            Wonderful! Works great with a couple exceptions.

            First – when you hover over the view link when looking a list of posts in the admin it doesn’t fill in the taxonomy it defaults to the ‘else’ value.

            Second – the same thing happens when you query the posts for display on the front end and declare that the ‘post_type’ => ‘podcast’. If you don’t specify the post_type in your query the permalink comes up fine.

            I’m assume the admin is also querying the posts and specifying that the type is podcast, so the two issues are most likely related.

            That’s not a big deal for me at this point but its definitely not ideal.

            Anyway, thanks for the help. I really appreciate it.

          • ShibaShake says

            That sounds strange. So in both cases it is showing up as /no-speakers/test-1?

            Two things that come to mind –
            1. Make sure to flush your rewrite rules.
            2. Do some echos in your function and see what terms are being retrieved by wp_get_object_terms.

          • says

            Yep. Whatever value is assigned to ‘else’ shows up in the permalink in those two instances.

            I have flushed my rewrite rules by both visiting the permalinks page and by changing the default permalinks but neither helped.

            When I echoed out the terms it retrieved the correct object and displayed it fine.

            I then did some additional investigating and found another post on the subject: http://xplus3.net/2010/05/20/wp3-custom-post-type-permalinks/

            Comparing your code and his it looks like you have to declare the post_type so when you query it brings back the correct object.

            Doing that solved both issues!

            Thanks for the help and teaching me something new.

  31. says

    Thanks for all the different articles on changing up the permalinks.

    I’m a little fuzzy however trying to figure out how to enter my own function to retrieve a specific taxonomy value.

    I have a custom taxonomy called ‘speaker-name’ with the values of different speakers.

    I have a custom post type called ‘podcast’. I want the permalink to include the name of the speaker which is checked in the ‘speaker-name’ taxonomy.

    Thanks!

    • ShibaShake says

      You want to hook into the post_type_link filter then.

      // Goes in the init function
      add_filter('post_type_link', 'podcast_permalink'), 10, 3);
      

      Then just pattern your podcast_permalink function similar to the rating_permalink example I showed above. In line 10 is where you want to put in your own taxonomy retrieval function. Then make sure to replace the %rating% tag with %speaker-name%.

Leave a Reply

Your email address will not be published.