Exclude the first ‘n’ number of posts of a tag from home page?

Use case (example): Using a separate, custom query my website’s home page shows 5 featured posts, tagged ‘Highlights (highlights)’, followed by the latest posts, from the main query.

I don’t want the 5 featured posts, i.e. the first 5 posts tagged ‘highlights’, to appear among the latest posts.

Read More

To put it another way, the latest posts should include all the latest posts, but in doing so, if it finds a post is tagged ‘highlights’ and is among the first 5, it should be excluded.

All this, without breaking the pagination.

How do I do this?


I have faint idea as to how I can do this:

function itsme_filtered_latest_posts( $query ) {

    if( $query->is_home() && $query->is_main_query() ) {

        $query->set( ... );

        $query->set( 'offset', ... );

    }

}
add_action( 'pre_get_posts', 'itsme_filtered_latest_posts' );

Like I said, I only have a faint idea, which is as good as having none.

Related posts

2 comments

  1. A in your example, you have access to all the WP_Query Object query_vars (see [here])1, you could use the post__not_in query_var in your query. It takes an array of ids as a parameter. So first you query for your posts tagged ‘highlighted’.
    While displaying them, you would add all their ids to an array like so

    <?php
    $do_not_duplicate = array(); // set befor loop variable as an array
    
    while ( have_posts() ) : the_post();
        $do_not_duplicate[] = $post->ID; // remember ID's of 'highlighted' posts
    
        //display posts
    
    endwhile;
    ?>
    

    then you kick off another query like so.

    <?php
    // another loop without duplicates
    query_posts( array(
        'post__not_in' => $do_not_duplicate
        )
    );
    while ( have_posts() ) : the_post();
        // display your posts without the highlighted
    endwhile;
    ?>
    
  2. Do something like this:

    function get_custom_posts_wpse_124312() {
      static $post_qry;
      if (!empty($post_qry)) {
        return $post_qry;
      } else {
        $post_qry = new WP_Query(array('post_type'=>'post','posts_per_page'=>2)); // whatever arguments you need
      }
      return $post_qry;
    }
    
    function filter_featured_special_wpse_124312($qry) {
      if ($qry->is_main_query()) { // whatever conditions you need
        remove_action('pre_get_posts','filter_featured_special_wpse_124312');
        $fs = get_custom_posts_wpse_124312();
        if (!empty($fs)) {
          $ids = wp_list_pluck($fs->posts,'ID');
          $qry->set('posts__not_in',$ids);
        }
      }
    }
    add_action('pre_get_posts','filter_featured_special_wpse_124312');
    

    The get_custom_posts_wpse_124312() should retrieve your “5 featured posts, tagged ‘Highlights (highlights)'” using whatever arguments you need to do that. I assume a tax_query? You then use that data to exclude the posts returned from your main query. You can then use get_custom_posts() in your template to retrieve the post object for display. You will need to create a Loop for it in the template file. Because $post_qry is static the “featured” query should only run once.

Comments are closed.