How to create Custom Post Types in WordPress

I’ve been working on a game database that’s powered by a vanilla WordPress instance. For the project it made sense to create a new post type (game), as well as a custom taxonomy (platform). I didn’t want to use a plugin and instead opted to create the new post type as part of the child theme’s function.php file.

Here’s how I did it.

The Custom Post Type (Game)

Let’s take a look at the code for the custom post type first. We’ll assume we’re going to use the built-in taxonomies for now (Tags and Categories), so that it works just like a regular post. The only difference is that we’ll have a new menu item just for Games in the admin menu, like this:

The code to make that happen looks like this:

// Create a custom GAME Post Type
function create_game_posttype() {

// create out custom post type
register_post_type( 'games',
// with these options
'labels' => array(
'name' => __( 'Games' ),
'singular_name' => __( 'Game' )
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'game'),
'show_in_rest' => true,


// register our post type with tags and categories
register_taxonomy_for_object_type ('category', 'games');
register_taxonomy_for_object_type ('post_tag', 'games');

// initialise on theme setup
add_action( 'init', 'create_game_posttype' );

This function creates the Game post type, gives it the relevant labels (for the admin menu), and adds both default WordPress taxonomies to it (namely categories and tags). This happens in the last step before the function is called via the init hook. There are plenty more parameters you can set, as outlined in the documentation.

The Custom Taxonomy (Platform)

I thought it might be nice to a have a completely different taxonomy system in my game database, namely one that would allow me to categories my games by platform. This would be something like PS3, PS4, GameCube or PC. Ideally this taxonomy would work like the regular categories and allow parenting as well, so we can have a marketplace like Steam or GOG parented to the PC Platform.

The following code makes that happen:

// create custom "Platform" taxonomy
function create_platform_tax() {
// Add new taxonomy, make it hierarchical (like categories)
$labels = array(
'name' => _x( 'Platforms', 'taxonomy general name', 'textdomain' ),
'singular_name' => _x( 'Platform', 'taxonomy singular name', 'textdomain' ),
'search_items' => __( 'Search Platforms', 'textdomain' ),
'all_items' => __( 'All Platforms', 'textdomain' ),
'parent_item' => __( 'Parent Platform', 'textdomain' ),
'parent_item_colon' => __( 'Parent Platform:', 'textdomain' ),
'edit_item' => __( 'Edit Platform', 'textdomain' ),
'update_item' => __( 'Update Platform', 'textdomain' ),
'add_new_item' => __( 'Add New Platform', 'textdomain' ),
'new_item_name' => __( 'New Platform Name', 'textdomain' ),
'menu_name' => __( 'Platform', 'textdomain' ),

// show_in_rest makes this thing show up in the post editor
$args = array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'platform' ),
'show_in_rest' => true,

register_taxonomy( 'platform', array( 'games' ), $args );
// initialise on theme setup
add_action( 'init', 'create_platform_tax' );

This looks a little more complex, only because we have to setup all the labels for the admin area. It’ll look just like the one that lets us amend the default Categories (under Posts), except now it’ll be a whole new menu (Platform) available under Games. The “textdomain” placeholder above is for potential translations.

All these and other parameters are explained in the documentation. There’s one undocumented peculiarity that I’ve noticed: the selection box for taxonomies does not show up, unless we set the “show_in_rest” parameter to true. When left to false, those boxes on the right hand side when you write a custom post might not reveal themselves. Go figure.

Adding Platform to Games

Once created, we need to add our custom taxonomy to our custom post type. We’ve already done this above with the regular default taxonomies, which we can now remove (or leave in place, depending on our needs). We do that with the register_taxonomy_for_object_type() function, which is documented here.

The last line in this code will take care of it (we’ve seen the other two lines in the register_post_type() function above):

// regsiter our post type with tags and categories
register_taxonomy_for_object_type ('category', 'games');
register_taxonomy_for_object_type ('post_tag', 'games');
register_taxonomy_for_object_type ('platform', 'games');

And that’s it! Some would argue it’s super easy, but as it is with many such things, I was missing several key pieces of the puzzle to make this work. I hope this guide will help get your custom post type projects off the ground.

You can leave a comment on my original post.