Custom Post Types on Homepage – Correct way

There are numerous tutorials on the web about showing Custom Post types on Homepage. WordPress by default shows only Posts on the homepage. Custom Post types are not automatically shown on the homepage or the feed. Now while searching for the method you must have seen the following code everywhere:

[php]
add_filter( ‘pre_get_posts’, ‘my_get_posts’ );
function my_get_posts( $query ) {
if ( is_home() && false == $query->query_vars[‘suppress_filters’] )
$query->set( ‘post_type’, array( ‘post’, ‘page’, ‘album’, ‘movie’, ‘quote’, ‘attachment’ ) );
return $query;
}
[/php]

This code you can put in either your theme’s function.php file or a custom plugin file you created for your site. This code is all good but not many sites will tell you that this might break just any other loop that you might be using on your homepage. For instance if your homepage is showing a custom menu, then they will stop working. This code infact converted all my custom loop widgets to use this very loop. So practically all widgets started showing the same posts as were shown on the homepage and my custom menu disappeared.

So my suggestion is to not to use this code to show custom post types on your homepage. Stephen Harris in the comments has suggested an even better solution. Here is the code

add_filter( 'pre_get_posts', 'my_get_posts' );
function my_get_posts( $query ) {
	if ( is_home() && $query->is_main_query())
		$query->set( 'post_type', array( 'post', 'page', 'album', 'movie', 'quote', 'attachment' ) );
	return $query;
}

In the above code, we check that the query we want to modify is the main query or not. All other queries are left untouched in this process. Since is_main_query() function was introduced with WordPress 3.3, so the above method won’t work with versions below it.

I have removed my original alternative in wake of the above solution as it is good enough and does not require you to modify the queries. You can check the full solution mentioned at WordPress StackExchange.

4 Comments


  1. Simply Perfect. I was stumbling across this issue, my navigation menus disappeared while i was using the wrong code, but the Stephen’s code solution is better & worked like a charm.

    Thanks.
    Hash


  2. I’m actually using WP_Query() and then calling wp_reset_postdata(), which doesn’t destroy the last query like wp_reset_query() does


  3. Hi Navjot, great post but I have to disagree. The first option is much better as you don’t have to perform another query. However, the problem is that you shouldn’t (and many websites do!) check for (un)-‘supressed filters’.

    Instead you should check it ‘is (the) main query’: see this WordPress SE answer: http://wordpress.stackexchange.com/questions/45250/cannot-override-post-types-in-wp-query/45256#45256

    The reason why you should not use the check for ‘supressed filters’ is that this returns true for every WP_Query query, and even get_posts if manually set. As you mentioned, if you have a second loop on your home page – the above filter will interfer with it.

    Thanks again for the post!


  4. I’m actually using WP_Query() and then calling wp_reset_postdata(), which doesn’t destroy the last query like wp_reset_query() does. I suppose it depends on what you’re doing, but this process doesn’t interfere with other calls.

Comments are closed.