I recently received a request from a client who wanted to have their WordPress loop visible on the home page as well as on a “blog” page. The posts that would be displayed on the home page would be slightly different from those on the blog page.

The desired effect can be achieved using the following process.

First, duplicate the your default loop template file, usually index.php and rename it to blog-page.php

At the top of this file, insert this comment so that any static page can use this template file by setting the template drop down by editing the page in the WordPress dashboard.

 	/*  	Template Name: Blog Page    */

Next set up an alternate post query in the template file by creating a new instance of WP_Query. This is a better approach than calling query_posts(), since query_posts() alters the global query variables, which will have some undesirable results( e.g. your “blog” page won’t get the current-menu-item class applied to it in the navigation, so the link item can’t be highlighted).

Use the code below to create a new instance of WP_Query. Pass in the following default query vars so that post paging works correctly. It might also be helpful to run your alternate query variables through a filter, so you can hook into this query in a plugin or in the functions.php file and further customize it.

global $paged; 
$alternate_blog_query_vars = apply_filters(
$alternate_query = new WP_Query($alternate_blog_query_vars);

Next, alter the loop functions to use the $alternate_query instead of the main query. Look for the calls to have_posts(), and the_post(), and change them so it looks like this:

if ($alternate_query->have_posts()) :
	while ($alternate_query->have_posts()) : $alternate_query->the_post();
		<!-- loop code goes in here -->

That should just about do it. You can now set any page in your WordPress website to display the posts that would normally appear only only the home page. You can also use the filter ‘alternate_blog_query_vars’ to modify the posts that are shown on these pages.

The only problem I ran into with this approach is that the wp-paginate plugin wouldn’t recognize that this post needed to be paginated, because it only considers the main loop when it is rendering its pagination buttons. I fixed this by temporarily making my custom query the main query, then resetting it once the pagination was rendered so that nothing would break further down in the code.

  if(function_exists('wp_paginate')) {
 	global $wp_query;
  	$tmp_query = $wp_query; 
	$wp_query = $alternate_query;	
	$wp_query = $tmp_query;

Easy as pie!