Prevent Posts in a Category From Displaying in WordPress’ Loop

By  on  

This code snippet has become a WordPress plugin!

Categories are obviously a major "classification" utility for websites and blogs that use WordPress.  Sometimes you want a category to represent more than just a basic post subject classification -- you may want a category of your blog to represent a link and writeup to an external site or may want to display their posts in a different way.  On this blog, I've added a "Quick Tips" category which are very short posts with tiny snippets of code that (quickly) detail how to do something simple.  I want those posts to display on listing pages, but not on the homepage.  I've seen some treacherous code to accomplish this feat, but luckily I've found a much cleaner way to prevent posts in a given category from displaying on a homepage.

The WordPress PHP

WordPress' API provides a pre_get_posts action which allows for additional pre-query logic:

// No "Quick Tips" on the homepage
function preventHomepageTips($query) {
	if($query->is_home() && $query->is_main_query()) {
		$query->set('cat', '-40'); // 40 is Quick Tips's category ID
	}
}
add_action('pre_get_posts', 'preventHomepageTips');

The custom function above is added as a WordPress action, usually within your functions.php file.  It's important you know the ID of the category or categories you don't want displaying in the main loop.  A dash is placed before said category ID.  To prevent multiple categories, separate them by commas:

$query->set('cat', '-40,-52');

If you simply want to prevent posts from displaying on the homepage but don't want to effect subsequent archive pages, you could add another hackish conditional:

if($query->is_home() && $query->is_main_query() && $_SERVER['REQUEST_URI'] == '/') {

This is an incredibly useful snippet that can be used for any number of purposes.  Chris Coyier, for example, uses a special category for his "Hot Links" posts (links to external websites) which he obviously doesn't displaying within the main loop.  There you have it though -- preventing posts in a category from displaying the loop!

Recent Features

  • By
    Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?

  • By
    5 Awesome New Mozilla Technologies You’ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • By
    9 Mind-Blowing WebGL Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted 9 mind-blowing demos.  Another technology available...

  • By
    Introducing LazyLoad 2.0

    While improvements in browsers means more cool APIs for us to play with, it also means we need to maintain existing code.  With Firefox 4's release came news that my MooTools LazyLoad plugin was not intercepting image loading -- the images were loading regardless of...

Discussion

  1. You the man.

  2. Hi there –

    I found your page while searching for something very similar to what you’ve done here, but instead of preventing a post from showing up on the homepage, I want to prevent it from showing up in a specific category.

    Here’s the thing: I have a category Cuisines and subcategories Italian, French, Spanish, etc. Each of those subcats has various recipes, as well as a post for the subcat itself (e.g., check out my Italian recipes!) I want the latter not to show up in the subcat, because obviously if you click them, they just link back to the same page you’re already on. I wonder if there’s an easy way to modify your code to accomplish this?

  3. Perfect! This is exactly what I was looking for! Thanks for sharing!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!