How it Works
This plugin will index all posts in your Multisite Install with custom fields (so you can use meta_query) and terms (for tax_query). The posts index is going to be stored in separate database tables wp_network_posts and wp_network_postmeta, the terms index will be stored in wp_network_terms, wp_network_term_relationships and wp_network_term_taxonomy.
These tables are identical to the original WordPress tables, but also have a BLOG_ID column.
The whole indexing process is performed in the background with the help of WordPress Cron – that’s why you’ll never face any performance issues even if your network has hundreds of sites and thousands of posts.
Once the index is ready, you can pull any content from it using Network_Query or network_get_terms(). For example, you can order by the result in any way you want or perform an additional search in it.
Below, let me guide you through the installation process, and then we take a look at examples.
Installation
Once you upload the plugin to your website, please go to Network Admin > Plugins and Network Activate it from that page.
By default, the plugin will index a post only when it is published or updated. If you want to add to the index your old posts, please go to Settings > Index and then switch to the “Rebuild Index” tab.

But before rebuilding the index, you can also configure what post types and post statuses you would like to index:

You can configure it for specific sites as well.

When your posts appear in the index, you can see them in the Network Dashboard:

Plus, in the plugin settings, you can also enable the “Network Posts” page, which will appear in the network dashboard, where you can manage posts across all indexed sites in your WordPress multisite network. You can read more about this feature here.
So, How to Get All Network Posts in a One Query?
Now, let’s get straight to the examples.
1. Get posts just like with WP_Query
Let me present to you the Network_Query class — it works just like a standard WP_Query class, but for all WordPress Multisite blogs (sub-sites) at the same time, and more importantly, it supports all the same parameters (documentation) + blog_id parameter (I will show how this parameter works in the next example).
Now, let’s begin with something simple.
$network_q = new Network_Query( 'posts_per_page=5' ); // display 5 latest global posts
if( $network_q->have_posts() ) :
// run the loop for each post
while( $network_q->have_posts() ) : $network_q->the_post();
// we just get post titles here
// but you can print_r( $network_q->post ) to view all post data
echo '<h3>' . $network_q->post->post_title . '</h3>';
endwhile;
else :
echo 'No posts found for this criteria';
endif;Something a little more interesting.
<?php
// Network_Query parameters
$args = array(
'posts_per_page' => 14,
'orderby' => 'name',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'featured', // we display only posts with custom field 'featured' = 'on'
'value' => 'on'
)
)
);
$network_q = new Network_Query( $args );
// if there are posts, then print <ul>
if( $network_q->have_posts() ) :
?><ul><?php
// run the loop
while( $network_q->have_posts() ) : $network_q->the_post();
// the get_permalink() function won't work without switch_to_blog()
// you can use network_get_permalink() instead but it is a little slower
switch_to_blog( $network_q->post->BLOG_ID );
// you can obtain the post title from $network_q->post object
?>
<li class="post-<?php echo $network_q->post->ID ?> blog-<?php echo $network_q->post->BLOG_ID ?>">
<a href="<?php echo get_permalink( $network_q->post->ID ) ?>"><?php echo $network_q->post->post_title ?></a>
</li>
<?php
// restore_current_blog() to switch to the previous (!) website
restore_current_blog();
endwhile;
?></ul><?php
endif;
network_reset_postdata(); // add it after the loop if you plan to use Network_Query multiple times on the pageSome comments:
- In the loop, we obtain
$network_q->postobject — it has allWP_Postobject parameters with$network_q->post->BLOG_ID, the ID of the network blog. - If you need to do something and the
WP_Postobject is not enough for your purposes, then use theswitch_to_blog()function – it allows you to run any WordPress loop functions, likeget_the_post_thumbnail(),get_permalink()etc. Just do not forget to pass a Post ID into these functions. - We need
restore_current_blog()to cancel theswitch_to_blog()effect, the function switches us to the previous blog — so use it in a loop. - The
network_reset_postdata()function works similarly towp_reset_postdata().
2. Search across all blogs
The next very important feature of the plugin is the global search. You can search all sites not only for posts and pages (post types), but you can also perform a search for categories and post tags (taxonomies).
Starting with the plugin version 4.4, it is no longer required to do anything in the code in order to enable the global search. Just go to Settings > Index and then proceed to the Globals tab.

You can also use WordPress’s default search engine across the whole network. I mean s parameter of the Network_Query class.
$args = array(
's' => 'Search query'
);
$query_search = new Network_Query( $args );It is also possible to search for posts by their custom field values — meta_query parameter of the Network_Query class will help you with that.
$args = array(
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'key1', // key1 must contain "wordcamp"
'value' => 'wordcamp',
'compare' => 'LIKE'
),
array(
'key' => 'key2', // OR key2 must contain "wordpress"
'value' => 'wordpress'
'compare' => 'LIKE'
)
)
);
$query_search = new Network_Query( $args );Searching terms by part of their titles and descriptions looks like this:
$network_cats = network_get_terms( 'category', 'description__like=wordcamp' );$network_cats = network_get_terms( 'category', 'name__like=wordpress' );In my full global search tutorial, I explain each of the above examples and show how to replace the default WordPress search form and search results page with the global ones.
Everything else is like in WP_Query.
3. Get posts from the specific blogs in a network. Choose post types to query
In these examples, we are going to work with post_type and blog_id parameters of the Network_Query class, but I would like to remind you that you can exclude specific blogs and post types in plugin settings as well; I described it in the installation part.
$args = array( 'post_type' => array( 'post', 'page' ) ); // get only posts and pages$args = array(
'post_type' => 'post', // only posts
'blog_id' => array( 1, 3 ) // only from blogs 1 and 3
);Do not know where to get a site ID? Not a problem — my plugin will show a Site ID column in your network dashboard, the Sites > All sites page.

You should also know one thing about the post_type query parameter — it will only work for indexed post types. If a post type is excluded from the index in plugin settings (check the installation part), the post_type parameter will ignore it as well.
4. Query network posts with pagination
When you want to show posts from all blogs, it is very important to implement pagination. Below is the simplest way how you can do it:
global $wp_query;
// get the current page number from $wp_query, I mean the URL parameter, i.e. /page/2
$current_page = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; // you can use $wp_query->query['paged'] as well
// similiar to query_posts()
$network_q_posts = network_query_posts( array( 'posts_per_page' => 3, 'paged' => $current_page ) );
// run the loop
foreach( $network_q_posts as $network_q_post ) :
// we need it to work with get_the_post_thumbnail() and get_permalink()
switch_to_blog( $network_q_post->BLOG_ID );
echo '<li>' . get_the_post_thumbnail( $network_q_post->ID ) . '<a href="' . get_permalink( $network_q_post->ID ) . '">' . $network_q_post->post_title . '</a></li>';
// switch back
restore_current_blog();
endforeach;
// we should change the global $wp_query value to work correctly with pagination
$wp_query = $GLOBALS[ 'network_query' ];
// I use the popular WP PageNavi plugin
wp_pagenavi();
// reset the $wp_query
wp_reset_query();If you have problems with this example, you can read a detailed tutorial here.
5. Get categories and post tags globally using get_terms() analog
My plugin allows you to get not only post types but taxonomy terms as well. It can be implemented easily with network_get_terms() (click the link to view the detailed tutorial).
Here is a simple example:
$network_categories = network_get_terms( 'category', 'orderby=name&hide_empty=0' );
if( $network_categories ){
echo '<select>';
foreach ( $network_categories as $network_category ){
echo "<option value='{$network_category->term_id}'>{$network_category->name}</option>";
}
echo '</select>';
}
/*
in this example is obvious that
$network_category->name - category name,
$network_category->term_id - category global unique ID across the network
but you can get more info about the category if you look into the object using
print_r( $network_category );
*/