Custom post types are new post types you can create in WordPress.

A custom post type can be added via the register_post_type() function. This function allows you to define a new post type by its labels, supported features, availability and other specifics.

You must call register_post_type() before the admin_menu and after the after_setup_theme action hooks. A good hook to use is the init action hook.

Basic example of creating custom Post Type

Here is a basic example of adding a custom post type into WordPress

add_action( 'init', 'create_my_post_type' );
function create_my_post_type() {
  register_post_type( 'movie',
    array(
      'labels' => array(
        'name' => __( 'Movie' ),
        'singular_name' => __( 'Movie' )
      ),
      'public' => true,
      'has_archive' => true,
    )
  );
}

The above example creates a post type movie labelled with Movie which will show in the post type menu and post edit screen.

As you observed, the register_post_type() function receives two major arguments. The first one is labels which define the name of the post type in both plural and singular forms. The second one is public which is a predefined flag to show the post type on the administration screens and to make it show up in the site content itself, if it’s queried for.

There are many more arguments that you can pass to the register_post_type() function, to do things like show the new post type in search, change the url of the new posts, limit the post type support, add an icon to the post type menu, and hide or show meta boxes in the post edit screen. These parameters are optional, and you can use them to configure your post type on a detailed level.

Creating post type as a Plugin

To prevent losing your post type when switching to a new theme, define your post type as a plugin. That way, your website will not break when you switch to different themes.

Naming your post type

I recommend prefix your post type identifier with a short namespace that identifies your plugin or theme. For example, when creating a post type movie, it is better to add a prefix like ywt_movie. That ways, you can avoid conflict to plugins that were using the same post type.

Reserved Post Type Identifiers

Although the core development team has yet to make a final decision on this, it has been proposed on the wp-hackers mailing list that future core post type identifiers will be namespaced with wp_, i.e. if the core team decides to add an event post type then according to this suggestion they would use the wp_event identifier. Even though this has not been finalized, it will be a good idea to avoid any custom post types whose identifier begins with wp_.