WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to hide the WordPress post from archives page using the 'private' option. I only want the post to be hidden from archives but visible to public. How to I do it?

share|improve this question

You'll want to filter the main query via pre_get_posts callback.

If you'll only want to handle one specific post in this manner, you can reference/exclude its post ID directly. If, however, you want this same behavior for any future private posts, then I would query all posts with $post->post_status of private, and exclude them.

One post (where ID = 123):

function wpse99672_filter_pre_get_posts( $query ) {
    if ( ! is_singular() && $query->is_main_query() ) {
        $query->set( 'post__not_in', array( 123 ) );
add_action( 'pre_get_posts', 'wpse99672_filter_pre_get_posts' );

Or, for all private posts:

function wpse99672_filter_pre_get_posts( $query ) {
    if ( ! is_singular() && $query->is_main_query() ) {
        // Query all post objects for private posts
        $private_posts = new WP_Query( array( 'post_status' => 'private' ) );
        // Extract post IDs
        // Note: for performance, you could consider
        // adding this array to a transient
        $private_post_ids = array();
        foreach ( $private_posts as $obj ) {
            $private_post_ids[] = $obj->ID;
        $query->set( 'post__not_in', $private_post_ids );
add_action( 'pre_get_posts', 'wpse99672_filter_pre_get_posts' );
share|improve this answer

I think the easiest way would be to control the loop in the archive.php file, IF it's just the one post you want to hide from the archives.

$query = new WP_Query( 'p=-7' );

Where 7 is the post_ID of the post you want to hide and the - sign designates you want to exclude it from the loop.

Take a look at this link that explains the usage and arguments that can be passed, in case you want to go further then what your question suggests.

Here and here you can find alternate methods to accomplish what I mentioned.

--- Update ---

Given toscho's comments I've dug around a bit and here is how you can use a filter on the pre_get_posts():

function exclude_post( $query ) {
    if ( is_archive() ) {
        $query->set( 'p', -7 );
    }//end if
}//end function
add_action( 'pre_get_posts', 'exclude_post' );
share|improve this answer
A new WP_Query just to hide one post? Why would you waste the original query? – toscho May 16 '13 at 10:28
I did take a peek at the get_posts(); arguments and I didn't find the $post_ID so I mentioned the last 2 links for clarification without going into it again. Would something like this be better? <?php if(is_archive()) { $args = array( 'post_ID' => -7 ); $show_posts = get_posts ( $args ); } ?> – Fernando Silva May 16 '13 at 10:46
A filter on pre_get_posts is the only fast option here in my opinion. – toscho May 16 '13 at 11:09
Not sure about if ( is_archive() ) or if ($query->is_archive). Both usages are in different examples on the codex. – Fernando Silva May 16 '13 at 11:23

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.