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.
<?php | |
/** | |
* 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', // https://developer.wordpress.org/resource/dashicons/ | |
); | |
register_post_type( 'testimonial', $args ); | |
} | |
add_action( 'init', 'be_register_testimonial_post_type' ); |
Labels
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.
Supports
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.
Rewrite
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.
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
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
array(
‘labels’ => array(
‘name’ => __( ‘Portfolio’ ),
‘singular_name’ => __( ‘Portfolio’ )
),
‘has_archive’ => true,
‘public’ => true,
‘rewrite’ => array(‘slug’ => ‘portfolio’),
)
);
}
I have seen this code here https://www.cloudways.com/blog/gutenberg-wordpress-custom-post-type/
Bill Erickson says
You need to add
'show_in_rest' => true
for Gutenberg to be used in that post type.Here’s the update to the code you posted: https://gist.github.com/billerickson/7c832b543ff14eb492025908427757d6
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.
Jesús
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.