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

As WordPress evolved it introduced the support for WordPress Custom Post Type also shortened as CPT. Allowing developers to register different post types along with 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 unless removed by developer.
- 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 functions.php. We are going to use "init" hook of WordPress and use "register_post_type" to register a custom post type. This is how the function is used:
register_post_type('your_post_stype', $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()" with function "custom_cpts()".
- 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);
}
