How to Create a WordPress Custom Post Type – What It Is, Creating and Customizing One

How to Create a WordPress Custom Post Type – What It Is, Creating and Customizing One

Do you want to create a WordPress custom post type? It’s an excellent and useful way to organize your website if you’re running several types of content all at once.

In this tutorial, you will learn how to make a WordPress custom post type by building a site-specific plugin.

What Is a WordPress Custom Post Type?

The CMS provides a few default post types, such as WordPress Post, Page, Revision, and Attachment. On a small scale, they will represent your blog topic just fine. However, they might not be sufficient after your content becomes more diverse.

That’s where the WordPress custom post type comes into play. In short, it is an additional post type that you create based on your needs. With it, you’ll be able to group your posts more specifically.

Creating a custom post type in WordPress is more efficient than assigning categories to your posts. That’s because categorizing articles places them on the same list, commonly in the Post section. The problem is, if you have more than one broad topic, it will be difficult for you to keep track of them.

On the other hand, it lets you choose a more suitable section for your post right from the start. This should help you classify your content better and more seamlessly.

WordPress custom post type has its own menu in the WordPress admin area, which leads to a list of posts of that particular type.

The new WordPress custom post type

In the example above, if a user goes to the Custom Articles database section of your site, the posts from Post, or Page will not be included. That’s because they belong to their own types.

Not only that, you can help readers narrow down their searches further by grouping posts on your Custom Articles into different categories, like Review, Tutorial, etc. Such a great convenience for your visitors, right?

What Can You Change in WordPress Custom Post Type?

When creating a new post type, you have several customization options. You can choose where the menu appears in the admin area, whether that type of post is included in search results, whether it supports excerpts, whether comments are allowed, and so on.

What’s great is that you can also change various pieces of text, such as renaming Add New Post as Add New Custom Article, replace the Featured Image text with Add Poster, and the list goes on.

Moreover, WordPress custom post type allows you to enable the custom field feature in the post editor. Thanks to this, it’s possible to provide more details about your content.

Take a look at our Custom Articles post type example. Besides having the article as its main content, you have the option to add custom fields for information like Author, Reading Time, and so on.

Custom field forms under your post editor

However, any custom fields you create are available on all post types. Therefore, a plugin is required to limit a specific field to only appear for a certain post type. We will explain how to do this later on, so keep on reading.

Elements of a WordPress Custom Post Type

To begin, let’s learn how to write a new function that calls the register_post_type() function. It should come with two parameters:

  • The name of the post type that should be no more than 20 characters and must not contain spaces or capital letters. Our custom post type name is article.
  • An associative array named $args that contains information about the post type in ‘key’ => ‘value’ pairs.

Important! Remember that the functions must be hooked to the init action hook. Otherwise, your WordPress custom post type will not register correctly.

Lastly, all custom functions should be prefixed to avoid conflicts with other plugins or theme functions. To make them unique, we’ll be using Hostinger Tutorials initials for this example – ht.

The initial code to add a new custom post type should look like this:

// The custom function MUST be hooked to the init action hook
add_action( 'init', 'ht_custom_post_custom_article' );

// A custom function that calls register_post_type
function ht_custom_post_custom_article() {

  // Set various pieces of text, $labels is used inside the $args array
  $labels = array(
     'name' => _x( 'Custom Articles', 'post type general name' ),
     'singular_name' => _x( 'Custom Article', 'post type singular name' ),

  // Set various pieces of information about the post type
  $args = array(
    'labels' => $labels,
    'description' => 'My custom post type',
    'public' => true,

  // Register the post type with all the information contained in the $arguments array
  register_post_type( 'article', $args );

Since the $args and $labels are both arrays, it’s better to write the $labels variable first and then the $args variable. Once that is done, you can register the code.

Now, we are going to discuss $args and $labels arrays that we will use to customize the WordPress custom post type.

What Is $args Array?

$args is short for argument and this variable is used to contain arrays. Array, on the other hand, is a data structure that stores elements (key and value pairs) of an object (WordPress custom post type).

There are many arrays in $args, but we’re going to list only the most commonly used. Keep in mind, however, that they are all optional.

  • labels – an array that defines various pieces of text, such as the menu name and the name of the WordPress custom post type itself. We’ll talk more about this array later in the $label array section.
  • description – a short and descriptive summary of the post type. This can be shown in the post type’s template and will not be used anywhere else.
  • public – to change the visibility of the WordPress custom post type to authors and visitors. We’re going to set the value to TRUE to make it appear in the WordPress Dashboard.
  • menu_position – the position of the new link in the WordPress admin area navigation menu. The value of five puts it below Posts and 100 puts it below Settings. You might want to see the full list of positions in the WordPress Codex page.
  • supports – selectively enable various post features such as featured images, excerpts, custom fields, etc. If set to FALSE instead of containing an array, it disables the editor for this post type. This will be useful if you want to lock all posts of this type while keeping them visible.
  • has_archive – this key defines three things if set to TRUE – your post type has an archive page, the URL follows your permalink structure, and the slug is the name you entered in parameter 1 of register_post_types(). For instance, shows all Custom Articles posts.
  • show_in_admin_bar – using the TRUE value will make this post type appear in the upper Admin bar, under the +New section.
  • show_in_nav_menus – changes whether posts of this type can be added to navigation menus created via the Appearance -> Menus screen. Here, we’ll need to enter a TRUE value.
  • query_var  – TRUE or FALSE sets whether or not readers can view a post by entering the post type and post title as a query in the URL, like ‘‘.

What Is $labels Array?

The first array in the $args variable is $labels. What’s unique, is that it’s made to contain other arrays. Therefore, it is crucial to create a variable named $labels to hold all the key and value pairs in a separate section. This reduces the risk of writing incorrect code and to make the function somewhat more cleaner.

Below are some of the most important keys for the $labels array:

  • name – the general plural name for the post type
  • singular_name – the name for a single post of this type
  • add_new – replaces the ‘Add New’ text
  • add_new_item – changes the ‘Add New Post’ text
  • edit_item – adjusts the ‘Edit Post’
  • featured_image – modifies ‘Featured Image’ in the post editor
  • set_featured_image – replaces ‘Set Featured Image’
  • menu_name – alters the text of the top-level link (the default text for the link is the name key)

You can take a look at the full list of $args and $labels arguments on the WordPress Codex page for register_post_type().

What Is ‘supports’ Array?

One of the keys in the $args array is supports. This is a simple array where you write the list of post editor features you want to enable for your WordPress custom post type. By default, only title and editor are enabled.

However, you can also write FALSE  instead of an array. By doing this, you will disable all post-editing features including the title and content area. That way posts can’t be edited but they are still fully visible.

Here is the list of post editor features you can enable in the supports array:

  • title
  • editor
  • author
  • thumbnail
  • excerpt
  • trackbacks
  • custom-fields
  • comments
  • revisions
  • page-attributes
  • post-formats

Creating a New Post Type via a Site-Specific Plugin

To create a WordPress custom type, you can either build a site-specific plugin, download a normal plugin, or edit your functions.php file.

The third method is not recommended because your custom post type data might be overwritten after theme update. The second method is also not reliable since your data will disappear once you deactivate the tool.

Therefore, we are going to proceed with the first option – building a site-specific plugin. Basically, it’s a custom tool that you can build by yourself for specific tasks.

What’s great about it is that you can keep the data even if you decide to update your theme or deactivate the plugin. It’s also highly customizable.

However, this method can get a bit technical. That’s why, to help you get started, we encourage you to read our tutorial on how to create a WordPress plugin, as well.

Now that we know what elements are required for the function, we can build our plugin, write the custom functions, and hook them to the init action hook.

This is how a finished WordPress custom post type should look like:



Plugin Name: My Custom Post Types

Description: Add post types for custom articles

Author: Hostinger Dev


// Hook <strong>lc_custom_post_custom_article()</strong> to the init action hook

add_action( 'init', 'ht_custom_post_custom_article' );

// The custom function to register a custom article post type

function ht_custom_post_custom_article() {

// Set the labels, this variable is used in the $args array

$labels = array(

'name'               => __( 'Custom Articles' ),

'singular_name'      => __( 'Custom Article' ),

'add_new'            => __( 'Add New Custom Article' ),

'add_new_item'       => __( 'Add New Custom Article' ),

'edit_item'          => __( 'Edit Custom Article' ),

'new_item'           => __( 'New Custom Article' ),

'all_items'          => __( 'All Custom Articles' ),

'view_item'          => __( 'View Custom Article' ),

'search_items'       => __( 'Search Custom Article' ),

'featured_image'     => 'Poster',

'set_featured_image' => 'Add Poster'


// The arguments for our post type, to be entered as parameter 2 of register_post_type()

$args = array(

'labels'            => $labels,

'description'       => 'Holds our custom article post specific data',

'public'            => true,

'menu_position'     => 5,

'supports'          => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments', 'custom-fields' ),

'has_archive'       => true,

'show_in_admin_bar' => true,

'show_in_nav_menus' => true,

'query_var'         => true,


// Call the actual WordPress function

// Parameter 1 is a name for the post type

// Parameter 2 is the $args array

register_post_type( 'article', $args);


Now, to turn this code into a plugin, follow the steps below:

  1. First, open a text editor on your computer. Copy and paste the code.
  2. Save it as a PHP file. For this example, we will name it my-custom-post-type.php.
  3. Navigate to public_html -> wp-content -> plugins. There, create a new folder with the same name as your plugin and upload your PHP file inside. Use your hosting provider’s File Manager tool or an FTP client such as FileZilla to upload the file.
    The folder for your site-specific plugin
  4. Next, log in to your WordPress Dashboard and go to the Plugins menu. You’ll see your newly-installed plugin. Lastly, activate it. There will be a new post type, called Custom Articles.
    The plugin for your adding custom post type

Congratulations, you have just installed a site-specific plugin to create a WordPress custom post type!

Customizing New Post Type

To begin customizing your new post types, you just have to upload two corresponding template files to your theme’s main directory. Names of these template files should look like this:

  • Template for an individual post – single-{post-type}.php
  • Template for an archive page – archive-{post-type}.php

The {post-type} part of the file names must be the name from parameter 1 of register_post_type(). In this example,  the file names should be single-article.php and archive-article.php

If you don’t create templates, WordPress will use single.php and archive.php instead, which keeps all your posts and archives identical.

That being said, the best way to start is to duplicate single.php or archive.php and rename them as above. That way the overall structure is identical to the rest of your theme and all required template tags are already in place. Thus, it will be easier for you to style the template later.

Here’s how to upload your template files:

  1. Once you’ve gained access to your website storage, locate the folder of your currently active theme. In our case, it is the Twenty Seventeen theme. So the directory is /public_html/wp-content/themes/twentyseventeen.
  2. Copy the single.php and archive.php files and paste them outside that folder.
  3. Rename them single-article.php and archive-article.php. Next, move them back to the Twenty Seventeen folder.
    The modified template files for your custom post type
  4. Repeat the second and third steps for other custom post type templates.

Once the template files have been uploaded, it’s time to display the WordPress custom post types on the front page.

Displaying Custom Post Types on the Front Page

Custom post types are not displayed on the front page by default. That’s why you have to write a new function that calls the set method of WordPress’ WP_Query object. Let’s take a look at the code structure first:

// Hook our custom function to the pre_get_posts action hook

add_action( 'pre_get_posts', 'add_article_to_frontpage' );

// Alter the main query

function add_article_to_frontpage( $query ) {

if ( is_home() && $query->is_main_query() ) {

$query->set( 'post_type', array( 'post', 'article' ) );


return $query;


In this function, $query->set() takes two parameters:

The first one is the property you want to change. In our case, we want to change the post_type.

The second parameter is the array that you want as the value of the post_type property (post and article).

As you can see, the array starts with ‘post’. This is because it is the default post type in WordPress and we still want to include it on the front page. If you only want to display custom posts on the front page, you can remove it.

In this example, we’ll add ‘article’ to the array, meaning that the front page will show all regular posts and all custom article posts.

Now, to achieve this, you can paste the code to your theme functions file (functions.php) or to the site-specific plugin that you have created. Again, to prevent any data loss, we’ll be using the second option.

  1. Access your website files again and go to the folder of your site-specific plugin (/public_html/wp-content/plugins/my-custom-post-type).
  2. Open the PHP file. Then, copy the code from before and paste it at the bottom of the file.
    Additional code to display custom post on the front page
  3. Save your changes.

You can visit your website now. All posts from the default and custom post types should be available on the front page.

The default and ustom posts displayed on the front page

Adding and Displaying WordPress Custom Field

Once you have created a new WordPress custom post type, you might want to add a custom field so you can provide more details about your content.

There are two ways to do this – using the standard WordPress custom field or a plugin and each has its own advantages and disadvantages. We’ll begin with the default one.

Using WordPress Default Custom Field

WordPress provides us with a built-in tool to add a custom field. What’s great, it is pretty easy to use.

  1. WordPress custom field is hidden by default. Therefore, you need to activate it from Screen Option in the post editor.
    Activating the custom field feature
  2. Once activated, you will see a custom field section under the editor, where you can enter the name and its value. When you’re done, click the Add Custom Field button.
    Custom field forms under your post editor

Unfortunately, custom fields won’t show up by default on the front-end of your page. To make them visible, you need to insert the_meta() or echo get_post_meta() function to the theme file that’s responsible for displaying your posts.

Now that we have two post types, we can either edit single.php or single-article.php. It depends on where you want the custom field to be.

Let’s say we want to add an Author custom field for the custom articles posts. We’ll need to enter the code in single-article.php. Here are the steps:

  1. From your WordPress Dashboard, head to Appearance -> Theme Editor -> singe-article.php.
  2. Locate the WordPress Loop and find this line.
    get_template_part( 'template-parts/post/content', get_post_format() );
  3. Paste one of the following code snippets to the file under that line.
    • the_meta(); – use this code if you want to display all available custom fields on a post.
    • echo get_post_meta( $post->ID, ‘key’, TRUE ); – use this code to display a specific custom field. Remember to replace the key value with your custom field name.
  4. After that, click Update File.

If you visit your website, you will see the Author custom field below the post.

The Author custom field displayed on your post page.

Limiting Custom Fields to a Specific Post Type via a Plugin

Advanced Custom Field banner

While it is simple to use, adding custom fields directly from WordPress is not necessarily the best option. That’s because once you’ve added a custom field, it will be available for all types of posts. This can make it difficult to find the field you need for a specific post type.

Therefore, you might want to try the Advanced Custom Fields plugin. It limits certain custom fields so that they are only selectable on a chosen post type. This is how you use the tool:

  1. On your WordPress Dashboard, go to the Plugins menu and select Add New. Type Advanced Custom Field in the search bar. Install the plugin.
    Installing Advanced Custom Field Plugin

Important! After this plugin is enabled, you will no longer see the default WordPress custom field on your post editor.

  • There will be a new menu on your sidebar called Custom Fields. To add a custom field, click the Add New button. You will need to enter several important details, such as:
    • Field Label – the name of your custom field that will be displayed on the edit page.
    • Field Name – the ID of your custom field that will be used to display on your theme.
    • Field Type – choose between text, checkbox, URL, etc., based on your needs.
      Adding a custom field from Advanced Custom Fields
  • Once you’re done, hit Close Field. Now, to limit this custom field to a specific post type, head to the Location settings in Advanced Custom Field plugin.
  • Let’s say we want the new custom field to be selectable only on a specific post type. Each option in the Show this field if columns should be Post Type -> is equal to -> Custom Article.
    Limiting the rating custom field to the Movie post type
  • Once done, don’t forget to click Publish to save your change.
  • Since this field is created via a plugin, you must use that plugin’s functions to display it. These steps to insert the function are similar to the default WordPress custom field. The only difference is that you have to enter the_post( ‘key’ ); code instead.


    WordPress custom post type is the perfect solution to organize your website, especially if it focuses on more than one subject. You will have the power to divide your content based on the information that they contain.

    With a little bit of WordPress and PHP skills, you can easily follow all the steps yourself.

    Good luck and be sure to leave a comment below if you have any questions!

    The author

    Liam C.

    Liam is a WordPress fanatic that loves to write about web development and coding. When he's not working, he likes to help people create websites and applications. In short, his job is also a hobby!