How to Register a Custom Post Type (CPT) with register_post_type() in WordPress
Custom Post Types (CPTs) let you go beyond standard posts and pages in WordPress. They’re useful for organizing different kinds of content like portfolios, testimonials, products, or events. WordPress provides the register_post_type() function to create them. Here’s how you can register and configure a CPT the right way.
1. Basic Example
Add the following code to your theme’s functions.php file or a custom plugin:
<?php
function my_register_portfolio_cpt() {
$args = array(
'labels' => array(
'name' => __( 'Portfolios' ),
'singular_name' => __( 'Portfolio' ),
),
'public' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'portfolio' ),
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
'show_in_rest' => true, // Enables Gutenberg and REST API
);
register_post_type( 'portfolio', $args );
}
add_action( 'init', 'my_register_portfolio_cpt' );
?>
This registers a new post type called Portfolio that supports the editor, featured images, and excerpts, and appears at yoursite.com/portfolio/.
2. Adding Labels for Better UI
To make your CPT more user-friendly, define a full set of labels:
<?php
function my_register_event_cpt() {
$labels = array(
'name' => __( 'Events' ),
'singular_name' => __( 'Event' ),
'add_new' => __( 'Add New Event' ),
'add_new_item' => __( 'Add New Event' ),
'edit_item' => __( 'Edit Event' ),
'new_item' => __( 'New Event' ),
'all_items' => __( 'All Events' ),
'view_item' => __( 'View Event' ),
'search_items' => __( 'Search Events' ),
'not_found' => __( 'No events found' ),
'not_found_in_trash' => __( 'No events found in Trash' ),
'menu_name' => __( 'Events' ),
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-calendar-alt',
'rewrite' => array( 'slug' => 'events' ),
'supports' => array( 'title', 'editor', 'thumbnail', 'custom-fields' ),
'show_in_rest' => true,
);
register_post_type( 'event', $args );
}
add_action( 'init', 'my_register_event_cpt' );
?>
This creates an Events post type with its own menu icon and archive page.
3. Common register_post_type() Arguments
public– Controls visibility (true for front-end and admin).has_archive– Enables an archive page (e.g.,/events/).rewrite– Defines the URL slug.supports– Features available:title,editor,thumbnail,excerpt,custom-fields.show_in_rest– Enables the block editor and REST API support.menu_icon– Dashicon for the admin menu (e.g.,dashicons-admin-users).capability_type– Custom capabilities for advanced permissions.
4. Flushing Rewrite Rules
After registering a new CPT, you may need to refresh permalinks:
- Go to Settings → Permalinks.
- Click Save Changes (no need to modify anything).
- This flushes rewrite rules so your new CPT URLs work properly.
5. Summary
- Use
register_post_type()inside aninithook to create CPTs. - Define labels for better admin UI.
- Configure
supports,rewrite, andshow_in_restas needed. - Flush permalinks after adding a new post type.
With register_post_type(), you can organize your WordPress site into structured, custom content types tailored to your needs.
🎨 Want to learn more? Visit our WordPress Customization Hub for tips and advanced techniques.