How to Create a Custom Taxonomy in WordPress

Registering a custom taxonomy and linking it to a post type

WordPress has two built-in taxonomies: Categories (hierarchical) and Tags (flat). Custom taxonomies work the same way but belong to whichever post types you choose — ideal for organising portfolio items by technique, products by brand, or events by venue.

Problem: How do you register a custom taxonomy in WordPress and attach it to a specific post type?

Solution: The example below registers a hierarchical genre taxonomy for a book custom post type:

add_action( 'init', 'register_genre_taxonomy' );

function register_genre_taxonomy() {
    $labels = [
        'name'              => __( 'Genres',       'textdomain' ),
        'singular_name'     => __( 'Genre',        'textdomain' ),
        'search_items'      => __( 'Search Genres', 'textdomain' ),
        'all_items'         => __( 'All Genres',   'textdomain' ),
        'parent_item'       => __( 'Parent Genre', 'textdomain' ),
        'parent_item_colon' => __( 'Parent Genre:', 'textdomain' ),
        'edit_item'         => __( 'Edit Genre',   'textdomain' ),
        'update_item'       => __( 'Update Genre', 'textdomain' ),
        'add_new_item'      => __( 'Add New Genre', 'textdomain' ),
        'new_item_name'     => __( 'New Genre Name', 'textdomain' ),
        'menu_name'         => __( 'Genres',       'textdomain' ),
    ];

    register_taxonomy( 'genre', [ 'book' ], [
        'labels'            => $labels,
        'hierarchical'      => true,     // true = like categories, false = like tags
        'public'            => true,
        'show_ui'           => true,
        'show_in_rest'      => true,
        'rewrite'           => [ 'slug' => 'genre' ],
    ] );
}

To assign terms to a post programmatically:

// Assign by term slug
wp_set_object_terms( $post_id, [ 'fiction', 'thriller' ], 'genre' );

// Get assigned terms
$terms = get_the_terms( $post_id, 'genre' );

NOTE: Register the taxonomy before the post type if you want them linked from the start. After adding a new taxonomy, visit Settings → Permalinks and click Save to flush the rewrite rules.