How to Create WordPress Custom Post Type

In this tutorial we are going to learn how to create custom post type in WordPress in an easy and simple way. No reason to think custom post type is hard and difficult to learn but instead let say “Hurray, I finally found out how to create custom post type for my great website in less than 30 minutes”.

Don’t worry, in this tutorial I will explain every steps as clear as possible so after reading this tutorial you can practice it your self.

The Questions

  • What is custom post type?
  • Why custom post type?
  • When we use custom post type?
  • Where custom post type can be optimal for use ?
  • How many post types we can have in WordPress based site?

You might ask “What makes custom post type so special?”.

Just like common type “post”, custom post type is :
  • still act as posts
  • by default do not display on common archive
  • by default do not appear on feed
  • can have its own permalink
  • can have its custom hierarchy
  • can have custom menu display on admin menu
  • and many thing you can do with them

In short, custom post type is like combination between type “pages” and “post” but you can customized it.

Let’s Start Playing with Custom Post Type

Let say we have a restaurant with a lot of food recipes from all over the world. Can it be done with common “post” ? Sure, but in this condition we want specific layout display and more organized besides the food recipes display side by side with restaurant news article.

We are going to create custom post type for our restaurant and named it “recipes” (without quotes off course). You can put the codes on your theme’s functions.php file.

1. Register our custom post type (make it integrated with WordPress post system)

[php]register_post_type( ‘recipes’, $recipes_args );[/php]

2.  Define GUI options to display on Add / Edit post

$recipe_labels = array(
‘name’ => ‘Recipes’,
‘singular_name’ => ‘Recipes’,
‘menu_name’ => ‘Recipes’,
‘add_new’ => ‘Add Recipes’,
‘add_new_item’ => ‘Add New Recipes’,
‘edit’ => ‘Edit’,
‘edit_item’ => ‘Edit Recipes’,
‘new_item’ => ‘New Recipes’,
‘view’ => ‘View Recipes’,
‘view_item’ > ‘View Recipes’,
‘search_items’ > ‘Search Recipes’,
‘not_found’ => ‘No Recipes Found’,
‘not_found_in_trash’ => ‘No Recipes Found in Trash’,
‘parent’ => ‘Parent Recipes’,

3. Define hierarchy and permalink

$recipe_args = array(
‘labels’ => $recipe_labels,
‘description’ => ‘put description for this recipes custom post type’,
‘public’ => true,
‘show_ui’ => true,
‘show_in_menu’ => true,
‘capability_type’ => ‘post’,
‘hierarchical’ => false,
‘rewrite’ => array(‘slug’ => ‘recipe-name’),
‘query_var’ => true,
‘supports’ => array(‘title’,’editor’,’excerpt’,’custom-fields’,’thumbnail’),
‘menu_position’ => 5,
‘has_archive’ => true,

Up to this point our post type have been defined and registered, but still have no hierarchy or taxonomy.

4. Register taxonomy label (again make it integrated )

//register recipe taxonomy category
register_taxonomy( ‘recipe-type’, array( ‘recipe’ ), $taxonomy_recipe_category_args );

5. Define taxonomy label for custom post type

$taxonomy_recipes_category_labels = array(
‘name’ => ‘Recipes Types’,
‘singular_name’ => ‘Recipes Types’,
‘search_items’ => ‘Search Recipes Types’,
‘popular_items’ => ‘Popular Recipes Types’,
‘all_items’ => ‘All Recipes Types’,
‘parent_item’ => ‘Parent Recipes Type’,
‘parent_item_colon’ => ‘Parent Recipes Type:’,
‘edit_item’ => ‘Edit Recipes Type’,
‘update_item’ => ‘Update Recipes Type’,
‘add_new_item’ => ‘Add New Recipes Type’,
‘new_item_name’ => ‘New Recipes Type Name’,
‘separate_items_with_commas’ => ‘Separate recipe type with commas’,
‘add_or_remove_items’ => ‘Add or remove recipe types’,
‘choose_from_most_used’ => ‘Choose from the most used recipe types’,
‘menu_name’ => ‘Recipes Types’,

6. Define action options for taxonomy label

$taxonomy_recipe_category_args = array(
‘labels’ => $taxonomy_recipe_category_labels,
‘public’ => true,
‘show_ui’ => true,
‘hierarchical’ => true,
‘rewrite’ => array( ‘slug’ => ‘recipe-type’ ),
‘query_var’ => true,
‘singular_label’ => ‘Recipe Type’,

Finally, our custom post type have all requirements.

Breaking Down the Codes

Now that we have all the codes written, you probably wondering what on earth was those codes.

Fear not, I’m going to explain every bit of the above codes for you.

Step 1

On this step we define our custom post type name and for this example we name it “recipes”.

You can name it  with anything but just for suggestion make the name for custom post type simple and meet the purpose.

Step 2

We are defining how custom post type will look when we  add or edit or viewing archives of recipe post type (see screenshot for more detail).

Recipes Post Type

Step 3

On this step we can customizing how the custom post type action.

‘labels’  : Contain array from the step 1 ( $recipes_label )

‘description’ : ‘put description for this recipes custom post type’, : Optional post type description

‘public’ => true  : If we want to display this post type in admin UI.

‘show_ui’ => true, :  Display a user-interface for this post type

‘show_in_nav_menus’ => true,  : Whether post_type is available for selection in navigation menus

‘capability_type’ => ‘post‘, The post type to use for checking read, edit, and delete capabilities

‘hierarchical’ => false : Whether the post type is hierarchical. Allows parent to be specified (default is false)

‘rewrite’ => array(‘slug’ => ‘recipe-name’),  : Rewrite permalinks with this format (in this example the single custom post type will have slug ‘recipe-name’ – without quotes)

‘query_var’ => true :  Name of the query var to use for this post type

‘supports’ => array(‘title’,’editor’,’excerpt’,’custom-fields’,’thumbnail’)  : An alias for calling add_post_type_support() directly, by default is only title and editor.

In this example, the recipes custom post type that we made will have excerpt box, custom-fields box, and featured image as additional.

Need more options?

Don’t worry we can add more like : author, trackbacks, comment, revisions, and page-attribute.

‘menu_position’ => 5,  : Custom post type menu position. A little tips on menu position:

  •  5 – below Posts menu
  • 10 – below Media menu
  • 20 – below Pages menu

‘has_archive’=> true, : Will enables post type archives that displays all the items under corresponding post type.

For more options, WordPress Codex have reference in Function Reference : Register Post Type

Step 4

In this step we play with taxonomy hierarchy.

[php]register_taxonomy( ‘recipe-type’, array( ‘recipes’ ), $taxonomy_recipe_category_args );[/php]

Our taxonomy is defined as ‘recipe-type’ and as part of custom post type ‘recipes’ (see code right above).

Step 5

We arranged how the taxonomy admin panel UI look like. I believe it’s easier to explain with a screenshot.

Recipe Types

Step 6

On this step, we made optional arguments for taxonomy label.

‘labels’ => $taxonomy_recipe_category_labels, : This label variable is array taken from Step 5.

 ‘public’ => true : Option to display this taxonomy label in the admin UI

‘show_ui’ => true : Display a user-interface (admin panel) for this taxonomy

‘hierarchical’ => true : If we want to make the taxonomy hierarchical. Allows Parent to be specified

‘rewrite’ => array( ‘slug’ => ‘recipe-type’ ) : The permalink way for the taxonomy will have slug ‘recipe-type’. You can change it with other, just make sure to refresh / re-save the settings on Setting -> Permalinks

‘query_var’ => true : Name of the query var to use for this post type, (by default is true).

‘singular_label’ => ‘Recipe Type’ : name for one object of this taxonomy. Defaults to value of name

Further information can see Function Reference Register Taxonomy

Display Custom Post Type in Front End

To this point we have defined and registered our recipes post type easily, and now it’s time to make it real. Be ready, the following will need more attention and very seriously (just kidding, trust me it will be easy steps )

According to WordPress Template Tags guide, for single post item is displayed using single.php or single-postname.php template file.

But how about single post for custom post type?

You just need to make a file named single-custom-post-type-name.php. Based on our tutorial, our single post template file for for recipes post type is single-recipes.php

To test if it’s working, just copy single.php file of Twenty Eleven or Twenty Ten theme to your current theme folder that you use for this tutorial and rename it to single-recipes.php.

For displaying all archives for recipes post type you just need to create, a file named taxonomy-recipes.php and it will use something query arguments like WP_Query. Here’s a simple example of the archive page:

<?php get_header(); ?>

<div id=”wrapper”>
<div class=”inner”>
<ul class=”posts”>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<h3 class=”title”><a href=”<?php the_permalink() ?>” title=”<?php echo get_the_title(); ?>”><?php the_title(); ?></a></h3>
<div class=”the-content”>
<?php the_content(); ?>
<?php endwhile; ?>

<div class=”navigation clearfix”>
<?php previous_posts_link( __(‘&laquo; Previous’, ‘warrior’) ); ?>
<?php next_posts_link( __(‘Next &raquo;’, ‘warrior’) ); ?>
<?php endif; ?>
<?php get_footer(); ?>

That’s all for your tutorial. If you have any feedback don’t hesitate to leave a comment :).