I've read a few posts about this, but can't find a clear answer :(

  • I have a custom post type called {ondemand}
  • Within the custom post, I have three taxonomies {speakers} and {categories} and {season}
  • Each taxonomy has 3-4 terms, for example under {speakers} there is one called [joebloggs]

Currently I have a main URL on our site, where the latest post is placed : www.mysite.com/ondemand

When I filter the posts by taxonomy terms the URL defaults to: www.mysite.com/ondemand/{speakers}/[joebloggs] (uses taxonomy.php to display the results)

However I'd like the URL to be like this for any term filtered: www.mysite.com/ondemand/[joebloggs]

Here's the code that I've used in my functions.php - I tried a re-write in each taxonomy (commented out) but that didn't work - they lead to a 404 page.... Any advice or re-code hints would be very much appreciated

* On Demand TV Post Type

add_action('init', 'ondemand');

function ondemand() {

$labels = array(
'name' => __('On Demand TV', 'post type general name'),
'singular_name' => __('TV Episode', 'post type singular name'),
'add_new' => __('New TV Episode', 'TV Episode'),
'add_new_item' => __('Add TV Episode'),
'edit_item' => __('Edit TV Episode Item'),
'new_item' => __('New TV Episode Item'),
'view_item' => __('View TV Episode Item'),
'search_items' => __('Search TV Episode'),
'not_found' => __('Nothing found'),
'not_found_in_trash' => __('Nothing found in Trash'),
'parent_item_colon' => ''

$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'query_var' => true,
'rewrite' => false,    
'capability_type' => 'post',
'hierarchical' => true,
'menu_position' => 3,   
'supports' => array('title','editor','comments','thumbnail')

register_post_type( 'ondemand' , $args );

register_taxonomy("Categories", array("ondemand"), 
array("hierarchical" => true, 
"label" => "Category", 
"singular_label" => "Category", 
"rewrite" => true));

register_taxonomy("Speaker", array("ondemand"), 
array("hierarchical" => true, 
"label" => "Speakers", 
"singular_label" => "Speaker", 
"rewrite" => true));
//"rewrite" => array('slug' =>'ondemand', 'hierarchical' => true, 'with_front' => false)));

register_taxonomy("Season", array("ondemand"), 
array("hierarchical" => true, 
"label" => "Seasons", 
"singular_label" => "Season",
"rewrite" => true));
//"rewrite" => array('slug' =>'ondemand', 'hierarchical' => true, 'with_front' => true)));

  • So you want your URL to be example.com/cpt/taxonomy-term without knowing wich taxonomy that term is from? I'm asking because taxonomies can share terms, and this can result in an unexpected behaviour. Sep 23, 2013 at 16:59
  • what if you have season/blogpage and speakers/blogpage where should www.mysite.com/ondemand/blogpage direct to? You should specify meaningful taxonomy names and use it for the URL
    – raam86
    Oct 4, 2013 at 12:15

1 Answer 1


I have done this before, but I warn you that this is something to avoid doing. It is best when you have a very limited number of terms that don't change.

With the warning over, here is how to do it. You need create a rewrite rule with the term slugs in it to not break your rewrite rules. If you use a catch all, then it will break the rewrite rules for your pages.

function my_custom_rewrite_rules_array( $rules ) {
    global $wp_rewrite;

    // Generate the regexp for the terms
    $terms = get_terms( 'Speaker', array( 'hide_empty' => false ) );
    $term_slugs = array();
    foreach ( $terms as $term ) {
        $term_slugs[] = preg_quote( $term->slug );

    // (term1-slug|term2-slug|term3-slug)
    $terms_regexp = '(' . implode( '|', $term_slugs ) . ')';

    // add_rewrite_tag( $tagname, $regex, $query )
    $wp_rewrite->add_rewrite_tag( "%speaker%", $terms_regexp, "taxonomy=speaker&term=" );
    // Use generate_rewrite_rules to make the various rules for pagination and other endpoints
    $speaker_rules = $wp_rewrite->generate_rewrite_rules( '/%speaker%/' );

    // Add our speaker rules
    return $speaker_rules + $rules;
add_filter( 'rewrite_rules_array', 'my_custom_rewrite_rules_array' );

As you may see, the downside of this is the rewrite rules need to be updated each time a new term is created. We can rebuild the rules whenever a change happens.

add_action( 'created_term', 'my_custom_flush_rewrite_rules', 10, 3 );
add_action( 'edited_term', 'my_custom_flush_rewrite_rules', 10, 3 );
add_action( 'delete_term', 'my_custom_flush_rewrite_rules', 10, 3 );
function my_custom_flush_rewrite_rules( $term_id, $tt_id, $taxonomy ) {
    $taxonomies_to_refresh = array( 'Speaker' );
    if ( in_array( $taxonomy, $taxonomies_to_refresh ) ) {

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.