Create Custom Post Status in WordPress using register_post_status()

This article will show you how to create custom post status in WordPress and add that post status to the WordPress post status drop down menu.

Upon recently in WordPress i have not had a reason to create a custom post status, i have just used the default statuses of ‘publish’, ‘private’, ‘protected’ but this time i required a custom post status to still be visible to the public but display a notification that it was no longer valid hence the creation of ‘archive’ custom post type.

Registering WordPress custom post status ‘archive’

To create a custom post status in wordpress, you need to first register it in your wordpress theme, once registered at first you will not notice anything different. Once you have added a post to your new status you will notice in the administration index for that post type will display a new link to view all posts with your new status.

Add the snippet below to your themes functions.php file.

function jc_custom_post_status(){
     register_post_status( 'archive', array(
          'label'                     => _x( 'Archive', 'post' ),
          'public'                    => true,
          'show_in_admin_all_list'    => false,
          'show_in_admin_status_list' => true,
          'label_count'               => _n_noop( 'Archive <span class="count">(%s)</span>', 'Archive <span class="count">(%s)</span>' )
     ) );
add_action( 'init', 'jc_custom_post_status' );

We hook our function to be run when wordpress inits, this is the earliest that a custom post type can be registered. We then register our archive post status with an array of arguments ( a full list of what these arguments do can be found here )

Adding custom post status to WordPress status dropdown

WordPress custom post statuses can be used without adding them to the edit posts post status drop down menu, but for this demonstration it is a good visual starting point.

Add the following snippet in your themes functions.php file.

add_action('admin_footer-post.php', 'jc_append_post_status_list');
function jc_append_post_status_list(){
     global $post;
     $complete = '';
     $label = '';
     if($post->post_type == 'post'){
          if($post->post_status == 'archive'){
               $complete = ' selected="selected"';
               $label = '<span id="post-status-display"> Archived</span>';
          echo '
               $("select#post_status").append("<option value=\"archive\" '.$complete.'>Archive</option>");
               $(".misc-pub-section label").append("'.$label.'");

The previous snippet of php and jquery gets hooked into the footer of the admin post.php page, you can set the script to a certain post type by changing the following line, replacing ‘posts’ with what custom post type you wish to add it to:

if($post->post_type == 'posts'){

Now lets try it out, go and edit a published post, click on the edit button next to the word status just above the blue publish button, options shown below:

Custom post status list

Click on the blue button to update the post, now in the administration index page for this post type you should have a new archive filter to display posts with your custom post status, shown below:

Custom post status admin filter

Adding custom post status to post type index

To finish your new custom post status by making it easier to tell the difference between your new status and others, for example when you make a post private in the list of posts you get a private next to the post.

Display custom post status label
Display custom post status label

Add the following snippet to your functions.php file to add this to your custom post status:

function jc_display_archive_state( $states ) {
     global $post;
     $arg = get_query_var( 'post_status' );
     if($arg != 'archive'){
          if($post->post_status == 'archive'){
               return array('Archive');
    return $states;
add_filter( 'display_post_states', 'jc_display_archive_state' );

The following section only shows the post status next to the post when viewing all posts, and hides it when you view the list of archived posts, get_query_var get the currently selected post status from the url and the if statement checks to see if the archive post status is not being viewed.

$arg = get_query_var( 'post_status' );
if($arg != 'archive'){
// code here if archive post status not selected

Leave a Reply

Fields marked with an * are required to post a comment