Custom Post Types & Taxonomies
While Posts and Pages cover many use cases, custom post types (CPTs) and taxonomies let you create dedicated content structures for Products, Testimonials, Portfolio Items, Events, and more. CPTs define the content type; Taxonomies define how to group and classify that content.
Prerequisites
- Understanding of WordPress hooks (init action)
- Access to theme functions.php or custom plugin
- Clear content structure requirements
Step-by-Step Guide
Understand Posts vs Taxonomies
Post Types define the TYPE of content (the "thing")
Core examples: Posts, Pages, Attachments, Revisions
Custom examples: Products, Portfolio Items, Testimonials, Events
Taxonomies define ways to GROUP and CLASSIFY content
Core examples: Categories, Tags
Custom examples: Genre, Location, Skill, Color
Register a Custom Post Type
Use register_post_type() hooked to the init action
First parameter: post type slug (lowercase, no spaces, max 20 chars)
Second parameter: array of arguments defining behavior
Key arguments: labels, public, has_archive, supports, rewrite
// Register "Book" Custom Post Type
add_action( 'init', 'create_book_post_type' );
function create_book_post_type() {
$labels = array(
'name' => 'Books',
'singular_name' => 'Book',
'menu_name' => 'Books',
'add_new' => 'Add New Book',
'add_new_item' => 'Add New Book',
'edit_item' => 'Edit Book',
'new_item' => 'New Book',
'view_item' => 'View Book',
'search_items' => 'Search Books',
'not_found' => 'No books found',
'not_found_in_trash' => 'No books found in trash',
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true, // Enable Gutenberg editor
'has_archive' => true, // Creates /books/ archive page
'rewrite' => array( 'slug' => 'books' ),
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
'menu_icon' => 'dashicons-book-alt',
);
register_post_type( 'book', $args );
}Key CPT Arguments Explained
labels: Array of UI text for admin screens (required for good UX)
public: true = visible to authors and public (most common)
has_archive: true = creates archive page at /your-slug/
supports: Array of features - title, editor, thumbnail, excerpt, custom-fields, etc.
rewrite: Controls URL structure - set slug for SEO-friendly URLs
show_in_rest: true = enables Gutenberg block editor and REST API access
menu_icon: Dashicon class or URL for admin menu icon
Register a Custom Taxonomy
Use register_taxonomy() hooked to init action
First param: taxonomy slug; Second: post type(s) it applies to; Third: args array
Key choice: hierarchical (like Categories) or non-hierarchical (like Tags)
// Register "Genre" Taxonomy for Books
add_action( 'init', 'create_book_taxonomies' );
function create_book_taxonomies() {
// Hierarchical taxonomy (like Categories)
$genre_labels = array(
'name' => 'Genres',
'singular_name' => 'Genre',
'search_items' => 'Search Genres',
'all_items' => 'All Genres',
'parent_item' => 'Parent Genre',
'parent_item_colon' => 'Parent Genre:',
'edit_item' => 'Edit Genre',
'update_item' => 'Update Genre',
'add_new_item' => 'Add New Genre',
'new_item_name' => 'New Genre Name',
'menu_name' => 'Genres',
);
register_taxonomy( 'genre', 'book', array(
'labels' => $genre_labels,
'hierarchical' => true, // Like Categories (parent/child)
'public' => true,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'genre' ),
));
// Non-hierarchical taxonomy (like Tags)
register_taxonomy( 'book_tag', 'book', array(
'labels' => array(
'name' => 'Book Tags',
'singular_name' => 'Book Tag',
),
'hierarchical' => false, // Like Tags (flat)
'public' => true,
'show_in_rest' => true,
'rewrite' => array( 'slug' => 'book-tag' ),
));
}Create Templates for Your CPT
WordPress automatically looks for CPT-specific templates
Single view: single-book.php (falls back to single.php)
Archive view: archive-book.php (falls back to archive.php)
Taxonomy archive: taxonomy-genre.php or taxonomy-genre-fiction.php
Create these files in your child theme to customize display
Verification Checklist
- Custom Post Type appears in WordPress admin menu
- Can add new items with all supported features
- Archive page works at the configured slug
- Custom taxonomy appears in CPT edit screen
- Gutenberg editor works (show_in_rest is true)
- Permalinks are clean after saving Settings > Permalinks
Pro Tips
- Always set show_in_rest => true for Gutenberg compatibility
- Use a plugin like Custom Post Type UI (CPT UI) for GUI-based registration
- Register CPTs in a plugin (not theme) if content should persist across theme changes
- Flush rewrite rules after any changes (save permalinks or wp rewrite flush)
- Use register_post_type_args filter to modify CPT registered by plugins