Using Custom Post Types

A WordPress website can contain multiple content types, known as “post types” in the WordPress world. The default post types are “Post” and “Page”, but you can create your own custom post types.

On my website I’ve created a Code Snippets post type and a Projects post type. This simplifies the content creation process by grouping different types of content in the backend, and lets you have dynamic archives. I can customize the edit screen with Custom Metaboxes and Taxonomies.

Registering a post type

In your core functionality plugin, use the register_post_type() function to create a post type.

* Register the Testimonial post type
function be_register_testimonial_post_type() {
$labels = array(
'name' => 'Testimonials',
'singular_name' => 'Testimonial',
'add_new' => 'Add New',
'add_new_item' => 'Add New Testimonial',
'edit_item' => 'Edit Testimonial',
'new_item' => 'New Testimonial',
'view_item' => 'View Testimonial',
'search_items' => 'Search Testimonials',
'not_found' => 'No Testimonials found',
'not_found_in_trash' => 'No Testimonials found in Trash',
'parent_item_colon' => 'Parent Testimonial:',
'menu_name' => 'Testimonials',
$args = array(
'labels' => $labels,
'hierarchical' => false,
'supports' => array( 'title', 'editor', 'thumbnail' ),
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_rest' => true,
'publicly_queryable' => true,
'exclude_from_search' => false,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => array( 'slug' => 'testimonials', 'with_front' => false ),
'menu_icon' => 'dashicons-groups', //
register_post_type( 'testimonial', $args );
add_action( 'init', 'be_register_testimonial_post_type' );
view raw post-type.php hosted with ❤ by GitHub

The labels parameter lets you customize all the labels used throughout the WordPress backend. It’s usually as simple as find/replacing the plural and singular forms of the post type, but you may want to tweak some of the other labels more extensively.


The supports parameter lets you specify which WordPress features should be enabled for this post type. Options:

  • ‘title’
  • ‘editor’ (content)
  • ‘author’
  • ‘thumbnail’ (featured image, current theme must also support post-thumbnails)
  • ‘excerpt’
  • ‘trackbacks’
  • ‘custom-fields’
  • ‘comments’ (also will see comment count balloon on edit screen)
  • ‘revisions’ (will store revisions)
  • ‘page-attributes’ (menu order, hierarchical must be true to show Parent option)
  • ‘post-formats’ add post formats, see Post Formats
Show in REST

The show_in_rest parameter lets you decide if this post type should be visible in the REST API. This must be set to true if you’d like to use the new Gutenberg block editor

Has Archive

The has_archive parameter enables the post type archive, a dynamic archive listing recent content in this post type.


The rewrite parameter lets you enable and customize the URL rewriting for this content type.

Menu Icon

The menu_icon parameter lets you specify a Dashicon to use as the icon in the admin area.

Using a plugin

Rather than coding it yourself, you can use Custom Post Type UI to create and manage your custom post types. The plugin lets you specify the post type slug, labels, and settings shown above.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson


  1. Hans says

    Hi Bill,

    I’ve been reading a lot of your posts lately with growing appreciation for the clarity and willingness to help and share that you demonstrate here. I am a gratefull for the opportunity to learn from such an expert. I begin to understand more and more of how wp works and can be handled. There’s a lot to know and learn. So thanks for the clarification you offer and the related sources you point to. Some great articles here.

    At the moment I use genesis/studiopress themes and have only made some slight adjustments with help of snippets and documentation.

    Now I want to add to my website, functions like a shop and payed courses, and I’ve been looking at cpt’s. Reading the codex and your article, making a cpt seems not that difficult, reducing the need to use extra plugins. But in my case I also want visitors to be able to submit a custom post (entering custom fields data) in a form at the frontend.

    I’m not sure about how to do that, except for using more advanced plugins like wp-types / toolset that seems to have it all (especially combined with beaver builder), but I’m a bit worried that such a combo could be too heavy for a shared server and that pageload would skyrocket. Would you advise for such a combination? If not, why not?

    You did mention ACF in another post and said you use that sometimes in projects, but not to present custom field data in the frontend. I guess that plugin could be used to add the custom fields to the cpt, but I then still need a form plugin that can submit the data on the frontend and save it in the cpt and cf. Could Gravity Forms be sufficient for that in combination with acf?

    I would appreciate any pointer to what option could be feasible/advisable. The solution has to run on a well managed ssd shared hosting plan (2 cores).

    Thanks, Hans

    • Bill Erickson says

      I recommend using a form plugin, then on submission using the form data to create a post in your custom post type. You can either code this second part yourself (I’ll be posting a tutorial in the next week or two about doing this with WPForms), or use Gravity Forms and the Custom Post Types AddOn.

      • Hans says

        Great, I’m looking forward to reading that article. 🙂

        I’m using the free version of NinjaForms now (as was advised by StudioPress), but will probably upgrade to a premium forms plugin like Gravity Forms soon and WPForms is looking good too. So I will wait for your article on that. With my current knowledge and skillset the help of some well-build and maintained plugins seems inevitable.

        I understand implicitly you don’t advise using solutions like wp-types toolset, and just use php and wordpress and perhaps acf to build and present cpt’s with cf’s. I hope I will be able to pull it of with help of your articles and pointers.

        Thanks, Hans

  2. Alvina says

    I am trying to enable Gutenberg editor for custom post types and having an error. Can you help me resolve this error? I am having in this line of code

    register_post_type( ‘portfolio’,
    // WordPress CPT Options Start
    ‘labels’ => array(
    ‘name’ => __( ‘Portfolio’ ),
    ‘singular_name’ => __( ‘Portfolio’ )
    ‘has_archive’ => true,
    ‘public’ => true,
    ‘rewrite’ => array(‘slug’ => ‘portfolio’),


    I have seen this code here

  3. Jesús Yesares says

    Hi Bill,

    thank you very much for your article.

    When I create a custom post type in Genesis Framework, the Genesis button on the top right of the Gutenberg editor does not appear.

    Do you know why? Is it possible to show this button?

    Thanks again.


    • Bill Erickson says

      Looking at the Genesis theme code, it looks like the Genesis editor sidebar will only appear if the post type supports custom-fields.