WordPress Custom Post Types and How To Create Your Own

WordPress post types are the bread and butter of the entire WordPress platform. Posts, pages, menu items, attachments, and even custom CSS (from the customizer) are examples of post types that come with a default installation of WordPress.

When would I use a custom post type?

Suppose you want to have a page to show team members name and bio.

You would create a custom post type specifically for team members and have your own dedicated menu item for managing them.

Below is a simple example of a custom post type for team members:

function create_team_member_post_type() {
  register_post_type( 'team_member',
    array(
      'labels' => array(
        'name' => __( 'Team Members' ),
        'singular_name' => __( 'Team Member' )
      ),
      'public' => true
    )
  );
}
add_action( 'init', 'create_team_member_post_type' );

Go ahead and add the code above to your themes functions.php file and refresh the page. Notice that there is now a Team Members menu item on the left.

Let’s go over the function register_post_type() — the function that’s responsible for registering custom post types.

Registering a custom post type in WordPress:

<?php register_post_type( $post_type, $args ); ?>

$post_type – A name for the post type in string format, no capital letters or spaces.

  • In our example we used team_member for the post type

$args – an array of arguments.

  • labels – (array) containing the singular and plural names of the custom post type. In the example above, we used Team Member and Team Members respectively.
  • public – (boolean) true or false value indicating whether or not this post type is public or private. In the example above, we used true because it will display a menu item on the left side of the dashboard for this post type.

For a complete reference on register_post_type() click here.

Adding New Custom Posts

Let’s add a few team members by clicking on Add New and entering in some random people.

Once you have some team members created how can we verify that the custom post type is actually working? The archive page of course!

Custom Post Type Archives

Depending on your permalink setup, the default URL to access post type archives is the name used when registering the custom post type.

In order for archives to be enabled for our team member custom post type, we have to specify that we want them enabled in the arguments we passed when we first created the custom post type.

To do this, we’re going to add an additional argument called has_archive to our code and set it to true.

function create_team_member_post_type() {
  register_post_type( 'team_member',
    array(
      'labels' => array(
        'name' => __( 'Team Members' ),
        'singular_name' => __( 'Team Member' )
      ),
      'public' => true,
      'has_archive' => true
    )
  );
}
add_action( 'init', 'create_team_member_post_type' );

In our example, we registered the team member post type using the name team_member and as such, we should be able to view the archives by visiting /team_member.

Adding a Featured Image to a Custom Post Type

Let’s expand on our team member custom post type by adding in support for assigning a featured image to each team member.

We can either modify the arguments passed to the register_post_type() function by passing a supports array containing the features we would like to enable for this custom post type, or we can pass an array to the add_post_type_support() function to specify title, editor, and thumbnail support.

Method 1: Modify the arguments

Let’s add a supports argument to our register_post_type() function and specify title, editor, and thumbnail support. This will give our custom post type support for a title, a content editor, and a featured image.
Click here for a full reference on the supports argument

function create_team_member_post_type() {
  register_post_type( 'team_member',
    array(
      'labels' => array(
        'name' => __( 'Team Members' ),
        'singular_name' => __( 'Team Member' )
      ),
      'public' => true,
      'has_archive' => true,
      'supports' => array('title','editor','thumbnail')
    )
  );
}
add_action( 'init', 'create_team_member_post_type' );

Method 2: Add post type support

This method involves using the add_post_type_support() function to register support of certain features.

function create_team_member_post_type() {
  register_post_type( 'team_member',
    array(
      'labels' => array(
        'name' => __( 'Team Members' ),
        'singular_name' => __( 'Team Member' )
      ),
      'public' => true,
      'has_archive' => true
    )
  );

  add_post_type_support('team_member', array('title', 'editor', 'thumbnail'));
}
add_action( 'init', 'create_team_member_post_type' );

Now you’ll notice a Featured Image meta box on the right side of the editor when you edit a team member. Here you can upload a photo of the them to display along with their bio on the archive pages.

What’s next?

Advanced users can create a template file called archive-team_member.php and customize the output of the team member archives page completely. Just make sure you copy your themes existing archive.php and modify it accordingly.