This article was originally published on this site


If you use WordPress on a daily basis, then you are probably familiar with commonly used post types such as posts and pages. However, there are times when you might want to break things down into separate categories or templates, and that is where custom post types come into play.

Custom post types help to extend and organize your site, and allow you to more easily scale your WordPress site. From press releases to case studies, or even a database of artists. Custom post types can be used for all sorts of different things.

One of the problems though is they aren’t always the easiest thing to set up. Typically developers are the ones that configure custom post types for a site. But that doesn’t have to be the case.

Below I’ll walk you through a couple of easy ways to set up a basic custom post type (CPT), as well as fixing the slug and enabling it to work in the WordPress block editor.

Examples of Custom Post Types and Usage

I thought it might help if you could see some examples of custom post types being used on live sites. So here are a couple.

Food and Menus Example

On our No Gluten site, we have different gluten-free foods lists as well as gluten-free restaurants and fast food places. Each of these has its own custom post type. You can click into “Menus” and add a new post, just like you would with a standard blog post.

Custom post type with food and menus

Custom post type with food and menus

Custom post type with food and menus

The difference is that these don’t appear on the blog. We already a blog section on our site. This allows us to completely customize a separate template for these types of posts. As you can see below, we have built a directory using the custom post types.

Custom post type with custom template

Custom post type with custom template

Custom post type with custom template

You can then build out different types within a custom post type. These are similar to how categories work with normal posts. So we have a menu type for fast food and one for restaurants.

A type within a custom post type

A type within a custom post type

A type within a custom post type

Coupon Example

Another example is with our WP Coupons plugin that you seeing powering our deals page on this site. Each coupon is simply a post underneath the “Coupons” custom post type. In this case, the custom post type is created automatically when you install and activate the plugin.

Coupon custom post type

Coupon custom post type

Coupon custom post type

Artist Example

One last example is from a new project that I’m working on about synthwave music. In the project, I’m creating a database of synthwave artists. So for this, it made logical sense to create a new “artist” custom post type in WordPress.

Artist custom post type

I then display the artists (CPT) automatically in alphabetical order on a page.

Artist custom post type in alphabetical order

Artist custom post type in alphabetical order

Artist custom post type in alphabetical order

How to Create a Custom Post Type

The first way you could go about creating a custom post type would be to simply use a plugin on the repository. However, I’m not a fan of installing additional plugins if I don’t have to. Especially if all that is needed is a separate custom post type without much customization.

If you want to go down the plugin route, here are a few plugins that can help:

Note: If you use one of the plugins above, some of the following steps below, like removing the slug, might not work.

I’m actually going to walk you through to create a custom post type manually with code. But don’t worry, you don’t need to be a developer to do this.

Step 1

The first step is to generate the code needed for your custom post type. I always use the handy online Post Type Generator tool from GenerateWP.

This allows you to easily change all the attributes and simply output the code in a few clicks. Here are a few attributes you will want to update:

  • name
  • singular_name
  • menu_name
  • name_admin_bar
  • slug
  • label
  • menu_icon (You can choose from any dashicon included in WordPress. Use one that is appropriate for your CPT.)

Here is the final code result. I’m using my “artist” custom post type as an example. So you will want to update this accordingly. I’ve also created a gist you can bookmark.

// Register Custom Post Type
function custom_post_type() {

        $labels = array(
                'name'                  => _x( 'Artists', 'Post Type General Name', 'text_domain' ),
                'singular_name'         => _x( 'Artist', 'Post Type Singular Name', 'text_domain' ),
                'menu_name'             => __( 'Artists', 'text_domain' ),
                'name_admin_bar'        => __( 'Artist', 'text_domain' ),
                'archives'              => __( 'Item Archives', 'text_domain' ),
                'attributes'            => __( 'Item Attributes', 'text_domain' ),
                'parent_item_colon'     => __( 'Parent Item:', 'text_domain' ),
                'all_items'             => __( 'All Items', 'text_domain' ),
                'add_new_item'          => __( 'Add New Item', 'text_domain' ),
                'add_new'               => __( 'Add New', 'text_domain' ),
                'new_item'              => __( 'New Item', 'text_domain' ),
                'edit_item'             => __( 'Edit Item', 'text_domain' ),
                'update_item'           => __( 'Update Item', 'text_domain' ),
                'view_item'             => __( 'View Item', 'text_domain' ),
                'view_items'            => __( 'View Items', 'text_domain' ),
                'search_items'          => __( 'Search Item', 'text_domain' ),
                'not_found'             => __( 'Not found', 'text_domain' ),
                'not_found_in_trash'    => __( 'Not found in Trash', 'text_domain' ),
                'featured_image'        => __( 'Featured Image', 'text_domain' ),
                'set_featured_image'    => __( 'Set featured image', 'text_domain' ),
                'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
                'use_featured_image'    => __( 'Use as featured image', 'text_domain' ),
                'insert_into_item'      => __( 'Insert into item', 'text_domain' ),
                'uploaded_to_this_item' => __( 'Uploaded to this item', 'text_domain' ),
                'items_list'            => __( 'Items list', 'text_domain' ),
                'items_list_navigation' => __( 'Items list navigation', 'text_domain' ),
                'filter_items_list'     => __( 'Filter items list', 'text_domain' ),
        );
        $rewrite = array(
                'slug'                  => 'artist',
                'with_front'            => true,
                'pages'                 => true,
                'feeds'                 => true,
        );
        $args = array(
                'label'                 => __( 'Artist', 'text_domain' ),
                'description'           => __( 'Post Type Description', 'text_domain' ),
                'labels'                => $labels,
                'supports'              => array( 'title', 'editor', 'thumbnail', 'comments', 'trackbacks', 'revisions', 'custom-fields', 'page-attributes', 'post-formats' ),
                'taxonomies'            => array( 'category', 'post_tag' ),
                'hierarchical'          => false,
                'public'                => true,
                'show_ui'               => true,
                'show_in_menu'          => true,
                'menu_position'         => 5,
                'menu_icon'             => 'dashicons-format-audio',
                'show_in_admin_bar'     => true,
                'show_in_nav_menus'     => true,
                'can_export'            => true,
                'has_archive'           => false,
                'exclude_from_search'   => false,
                'publicly_queryable'    => true,
                'rewrite'               => $rewrite,
                'show_in_rest' => true,
        );
        register_post_type( 'artist', $args );

}
add_action( 'init', 'custom_post_type', 0 );

Step 2

Next, you need to add the code to your WordPress site. As in a lot of my other posts, I always recommend using the free Code Snippets plugin for this. Then you don’t have to worry about losing any custom code when you update WordPress or your theme.

After adding the above code in a new snippet, you will then see your custom post type in the WordPress dashboard menu.

Custom post type in WordPress dashboard

Custom post type in WordPress dashboard

Custom post type in WordPress dashboard

Enable Block Editor Support

Most of you are now using the WordPress block editor. So you will want to make sure you enable support for it to work with your custom post type. This is already included in the snippet above, but I wanted to point this out. It is this line (gist):

'show_in_rest' => true,

Remove Base Slug from Custom Post Type URL

Out of the box, custom post types look like this:

domain.com/url/url

If you are like me, you probably prefer to remove the base slug from the URL for SEO purposes. Google generally prefers simple and short URLs.

domain.com/url

To remove the base slug, you can add another code snippet with the following (gist):

function na_remove_slug( $post_link, $post, $leavename ) {

    if ( 'artist' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;
    }

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'na_remove_slug', 10, 3 );

function na_parse_request( $query ) {

    if ( ! $query->is_main_query() || 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'artist', 'page' ) );
    }
}
add_action( 'pre_get_posts', 'na_parse_request' );

Enable Custom Post Type Preview

Next, you will want to add support for the preview window in the editor to work with the custom post type. Add another code snippet with the following (gist).

//adds custom post type query var to preview links
function mycptname_cpt_previow_query_vars($link, $post) {
        $custom_post_types = array('artist');
        if(in_array($post->post_type, $custom_post_types)) {
                return add_query_arg(['post_type' => $post->post_type], $link);
        }
        return $link;
}
add_filter('preview_post_link', 'mycptname_cpt_previow_query_vars', 10, 2);

Note: You can combine the above functions, I’m just showing them separately as it’s easier to see how everything is pieced together.

How to Display Custom Post Type on a Page

Last but not least, I’ll show you an easy way to display your custom post types. In some cases, you might want to create a separate template for the custom post type, but if you want something simple, the following works great.

Step 1

Download and install the free WP Show Posts plugin. This is developed by Tom Usborne, the developer of GeneratePress. So you can rest easy knowing it’s super lightweight. It’s actually quite powerful once you dive in and start using it.

Step 2

Next, create a new list and configure the settings. I’m using a simple list on my synthwave site in this example.

Posts

Under posts, make sure to change the post type to your new custom post type that you’ve created.

WP Show Posts with custom post type

Below are the screens and settings for the rest.

Columns

I’m using one column for now due to only having a few items. But if you have a lot of posts already, you could easily do a two, three, or four column layout which would fill out a page more.

Images

I remove the images as I want a simple list.

Content

I tweak the content to include the title.

Meta

I remove all the meta data attributes.

More Settings

You can sort the posts a lot of different ways. For mine, I wanted it to be alphabetical. So I changed the “Order” to ascending and the “Order by” to title.

Step 3

Then grab the shortcode from the sidebar of your list and enter it into the page where you want to list your custom post type.

You will then have a sorted list your new custom post type. As you publish new posts they will automatically appear.

Summary

The tutorial above is just a simple example of how to create a custom post type and a way you could use it dynamically on your WordPress site. As you dive deeper you can start making custom post type templates and really utilize them to build out your site in an efficient and organized way.

If this tutorial was helpful please let me know below in the comments.

Get More Stuff Like This

Marketing, WordPress, Blogging Tips, SEO and Reviews, twice a month.

Thank you for subscribing.

Something went wrong.