I created a custom post types and I want to let the user choose the static page for the archive page. For example, under Post page. I would like to add a Projects page: [ Dropdown ]

Is there a way to add another static page option to the reading settings page? Is there an existing hook to modify it?

reading settings

Also, is there a way to mark the selected page like this in Pages?

enter image description here


Looking at /wp/wp-admin/includes/template.php:1768

 * Filters the default post display states used in the posts list table.
 * @since 2.8.0
 * @since 3.6.0 Added the `$post` parameter.
 * @param array   $post_states An array of post display states.
 * @param WP_Post $post        The current post object.
$post_states = apply_filters( 'display_post_states', $post_states, $post );

if ( ! empty($post_states) ) {
    $state_count = count($post_states);
    $i = 0;
    echo ' — ';
    foreach ( $post_states as $state ) {
        ( $i == $state_count ) ? $sep = '' : $sep = ', ';
        echo "<span class='post-state'>$state$sep</span>";

It seems like there are hooks for the post_state, but how do you set it?

Also, looking at /wp-admin/options-reading.php:83

Is there a way to modify the Reading setting without actually modifying the file?


1 Answer 1


I dont know if it is possible to add a new field directly under the "Posts page" dropdown field, atleast I found no way to do this.

But you could just add another dropdown menu to the reading settings page. This will be on the bottom thou.

To do this, first we need to register our new setting and add a new settings field to the default WordPress reading page:

 * Register and define the settings
add_action('admin_init', 'prfx_admin_init');
function prfx_admin_init(){

    // register our setting
    $args = array(
        'type' => 'string', 
        'sanitize_callback' => 'sanitize_text_field',
        'default' => NULL,
        'reading', // option group "reading", default WP group
        'my_project_archive_page', // option name

    // add our new setting
        'my_project_archive_page', // ID
        __('Project Archive Page', 'textdomain'), // Title
        'prfx_setting_callback_function', // Callback
        'reading', // page
        'default', // section
        array( 'label_for' => 'my_project_archive_page' )

Now we can create the callback function for our custom field, which will hold our HTML markup:

 * Custom field callback
function prfx_setting_callback_function($args){
    // get saved project page ID
    $project_page_id = get_option('my_project_archive_page');

    // get all pages
    $args = array(
        'posts_per_page'   => -1,
        'orderby'          => 'name',
        'order'            => 'ASC',
        'post_type'        => 'page',
    $items = get_posts( $args );

    echo '<select id="my_project_archive_page" name="my_project_archive_page">';
    // empty option as default
    echo '<option value="0">'.__('— Select —', 'wordpress').'</option>';

    // foreach page we create an option element, with the post-ID as value
    foreach($items as $item) {

        // add selected to the option if value is the same as $project_page_id
        $selected = ($project_page_id == $item->ID) ? 'selected="selected"' : '';

        echo '<option value="'.$item->ID.'" '.$selected.'>'.$item->post_title.'</option>';

    echo '</select>';

After this you now have a new dropdown field under Settings > Reading.
The field is filled with all pages, you can select one and save the setting.

So now you want to mark this selected page on the page list in admin. These markings are called state/s. WordPress uses an filter to add these texts to the title called display_post_states.

 * Add custom state to post/page list
add_filter('display_post_states', 'prfx_add_custom_post_states');

function prfx_add_custom_post_states($states) {
    global $post;

    // get saved project page ID
    $project_page_id = get_option('my_project_archive_page');

    // add our custom state after the post title only,
    // if post-type is "page",
    // "$post->ID" matches the "$project_page_id",
    // and "$project_page_id" is not "0"
    if( 'page' == get_post_type($post->ID) && $post->ID == $project_page_id && $project_page_id != '0') {
        $states[] = __('My state', 'textdomain');

    return $states;
  • Thanks you! It helped me a lot!
    – Isu
    Commented Jun 10, 2021 at 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.