I have a custom post type 'Commercials' and custom post status 'Featured'. Now I want only one featured post. What I mean is right now I can make all posts as Featured, but I want only one to be featured. If there is already a featured post and I select a new one as featured then the old one will go back to publish.

I've been trying for hours to get a solution. Here is the code I'm using.

// Register Custom Post Status
function register_custom_post_status_featured(){
    register_post_status( 'Featured', array(
        'label'                     => _x( 'Featured', 'commercials' ),
        'public'                    => true,
        'internal'                  => true,
        'protected'                 => true,
        'private'                   => false,
        'publicly_queryable'        => true,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop( 'Featured <span class="count">(%s)</span>', 'Featured <span class="count">(%s)</span>' ),
    ) );
add_action( 'init', 'register_custom_post_status_featured' );

// Display Custom Post Status Option in Post Edit
function display_custom_post_status_featured_option(){
  global $post;
  $complete = '';
  $label = '';
  if($post->post_type == 'commercials'){
    if($post->post_status == 'featured'){
        $selected = 'selected';
    echo '<script>
        $("select#post_status").append("<option value=\"featured\" '.$selected.'>Featured</option>");
        $(".misc-pub-section label").append("<span id=\"post-status-display\"> Featured</span>");
        var currentPostStatus = $("select#post_status").find(":selected").text();
        $( "select[name=\"_status\"]" ).append( "<option value=\"featured\">Featured</option>" );
add_action('admin_footer', 'display_custom_post_status_featured_option');

// display label
function rudr_display_featured_status_label( $status ) {
  global $post;
  $complete = '';
  $label = '';
  if($post->post_type == 'commercials'){
    if($post->post_status == 'featured'){
            return array('Featured');
    return $status;

add_filter( 'display_post_states', 'rudr_display_featured_status_label' );

Any help would be very much appreciated.

  • May be think about meta data which will mark your post as "specially marked" instead of "featured" as any post of this post type.
    – Max Yudin
    Jun 4, 2019 at 17:29
  • @Max Wouldn't that create the same issue, I mean after marking a new post as special the older special post has to be unmarked. Jun 4, 2019 at 17:48

1 Answer 1


You can use one of the status transition filter hooks for this:

In the function assigned to the hook, you change the status to publish the previously featured post ( using e.g. $wpdb ). Both actions are performed after saving the post, so you have to change the status in posts other than edited.

add_action( 'featured_commercials', 'se339582_single_featured', 10, 2 );
function se339582_single_featured( $post_id, $post )
    global $wpdb;

    $sql = $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_status='publish' "
            ." WHERE post_status='featured' AND id <> %d", $post_id );
    $wpdb->query( $sql );


SQL for one featured post per category:

$taxonomy_slug = 'commercials';
$sql = $wpdb->prepare( "UPDATE {$wpdb->posts} p " .
    " INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id = p.id " .
    " INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id " .
    " SET p.post_status='publish' " .
    " WHERE p.id <> %d AND p.post_status='featured' AND tt.taxonomy=%s AND tt.term_id = %d", 

    $post_id, $taxonomy_slug, $term_id
  • It works, many thanks :) Jun 5, 2019 at 16:46
  • One more help, I have several custom categories under commercials post type. I want each one to have a featured post. I'm trying this but it's not working. $term =get_the_terms($post_id, 'commercials'); $term_id = $term->term_id; $sql = $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_status='publish' " ." WHERE post_status='featured' AND term_id=".$term_id." AND id <> %d", $post_id ); Can you help me out on this please? Jun 5, 2019 at 17:15
  • Thank you so much. everything is working perfectly. Jun 5, 2019 at 20:20
  • Hi, I'm using the first solution for a new post type(newsletter) and the post status this time is "active" instead of featured. I only need one active item for this post type. It works fine but when I go to Edit the Active post and try to save it instead of an "Update" button there is "Publish" button and the post status changes from Active to Publish, and then I have to manually set it to Active again. Any thoughts? Jul 2, 2019 at 10:09
  • @MuhammadRussell If you press button "Publish" and the status of the post differs from publish and future, status will be changed. You can update post with button "Save Draft", which will save changes and keep status of the post unchanged.
    – nmr
    Jul 10, 2019 at 10:16

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.