While developing WordPress plugins or themes or in general developing a website using WordPress very often we need to implement custom post types. But not very often but some cases we are in need to add settings page to custom post type to store different settings information.

To implement a settings page to a custom post type, first thing we need to do is implement a custom post type. We will start from there.

You can create a custom post type by calling register_post_type function. Here is the code snippet to do it.

    add_action( 'init', 'codex_book_init' );
     * Register a book post type.
     * @link http://codex.wordpress.org/Function_Reference/register_post_type
    function codex_book_init() {
    	$labels = array(
		'name'               => _x( 'Books', 'post type general name', 'your-plugin-textdomain' ),
		'singular_name'      => _x( 'Book', 'post type singular name', 'your-plugin-textdomain' ),
		'menu_name'          => _x( 'Books', 'admin menu', 'your-plugin-textdomain' ),
		'name_admin_bar'     => _x( 'Book', 'add new on admin bar', 'your-plugin-textdomain' ),
		'add_new'            => _x( 'Add New', 'book', 'your-plugin-textdomain' ),
		'add_new_item'       => __( 'Add New Book', 'your-plugin-textdomain' ),
		'new_item'           => __( 'New Book', 'your-plugin-textdomain' ),
		'edit_item'          => __( 'Edit Book', 'your-plugin-textdomain' ),
		'view_item'          => __( 'View Book', 'your-plugin-textdomain' ),
		'all_items'          => __( 'All Books', 'your-plugin-textdomain' ),
		'search_items'       => __( 'Search Books', 'your-plugin-textdomain' ),
		'parent_item_colon'  => __( 'Parent Books:', 'your-plugin-textdomain' ),
		'not_found'          => __( 'No books found.', 'your-plugin-textdomain' ),
		'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin-textdomain' )

	$args = array(
		'labels'             => $labels,
                'description'        => __( 'Description.', 'your-plugin-textdomain' ),
		'public'             => true,
		'publicly_queryable' => true,
		'show_ui'            => true,
		'show_in_menu'       => true,
		'query_var'          => true,
		'rewrite'            => array( 'slug' => 'book' ),
		'capability_type'    => 'post',
		'has_archive'        => true,
		'hierarchical'       => false,
		'menu_position'      => null,
		'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )

	register_post_type( 'book', $args );

This code snippet is taken from WordPress Official Codex. You can find the full reference here. Our goal is not to create custom post type. So we won’t go in depth into this function here.

Now, to add custom options page for this post type we will need it’s slug in the admin page. Which is in this case ‘book’. We will use add_submenu_page function here to implement our custom options page.

First, we have to add an action to admin_menu hook to invoke the add_submenu_page function. We will do it like this:

    function add_book_settings_page(){
        add_submenu_page('edit.php?post_type=book', 'Settings', 'Settings', 'manage_options', 'book-settings', 'book_settings_page');
    add_action('admin_menu', 'add_book_settings_page');

    function book_settings_page(){
        // here goes the contents of the settings page

This will add a new menu item under Book post type menu. Now at this point we will go some in depth into this code segment. There are 6 parameters to add_submenu_page function.

First one is parent_slug. Remember that we noted the slug to the custom post type ‘book’? We will use it here. General structure for any post type admin page in WordPress is edit.php?post_type=target_post_type. So, in our case we are using edit.php?post_type=book to specify that we want the settings page to appear as a submenu to the Book Menu.

Second and Third one is respectively Page Title and Menu Title. And they are used to determine properties as their name suggests.

Next one is capability. This parameter is used to determine the access level of the page. We are using ‘manage_options’, which means we are making this page admin level access.

Next parameter is slug for the settings page. We have put book-settings for this one.

Last parameter is callback function for generating the contents of the settings page. Next we will go through implementation of this function.