Custom WordPress post statuses are useful when creating different custom post types and their statuses. One of the best example on how to use them is WooCommerce and the order statuses. In this tutorial we will create a simple class that will handle creating custom post statuses with ease.

The OOP class that we will create will create the post status and every JavaScript code needed to add that status even in the Publish upper right box where we can choose the status of our article. Since that part is still in the WordPress Trac at the time of this article, we will add a WordPress filter that can be used to disable the JavaScript code once the custom post statuses get added in that box by the WordPress core.

Every bit of code that you see here or make from here can be used in any of your projects, both personal and commercial.

WordPress API for Custom Status

There is a function in the WordPress core that is used for registering custom WordPress post statuses. This function is register_post_status and you should use it to register your own WordPress post statuses.

Besides the post status slug, you can also pass some arguments:

  • label – label for this status
  • public – indicator to show the content with this status on the front of the site
  • internal – indicator if this is only used on the admin area
  • exclude_from_search – indicator to exclude the content with this status from search results
  • show_in_admin_all_list – indicator to show the content with this status in the admin area where all the content of that post type is shown
  • show_in_admin_status_list – indicator to show the status in the list of statuses such as All (20), Trash (3) and etc
  • label_count – label that will be displayed for different counts

There are some other arguments that can be set but we are not going to explain each of them thought we will have them in our code if for some reason you will have the need to set them.

Custom WordPress Post Status Class

Now that you know how to register a custom WordPress post status we can start coding our class. We will first define all our attributes:

The first attribute $post_type is an array that will hold every post type for which we want to register this post status. Attribute $slug is the unique name of the post status. The third attribute $enable_action is the value that will define the action button that will be used for this post status.

This action can hide the button so that the user can’t edit that content under that post status. That action can also be used to enable the publishing functionality so that the content under that post status can be published and get the publish post status. The last option is update which would enable saving the content under that post status and also leave the content under the same post status.

Attribute $defaults contains every argument that can be set for the custom WordPress post status and the last attribute is $settings that will contain every setting for that post status.

Constructing the WordPress Post Status

Once we understand the meaning of each of our attributes we can define how our custom WordPress post status will be created.

If there are no arguments, we will stop processing the creation of our WordPress post status. We will do the same if the slug or post_type arguments are not set. If they are set, we will also set them to our attributes $slug and $post_type.

After that we will check if the argument action is set. If that is set and it has one of the allowed values which are false, true, publish or update we will set that value to $enable_action.

We are also checking if the arguments label and label_count are set. If that is not set we are setting them from the $slug. Once everything is set we are unsetting arguments post_typeslug and action since that arguments are not needed in the function register_post_status.

The last we have to do is to parse our arguments with defaults to get an array full of needed arguments and also to hook some methods. We parse our arguments with defaults using a WordPress function wp_parse_args and set the returned value to our attribute $settings.

We are registering our custom WordPress post status in the method register_status that is hooked to the action init. Our method set_status is hooked to the action admin_footer where we will add our JavaScript functionality.

Registering Custom WordPress Status

This is a really simple method. We will just call the WordPress API function register_post_status:

Here we are just passing our $slug and $settings attributes. That is all 🙂

Adding JavaScript

This JavaScript will enable us to add the custom WordPress post status in the upper Publish box to enable the selection of our post status:

First we are using a dynamic WordPress filter that will enable us to disable the JavaScript functionality once that becomes a WordPress core functionality. After that we are checking if the post type we are viewing is in our array of allowed post types. If that is false, we are disabling the functionality.

If the current content has our custom post status then we are setting two variables that will be used to set our custom post status in the Publish box. The variable $complete is used for the HTML that creates an option element. We are appending that option to the select element with the id post_status. The variable $complete will there add the selected=selected element attribute to that option if it is set.

We are also adding the variable $label that will have our custom WordPress post status label as value (if the current content is of that post status). As the last thing, we are checking the action that is set.

If the action is set to false then we are removing the button so that the user cannot save or publish the content. If the action is set to update we are changing the text inside the button to “Update” and also the HTML attribute name to save.

By using that action, WordPress will know to save the content and not to publish it. If the action is set to true or publish then we will leave the button as it is so that the content will get published once its clicked.


Here is a simple example of setting a Custom Status with the update functionality:


Custom WordPress post statuses can be really useful as I have said at the beginning of this tutorial. By using the OOP approach we can easily create various custom post statuses for any type of content you want in WordPress.

Have you ever created custom post statuses? Did you struggle using them in the admin area? Share your experience in the comments below!

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at


  1. Thanks for posting this tutorial. I’ve been considering using Post Statuses. I thought there was a push to take them out of core?


    1. I am not aware of that. I know about a trac ticket that is waiting a future release to add additional options to register post status function:


      1. Ok, cool. Yeah, I’m going to look into this further.


  2. Hi, so I’ve registered a custom post status as follows
    ‘label’ => __(‘Active’, ‘wc_registry’),
    ‘label_count’ => _n_noop(__( ‘Active (%s)’, ‘wc_registry’ ), __( ‘Active (%s)’, ‘wc_registry’ ) ),
    ‘post_type’ => ‘wcregistry’,
    ‘public’ => false

    I want to use this status from an admin settings page with a dropdown with an option ‘active’
    my question is how do I implement this so that when a user saves the active option in the database it changes the post status to active


    1. You’ll have to update the post’s status. You can use this function but be sure when using that function to remove your function from the save_post because you could end up in an infinite loop. And once that function is called, you can re-hook your function to the save_post hook. (If the wp_update_post is called within that function.)


  3. Pozdrav Igore,:)
    I bumped in to this tut looking for a way to solve the issue with custom post status (WC shop order) – there seem to be an issue or bug with displaying custom status in posts (shop order) filters (All, Pending, Trash etc.) actually not displaying …
    Any idea what it might be ?(I was trying to solve it with earlier hook then ‘init’, but no success).
    LP, Alen from Ri 🙂


    1. Hi Alen, if you’re adding the status through the filter wc_order_statuses, it should display there. Otherwise, I am not sure. Might be a conflict with some other plugin.


  4. Hello 🙂

    Thanks you for this post but how you deal with save the post with the new status ?

    I mean when you open the post write some stuff and switch to custom post, how you save it ?


    1. Hi Vince, post status is just a status that will be saved regardless of a custom post type. Is that what you meant?


  5. Nice work Igor. This makes a wordpress developer effort time efficient.


  6. Igor, thanks for the tutorial very helpful. I added the code to my plugin php file but the status is not registering on the system. Can you give me some direction?


Leave a reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.