I am trying to register a new post type to hide post in searches but still allow for the post to be seen by url.

function reg_ghost_status(){
    register_post_status( 'ghosted', array(
        'label'                     => 'Ghost Post',
        'publicly_queryable'        => false,
        'exclude_from_search'       => true,
        'public'                    => true, //on false hides everywhere
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
    ) );
add_action( 'init', 'reg_ghost_status' );

I could not get this work and tried all sorts of combinations. It seems since it is 'public' it shows everywhere no matter what settings. So I than tried using the pre_set_query but I don't know how to use exclude instead of include by post_status.

function sxcsexclude_ghost_from_search($query) {
        if ( $query->is_single ) {
             $query->set('perm', 'readable');
             $query->set('post_status', array( 'publish', 'draft', 'ghosted', 'future' ));
            return $query;
add_action( 'pre_get_posts', '11111exclude_ghost_from_search' );

Can someone tell me why the register_post_status is not working.


  • Your code is registering a post status, not a post type. Try register_post_type instead.
    – vancoder
    Sep 29, 2020 at 20:37
  • Sorry I typed posttype but I did mean status
    – Tianbo84
    Sep 30, 2020 at 12:25

2 Answers 2


If it was me, I would probably just override the queries on the individual templates that you are trying to hide "ghosted" posts on. However, I can see how in some situations it would be better to override the main query.

How about:

function public_query_published_only($query) {
  if ( !$query->is_single() && !current_user_can('manage_options') && !is_admin() ) {
        $query->set('post_status', array('publish') );
        return $query;
add_action( 'pre_get_posts', 'public_query_published_only' );

So: if the query is not for a single post, and the user isn't a logged-in user, and the query isn't from the admin interface, only show posts with a status of "publish". (Of course, you could also add any other statuses that you deem to be query-able.)

Because there is not an exclusion filter for post status, this is the best I could think of without resorting to SQL.

  • Yes I think manipulating the query is going to be the only way. I'm just confused why the arguments for register_post_status aren't working, specifically exclude_from_search.
    – Tianbo84
    Sep 30, 2020 at 12:29
  • 1
    Would like to add I found that the API hasn't been finished for 10+ years which might have something to do with it. core.trac.wordpress.org/ticket/12706
    – Tianbo84
    Sep 30, 2020 at 12:30
  • @Tianbo84 What post type are you using the "ghost" status on? If the post type is allowed to show up in search, I don't think the post status is going to override that setting. So that might be where your conflict is.
    – wrydere
    Sep 30, 2020 at 15:20
  • post type is just 'post'. Do you mean if in the original query it has post_type => post?
    – Tianbo84
    Sep 30, 2020 at 17:53
  • I was just wondering if you were using it on the default 'post' type, or a custom post type. After some thought, and after looking at that ticket you linked to: perhaps you would be better off using a custom field, such as "ghosted", and then modifying the query to skip over posts that include that custom field. This seems to make more logical sense, since the post is technically published, it just is not displayed in archives/search.
    – wrydere
    Sep 30, 2020 at 20:58

This question asked long time ago, but here is the better solution:

add_action( 'posts_where', function( $where, $q ) {
    if( $q->is_search() ) {
        global $wpdb;

        $status_to_exclude = 'ghosted';   // Modify this to your needs!

        $where .= sprintf( 
            " AND {$wpdb->posts}.post_status NOT IN ( '%s' ) ", 

    return $where;
}, 10, 2 );

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.