I want to create a custom taxonomy which behaves similar to the post type as a category behaves to a the default posts (on the grounds of /%category%/%postname%/ permalink structure) so that the posts in the custom post types are displayed as www.example.com/custom-post-type/custom-taxonomy-name/post-name Also I want the category meta box to appear only when we add new default post and not when we add a new post in the custom post type and the custom taxonomy box to appear only when we add a new post in the custom post type and not when we add new a default post.


First of all if you want to show taxonomy metabox only to custom post type then register the taxonomy to only that custom post type by passing the custom post type name as argument in register_taxonomy. By doing this the taxonomy metabox appears only to custom post type. If your don't want to show category metabox to custom post type then remove the term category as argument while registering custom post type and instead include the taxonomy slug name like this 'taxonomies' => array( 'post_tag','your_taxonomy_name'). here is the code how i achieved that. I have registered a custom taxonomy with slug themes_categories under under custom post type themes

function themes_taxonomy() {  
        'themes_categories',  //The name of the taxonomy. Name should be in slug form (must not contain capital letters or spaces). 
        'themes',        //post type name
            'hierarchical' => true,  
            'label' => 'Themes store',  //Display name
            'query_var' => true,
            'rewrite' => array(
                'slug' => 'themes', // This controls the base slug that will display before each term
                'with_front' => false // Don't display the category base before 
add_action( 'init', 'themes_taxonomy');

Then to change the permalink i have created following function

function filter_post_type_link($link, $post)
    if ($post->post_type != 'themes')
        return $link;

    if ($cats = get_the_terms($post->ID, 'themes_categories'))
        $link = str_replace('%themes_categories%', array_pop($cats)->slug, $link);
    return $link;
add_filter('post_type_link', 'filter_post_type_link', 10, 2);

Then i registered a custom post type with slug themes as below

//Registering Custom Post Type Themes
add_action( 'init', 'register_themepost', 20 );
function register_themepost() {
    $labels = array(
        'name' => _x( 'Themes', 'my_custom_post','custom' ),
        'singular_name' => _x( 'Theme', 'my_custom_post', 'custom' ),
        'add_new' => _x( 'Add New', 'my_custom_post', 'custom' ),
        'add_new_item' => _x( 'Add New ThemePost', 'my_custom_post', 'custom' ),
        'edit_item' => _x( 'Edit ThemePost', 'my_custom_post', 'custom' ),
        'new_item' => _x( 'New ThemePost', 'my_custom_post', 'custom' ),
        'view_item' => _x( 'View ThemePost', 'my_custom_post', 'custom' ),
        'search_items' => _x( 'Search ThemePosts', 'my_custom_post', 'custom' ),
        'not_found' => _x( 'No ThemePosts found', 'my_custom_post', 'custom' ),
        'not_found_in_trash' => _x( 'No ThemePosts found in Trash', 'my_custom_post', 'custom' ),
        'parent_item_colon' => _x( 'Parent ThemePost:', 'my_custom_post', 'custom' ),
        'menu_name' => _x( 'Themes Posts', 'my_custom_post', 'custom' ),

    $args = array(
        'labels' => $labels,
        'hierarchical' => false,
        'description' => 'Custom Theme Posts',
        'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions', 'post-formats', 'custom-fields' ),
        'taxonomies' => array( 'post_tag','themes_categories'),
        'show_ui' => true,
        'show_in_menu' => true,
        'menu_position' => 5,
        'menu_icon' => get_stylesheet_directory_uri() . '/functions/panel/images/catchinternet-small.png',
        'show_in_nav_menus' => true,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'themes/%themes_categories%','with_front' => FALSE),
        'public' => true,
        'has_archive' => 'themes',
        'capability_type' => 'post'
    register_post_type( 'themes', $args );//max 20 charachter cannot contain capital letters and spaces

There are few things you have to remember while registering custom post. change the has_archive parameter to custom post type slug name and another is change the rewrite slug name as 'slug' => 'custom_post_type_slug/%taxonomy_slug%

Now when you add a new post type in the write post type page... you will see the permalink as http://www.example.com/wordpress/themes/%themes_categories%/post-name/. If the custom taxonomy for this post is not selected then the permalink will remain http://www.example.com/wordpress/themes/%themes_categories%/post-name/ which will then show a bad request. To correct this we create a default term in the custom taxonomy. (same as uncategorized in categories) Add this to functions.php

function default_taxonomy_term( $post_id, $post ) {
    if ( 'publish' === $post->post_status ) {
        $defaults = array(
            'themes_categories' => array( 'other'),   //

        $taxonomies = get_object_taxonomies( $post->post_type );
        foreach ( (array) $taxonomies as $taxonomy ) {
            $terms = wp_get_post_terms( $post_id, $taxonomy );
            if ( empty( $terms ) && array_key_exists( $taxonomy, $defaults ) ) {
                wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy );
add_action( 'save_post', 'default_taxonomy_term', 100, 2 );

Now when the custom taxonomy is left blank the permlaink becomes http://www.example.com/wordpress/themes/other/post-name/ automatically.

At last don't forget to flush the rewrite by clicking on save changes in permalink setting in admin section otherwise you will be redirected to 404 error. Hope this helps you.

  • Hey, I had a problem... when we output the link to the taxonomy archive using the echo get_the_term_list( $post->ID, $taxonomy, '', ', ', '' ); then the link appears as www.example.com/taxonomy-term and not www.example.com/themes/taxonomy-term. I think we need to write a HTACESS rule for it. – Saurabh Goel Jul 6 '12 at 13:49
  • +1, great explanation, followed step by step and it works, tested on WordPress 3.4.2 – Alex Vang Oct 23 '12 at 19:27
  • 1
    I was wondering: do you have to add custom taxonomy to the array of taxonomies when registering a custom post type? Because it seems to be working without adding it there also (if you register a taxonomy to the custom post type already). Just curious. – trainoasis Mar 8 '17 at 7:52
  • Tried this with CPT UI plugin while still using your rewrite to change the URL. All looks good. the URLs are all correct and I reset permalinks, but the actual posts are throwing a 404. :( EDIT: nevermind. I went through and removed Hierarchical from the taxonomy and also made sure to save things in the proper order, and now the posts seem to work. Yah! – Garconis May 17 '18 at 19:53

i.e. register a custom taxonomy MY_NEW_CARSS for custom post types:

$my_taxon_name  = 'MY_NEW_CARSS';
$my_post_types  = array('SUB_CAT_1','SUB_CAT_2','SUB_CAT_3');

//REGISTER CUSTOM TAXONOMY ( http://codex.wordpress.org/Function_Reference/register_taxonomy )
//If you aim to register HIERARCHICAL(Parent-ed) post type, read this warning: https://codex.wordpress.org/Function_Reference/register_post_type#hierarchical
add_action( 'init', 'my_f32' ); function my_f32() { 
    register_taxonomy( $GLOBALS['my_taxon_name'], array(), 
            'label'=>$GLOBALS['my_taxon_name'],     'public'=>true, 'show_ui'=>true,  'show_admin_column'=>true,   'query_var'=>true,
            'hierarchical'=>true,   'rewrite'=>array('with_front'=>true,'hierarchical'=>true),  

//REGISTER CUSTOM POST TYPE ( http://codex.wordpress.org/Function_Reference/register_post_type )
add_action( 'init', 'myf_63' );function myf_63() { 

    foreach ($GLOBALS['my_post_types'] as $each_Type)       {
            register_post_type( $each_Type, 
                    'label'=>$each_Type,     'labels' => array('name'=>$each_Type.' pagess', 'singular_name'=>$each_Type.' page'),        'public' => true,   'publicly_queryable'=> true,      'show_ui'=>true,      'capability_type' => 'post',      'has_archive' => true,      'query_var'=> true,     'can_export' => true,                   //'exclude_from_search' => false,     'show_in_nav_menus' => true,  'show_in_menu' => 'edit.php?post_type=page',//true,     'menu_position' => 5,
                    'hierarchical' =>true,
                    'supports' =>array( 'page-attributes', 'title', 'editor', 'thumbnail' ), 
                    'rewrite' => array('with_front'=>true, ),     //    'rewrite' => array("ep_mask"=>EP_PERMALINK ...) OR    'permalink_epmask'=>EP_PERMALINK, 

            register_taxonomy_for_object_type('category',$each_Type);       //standard categories
            register_taxonomy_for_object_type($GLOBALS['my_taxon_name'] ,$each_Type);   //Custom categories

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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