What is a Custom Post Type

WordPress stores all the posts and pages in the default post type “post” and “page” which is included in the default WordPress install, however we can create custom post type in WordPress according to our needs.

Most websites use both to publish their content, “page” for the static pages and “post” for their blog posts. But what if you have a different section which you want to use on your website and create an organized back-end for the site administrator to edit. For example, if you have a “News” section which is different from the blog, then a custom post type can be created so that the blog posts go into “post” while the news items go into the “news” custom post type.

There are a lot of benefits for using this. One of the most important feature of using a custom post type is that you can get the default title, editor and featured image fields in another post type like you have in the default “post” post type. In addition to this, one can use the power of custom meta boxes to enhance the UI experience of the WordPress dashboard.

How to create a Custom Post Type

There are several plugins which can create a custom post type for you website. There are some good plugins which can create a custom post type for your WordPress website according to your needs. However, most plugins use the same code which is used to create a custom post type. Now there can be a debate, whether to use a plugin or just code it out. If you want to use a plugin, then CPT UI is a good plugin with lot of options to create a custom post type. However if you want to code it out then here is how you do it.

To create a custom post type we use the function “register_post_type”. This function should only be invoked through the ‘init’ action. The function should be placed in your functions.php, if you have purchased the theme, then you might need to create a child theme for that and place the code in the functions.php of the child theme.

Here is how it is done..

function custom_post_news() {
	$args = array();
	register_post_type( 'news', $args ); 
}

add_action( 'init', 'custom_post_news' );

The above function will create a custom post type called “news”, but the problem with above is that everything will be related to the default post type “post” which will not be even visible in the admin dashboard.

To make the new custom post type visible and also to make it recognizable for the administrator, here is the full code that you have to place.

function custom_post_news() {
	$labels = array(
		'name'               => _x( 'News', 'post type general name', 'textdomain' ),
		'singular_name'      => _x( 'News', 'post type singular name', 'textdomain' ),
		'menu_name'          => _x( 'News', 'admin menu', 'textdomain' ),
		'name_admin_bar'     => _x( 'News', 'add new on admin bar', 'textdomain' ),
		'add_new'            => _x( 'Add New', 'news', 'textdomain' ),
		'add_new_item'       => __( 'Add News', 'textdomain' ),
		'new_item'           => __( 'New News', 'textdomain' ),
		'edit_item'          => __( 'Edit News', 'textdomain' ),
		'view_item'          => __( 'View News', 'textdomain' ),
		'all_items'          => __( 'All News', 'textdomain' ),
		'search_items'       => __( 'Search News', 'textdomain' ),
		'parent_item_colon'  => __( 'Parent News:', 'textdomain' ),
		'not_found'          => __( 'No news found.', 'textdomain' ),
		'not_found_in_trash' => __( 'No news found in Trash.', 'textdomain' )
	);
	$args = array(
		'labels'        => $labels,
		'public'        => true,
		'menu_position' => 25,
		'supports'      => array( 'title', 'editor', 'thumbnail' ),
		'has_archive'   => true,
	);
	
	register_post_type( 'news', $args ); 
}

add_action( 'init', 'custom_post_news' );

Adding the above will show you the admin menu called “News”

How to create Custom Post Type in WordPress

The $labels can be altered to suit your needs and can be replaced with whatever custom post type you want to create. However you might have to pay a little bit of attention while altering the following lines.

register_post_type( 'news', $args );

Here the “news” is the name of the custom post type. This HAS to be unique and cannot be same. For example, you cannot create another custom post type with the same name “news”. The URLs of your custom post type will also have this term, so for example you create an article called “How to create a custom post type”, then your URL will be domain.tld/news/how-to-create-a-custom-post-type.

'supports' => array( 'title', 'editor', 'thumbnail' ),

The above code will enable the title, editor and the featured image for the custom post type you have created. However you can further add more to it bu separating them with a comma and placing it within ”. Here is the complete list of items you can add.

  • ‘title’
  • ‘editor’ (content)
  • ‘author’
  • ‘thumbnail’ (featured image, current theme must also support post-thumbnails)
  • ‘excerpt’
  • ‘trackbacks’
  • ‘custom-fields’
  • ‘comments’ (also will see comment count balloon on edit screen)
  • ‘revisions’ (will store revisions)
  • ‘page-attributes’ (menu order, hierarchical must be true to show Parent option)
  • ‘post-formats’

If you want to rewrite the “slug” of the custom post type URLs, then you can do that by adding the following to the $args.

'rewrite' => array( 'slug' => 'latest-news' ),

This will change the URL of your custom post type pages to domain.tld/latest-news/how-to-create-a-custom-post-type, so your entire code will look like this.

function custom_post_news() {
	$labels = array(
		'name'               => _x( 'News', 'post type general name', 'textdomain' ),
		'singular_name'      => _x( 'News', 'post type singular name', 'textdomain' ),
		'menu_name'          => _x( 'News', 'admin menu', 'textdomain' ),
		'name_admin_bar'     => _x( 'News', 'add new on admin bar', 'textdomain' ),
		'add_new'            => _x( 'Add New', 'news', 'textdomain' ),
		'add_new_item'       => __( 'Add News', 'textdomain' ),
		'new_item'           => __( 'New News', 'textdomain' ),
		'edit_item'          => __( 'Edit News', 'textdomain' ),
		'view_item'          => __( 'View News', 'textdomain' ),
		'all_items'          => __( 'All News', 'textdomain' ),
		'search_items'       => __( 'Search News', 'textdomain' ),
		'parent_item_colon'  => __( 'Parent News:', 'textdomain' ),
		'not_found'          => __( 'No news found.', 'textdomain' ),
		'not_found_in_trash' => __( 'No news found in Trash.', 'textdomain' )
	);
	$args = array(
		'labels'        => $labels,
		'public'        => true,
		'menu_position' => 25,
		'rewrite'	=> array( 'slug' => 'latest-news' ),
		'supports'      => array( 'title', 'editor', 'thumbnail' ),
		'has_archive'   => true,
	);
	
	register_post_type( 'news', $args ); 
}

add_action( 'init', 'custom_post_news' );