Create Custom Post Types in WordPress
WordPress stores its content as post types and also allows to add custom post types. Learn how to create a custom post type without using a plugin.

WordPress offers this cool feature to add WordPress Custom Post Type also shortened as CPT. This feature allows developers to register different post types besides the other default post types in WordPress. In this post we are going to create a custom post type called "property" which represents a real estate property.
Post Types in WordPress
Taken from WordPress official Post Types page every single item is called post which is also the default post type of WordPress. By default WordPress comes with the following post types.
- Posts: A default post type for all blog posts.
- Pages: A post type for pages and can create hierarchical page structure.
- Revisions: A special post type used to keep a history of other post types.
- Attachments: Another special post type used to hold information about any media uploaded.
- Menus: A post type used to create menu for navigation purposes on website.
- Custom CSS: A theme specific post type to store CSS changes saved from customizer (Additional CSS).
- Changesets: These post types are like revisions but to store history of changes made from customizer.
How to Create A Custom Post Type in WordPress
We will create cpts.php file and place our code in this file. Then we will include this file in theme's functions.php file. We are going to use init hook of WordPress and use register_post_type function to register a custom post type. This is how the function is used:
register_post_type('your_post_type', $arguments);
The first parameter is your custom type slug and second parameter is an array of arguments for our custom post type or/and any other custom post types. For complete definition of parameters visit WordPress Register Post Type.
Steps to create a custom type in WordPress without using any plugin:
- Add an action hook for
init()withcustom_cpts()function. - Inside function
custom_cpts()define array of labels. - Set argument parameters for custom post type.
- Set labels, menu icon and support array parameter for post type.
- Call function
register_post_type()to create a custom post type. - Provide a unique slug for post type and pass arguments array we prepared as second parameter.
cpts.php
<?php
// Register Post Type on init Hook
add_action('init', 'custom_cpts');
function custom_cpts(){
// --- Labels Array --- //
// General name for the post type, usually plural
$labels['name'] = __('Properties', 'text-domain');
// Name for one object of this post type
$labels['singular_name'] = __('Property', 'text-domain');
// Label to signify all items in a submenu link
$labels['all_items'] = __('All Properties', 'text-domain');
// Label for adding a new singular item button on list screen
$labels['add_new'] = __('Add Property', 'text-domain');
// Label for adding a new singular item
$labels['add_new_item'] = __('Add New Property', 'text-domain');
// Label for editing a singular item
$labels['edit_item'] = __('Edit Property', 'text-domain');
// Label for the new item page title
$labels['new_item'] = __('New Property', 'text-domain');
// Label for viewing a singular item
$labels['view_item'] = __('View Property', 'text-domain');
// Label for viewing post type archives
$labels['view_items'] = __('View Properties', 'text-domain');
// Label for searching plural items
$labels['search_items'] = __('Search Property', 'text-domain');
// When no properties are found in admin screen
$labels['not_found'] = __('No Properties Found', 'text-domain');
//--- Custom Post Type Arguments ---//
// Name of the post type shown in the menu.
$cpt_args['label'] = __('Properties', 'text-domain');
$cpt_args['labels'] = $labels;
// Whether a post type is intended for use publicly
$cpt_args['public'] = true;
// The url to the icon to be used for this menu
$cpt_args['menu_icon'] = 'dashicons-admin-multisite';
// Whether to generate and allow a UI for managing this post type in the admin
$cpt_args['show_ui'] = true;
// Whether to delete posts of this type when deleting a user
$cpt_args['delete_with_user'] = false;
// Where to show the post type in the admin menu
$cpt_args['show_in_menu'] = true;
// Makes this post type available for selection in navigation menus
$cpt_args['show_in_nav_menus'] = true;
// Whether to exclude posts with this post type from front end search results
$cpt_args['exclude_from_search'] = false;
// Whether the post type is hierarchical
$cpt_args['hierarchical'] = false;
// Sets the query_var key for this post type
$cpt_args['query_var'] = true;
// Core feature(s) the post type supports
$cpt_args['supports'] = ['title', 'editor', 'thumbnail', 'comments'];
register_post_type('property' , $cpt_args);
}
