Avoid showing same WordPress post in multiple loops

Your WordPress theme might have multiple loops in the page. For example, there may be a ‘Featured’ section at the top of your homepage, and a ‘Recent Posts’ section below that.

These are separate loops, but could contain the same post. For example, your most recent post might also be in the Featured category.

You only want the post to appear once. How do you manage it?

Avoid showing duplicate WordPress posts

The answer is surprisingly simple. Put the following in your functions.php.

<?php
add_filter('post_link', 'track_displayed_posts');
add_action('pre_get_posts','remove_already_displayed_posts');

$displayed_posts = [];

function track_displayed_posts($url) {
  global $displayed_posts;
  $displayed_posts[] = get_the_ID();
  return $url; // don't mess with the url
}

function remove_already_displayed_posts($query) {
 global $displayed_posts;
 $query->set('post__not_in', $displayed_posts);
}

We only want to hide posts which have been displayed already – so we hook into the post_link() function call and make a note of the post we’re displaying.

We then want to hook into any new WordPress query to tell the query to not include any of the posts we’ve already seen. We do this by hooking into the pre_get_posts function and passing it our list of already-displayed posts.

Let’s make life even easier!

I’ve just been through WordPress’ slightly laborious review publishing process to make this an easy-to-install plugin for you! You can install Avoid Repeating Posts and all of your problems will go away:

If you’d like to check out the latest source code, have a look on GitHub.

And if you find this plugin or this code snippet useful, please comment below and let me know!

Want some more great WordPress tools? Check out my other plugin: Secretary.

This post was updated in December 2019 to refer to the new way of detecting which posts have been displayed, using post_link rather than the_title as a hook, as post previews don’t always use the_title (they may be thumbnail only) but they DO always have a link.

Loading...