Hiding Posts on Front Page and from all plugins

If you want to hide certain posts from all queries on the front page, then remove the conditions you’re using and check is_front_page() instead:

function exclude_single_posts_home($query) {
     if (is_front_page()) {
          $query->set('post__not_in', array(69489,69177,68878,68736));
      }
}

Normally checking the global state is the incorrect way to filter queries (what you’d originally done is the normal correct way), but in your case you actually do want to filter all queries based on the global state, so it’s appropriate.

Just be aware that post__not_in has poor performance, especially if you apply it to multiple queries at once. You might want to consider an alternative approach, like using a custom field or custom taxonomy that you can apply to posts that you want to hide. Queries based on those would be more efficient.


Having added a hide field to posts using Advanced Custom Fields, you can filter out these posts by setting a meta query:

function exclude_single_posts_home($query) {
    if (is_front_page()) {
        $original_meta_query = $query->get( 'meta_query' );

        $new_meta_query = [
            'relation' => 'OR',
            [
                'key'     => 'hide',
                'compare' => 'NOT EXISTS',
            ],
            [
                'key'     => 'hide',
                'value'   => '1',
                'compare' => '!='
            ],
        ];

        if ( $original_meta_query ) {
            $meta_query = [
                'relation' => 'AND',
                $original_meta_query,
                $new_meta_query
            ];
        } else {
            $meta_query = $new_meta_query;
        }

        $query->set('meta_query', $meta_query );
    }
}

The code for this is quite a bit more complicated, for a couple of reasons:

  • Since you’re only just adding the field for the first time, there will be posts that do not have a positive or negative value for hide, so we need to treat posts without this field at all as being not hidden. That’s what the NOT EXISTS query is for. Given this complication I’m not actually certain if the performance will be an improvement. You might want to install the Query Monitor plugin and compare the performance of each.
  • I was relatively confident that no existing queries on the front page had a value for post__not_in, so didn’t bother handling the possibility of conflicts. However, it is more likely that some of the existing queries already have a meta_query set, so this code includes logic that adds the new meta query for hiding posts to any existing queries of they exist, rather than replacing them.