Shiba

Adventures in WordPress

  • Home
  • Dog
  • Art
  • Contact
  • WordPress Articles
    • WP Plugins
    • WP Programming
    • WP Admin Panels
    • WP Theme Design
    • WP How-To
    • WP Theme Images
You are here: Home / WordPress Admin / Custom Taxonomy / Add Custom Taxonomy Tags to Your WordPress Permalinks

Add Custom Taxonomy Tags to Your WordPress Permalinks

by ShibaShake 125 Comments

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

Leave a Reply to David Hedley Cancel reply

Your email address will not be published. Required fields are marked *

Comments

« Previous 1 2 3 4 5 6 Next »
  1. Kevin says

    August 2, 2012 at 10:27 am

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

    Reply
  2. Rajan says

    July 27, 2012 at 4:33 am

    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?

    Reply
    • ShibaShake says

      August 1, 2012 at 7:20 am

      I would look at the post_link and post_type_link function to see what is being passed in and what is being passed out.

      Reply
  3. Diana says

    June 13, 2012 at 10:53 am

    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!

    Reply
  4. lance says

    May 2, 2012 at 8:40 pm

    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!

    Reply
    • ShibaShake says

      May 7, 2012 at 8:10 am

      Probably can just use the %author% tag and then customize it as necessary.

      Reply
  5. Lehooo says

    March 14, 2012 at 11:37 am

    Thanks, this was very helpful! Works like a charm!

    Reply
  6. Ryan says

    February 15, 2012 at 9:27 pm

    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.

    Reply
  7. Stefan Vorkoetter says

    February 15, 2012 at 6:38 am

    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?

    Reply
    • ShibaShake says

      February 15, 2012 at 7:25 am

      That is likely due to permalink conflicts.
      http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict

      Reply
      • Stefan Vorkoetter says

        February 16, 2012 at 12:10 pm

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

      • ShibaShake says

        February 16, 2012 at 3:39 pm

        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.

      • Stefan Vorkoetter says

        February 16, 2012 at 12:18 pm

        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.

      • Stefan Vorkoetter says

        February 17, 2012 at 7:55 am

        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.

      • Saulo Padilha says

        August 20, 2015 at 7:18 pm

        Stefan, you just saved my day. I was looking for that fix for more than 6 hours!

        thanks for share!

      • Alex Nowak says

        February 3, 2016 at 8:15 am

        Hi Stefan!
        The one you posted works perfect but do you have a clue what would be the right rule for child pages?

  8. Marius says

    October 10, 2011 at 4:51 am

    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!

    Reply
    • ShibaShake says

      October 17, 2011 at 10:08 am

      You may need to traverse the parent relationship manually by using a loop.

      Reply
      • Steffen says

        October 20, 2011 at 3:36 pm

        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?

      • ShibaShake says

        October 21, 2011 at 2:44 pm

        I would try doing it with two separate tags – %taxo% and %childtaxo%

  9. Rob says

    October 9, 2011 at 8:23 pm

    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]

    Reply
    • ShibaShake says

      October 17, 2011 at 9:58 am

      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.

      Reply
      • Rob says

        October 19, 2011 at 8:31 pm

        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 šŸ™‚

      • ShibaShake says

        October 21, 2011 at 2:39 pm

        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.

  10. Rob says

    September 27, 2011 at 8:54 am

    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 ?

    Reply
    • ShibaShake says

      September 28, 2011 at 3:41 pm

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

      Reply
      • Rob says

        September 30, 2011 at 3:28 pm

        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…?

      • Rob says

        October 2, 2011 at 5:49 pm

        [also, thanks for making me a hot girl! šŸ™‚ ]

      • ShibaShake says

        October 3, 2011 at 8:01 am

        LOL! You are welcome. šŸ˜€

      • ShibaShake says

        October 3, 2011 at 8:00 am

        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

      • Rob says

        October 3, 2011 at 3:11 pm

        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)

      • ShibaShake says

        October 6, 2011 at 8:04 am

        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.

« Previous 1 2 3 4 5 6 Next »

Recent Posts

  • Screenshot of an example article in code view of a modified Gutenberg editor.How to Harness the Power of WordPress Gutenberg Blocks and Combine It with Legacy Free-Form Text
  • Screenshot of the Success, WordPress has been installed page.Migrating Your WordPress Website to Amazon EC2 (AWS)
  • Screenshot of WinSCP for creating a SFTP configuration.How to Set-Up SFTP on Amazon EC2 (AWS)
  • WordPress Gutenberg code view screenshot of this article.How to Prevent Gutenberg Autop from Messing Up Your Code, Shortcodes, and Scripts
  • Screenshot of the Success, WordPress has been installed page.How to Create a WordPress Website on Amazon EC2 (AWS)

Recent Comments

  • Screenshot of the Success, WordPress has been installed page.How to Create a WordPress Website on Amazon EC2 (AWS) (1)
    • Erik
      - Great article. All worked great except for this step:apt install php-mysqlChanging to this fixed it:apt install ...
  • Add Custom Taxonomy Tags to Your WordPress Permalinks (125)
    • Anthony
      - Where does this code go? Like, what exact .php file please?
  • Screenshot of an example article in code view of a modified Gutenberg editor.How to Harness the Power of WordPress Gutenberg Blocks and Combine It with Legacy Free-Form Text (1)
    • tom
      - hi,my experience was like the same, but for me as theme developer the "lazy blocks"(https://wordpress.org/plugins/lazy-blocks/) ...
  • WordPress Custom Taxonomy Input Panels (106)
    • Phil T
      - This is unnecessarily confusing. Why declare a variable with the same name as your taxonomy? Why did you choose a taxonomy ...
  • Create Pop-up Windows in Your WordPress Blog with Thickbox (57)
    • Jim Camomile
      - I have used this tutorial several times and it is one of the few simple and effective ways to add popups with dynamic content, ...

Copyright © 2025 · Genesis Skins by ShibaShake · Terms of Service · Privacy Policy ·