How to Create a Settings Page for Custom Post Types in WordPress

Adding a settings page for your custom post type is a powerful way to enhance your WordPress customization. However, to avoid feeling overwhelmed, it's best to approach this step by step, writing minimal code, checking your progress, and then building upon it.
This guide will walk you through the process interactively, where you write a little code, check the result in the WordPress dashboard, and proceed to the next step.
We’ll start with a very basic custom post type
called Work in Progress
In your theme’s functions.php
file add the following code:
function create_work_in_progress_post_type()
{
$args = array(
'public' => true,
'label' => __('Work in Progress', 'themeName'),
);
register_post_type('work_in_progress', $args);
}
add_action('init', 'create_work_in_progress_post_type');
WordPress
admin dashboard. Work in Progress
. Now, let’s add more functionality, like labels, menu icons, and support for titles and thumbnails.
Update the previous code with this:
function create_work_in_progress_post_type()
{
$labels = array(
'name' => __('Work in Progress', 'themeName'),
'singular_name' => __('Work in Progress', 'themeName'),
'menu_name' => __('Work in Progress', 'themeName'),
);
$args = array(
'labels' => $labels,
'public' => true,
'menu_icon' => 'dashicons-hammer',
'supports' => array('title', 'editor', 'thumbnail'),
);
register_post_type('work_in_progress', $args);
}
add_action('init', 'create_work_in_progress_post_type');
Now that your custom post type is set up, it’s time to add a settings
page under the Work in Progress
menu.
In your theme directory, create a new file, e.g., inc/settings-page.php
, and add the following:
<?php
function add_wip_settings_page()
{
add_submenu_page(
'edit.php?post_type=work_in_progress', // Parent menu
__('Settings', 'themeName'), // Page title
__('Settings', 'themeName'), // Submenu title
'manage_options', // Capability
'wip_settings', // Menu slug
'render_wip_settings_page' // Callback function
);
}
add_action('admin_menu', 'add_wip_settings_page');
// Callback to display the settings page
function render_wip_settings_page()
{
echo '<div class="wrap"><h1>Work in Progress Settings</h1><p>Settings will go here.</p></div>';
}
?>
Add this line to your functions.php
file to load the settings page:
require_once get_template_directory() . '/inc/settings-page.php';
Work in Progress
> Settings
. Work in Progress Settings
Now that the settings page is visible, let’s add a form to save and retrieve a custom heading.
render_wip_settings_page
Function:Replace the placeholder content with the following:
function render_wip_settings_page()
{
// Check if the user is allowed to access the page
if (!current_user_can('manage_options')) {
return;
}
// Save settings if the form is submitted
if (isset($_POST['save_wip_settings'])) {
update_option('wip_custom_heading', sanitize_text_field($_POST['wip_custom_heading']));
echo '<div class="updated"><p>Settings saved.</p></div>';
}
// Retrieve the current value
$heading = get_option('wip_custom_heading', 'Default Heading');
?>
<div class="wrap">
<h1><?php esc_html_e('Work in Progress Settings', 'themeName'); ?></h1>
<form method="post" action="">
<table class="form-table">
<tr>
<th>
<label for="wip_custom_heading"><?php esc_html_e('Custom Heading', 'themeName'); ?></label>
</th>
<td>
<input type="text" name="wip_custom_heading" id="wip_custom_heading" value="<?php echo esc_attr($heading); ?>" class="regular-text">
<p class="description"><?php esc_html_e('Enter a custom heading for the Work in Progress section.', 'themeName'); ?></p>
</td>
</tr>
</table>
<?php submit_button(__('Save Settings', 'themeName'), 'primary', 'save_wip_settings'); ?>
</form>
</div>
<?php
}
Finally, let’s display the saved custom heading on the front end or admin area.
Use the following snippet wherever you want to display the saved heading:
<?php
$custom_heading = get_option('wip_custom_heading', 'Default Heading');
echo '<h1>' . esc_html($custom_heading) . '</h1>';
?>
If you want to move the "Work in Progress" menu higher or lower on the dashboard, update the menu_position
in your custom post type code.
'menu_position' => 20, // Places it below Pages
Check the WordPress dashboard and confirm the menu position.