How to Use Global Search in WordPress Multisite

In this step-by-step tutorial, I will guide you through the process of creating a search engine that allows you to search across all blogs within your WordPress multisite network.

The methods described here will also work great for WooCommerce products.

The only thing that I need you to keep in mind is that you’re really using a WordPress multisite network; if you have just a network of standalone WordPress installs, it is not what we need.

This method is also best suited for Classic and Hybrid WordPress themes, not for the Block themes (yet). If you need it to be adopted for a block theme, let me know in the comments below.

Also, please keep in mind that the Network_Query class is not available in WordPress Multisite by default; you need to install my plugin if you want to use it.

A Simple Example of Implementing the Global Search

Let’s start with the code snippet, which you can use wherever you want to display the search result:

/**
 * @snippet A global search example
 * @author Misha Rudrastyh
 * @url https://rudrastyh.com/wordpress/search-across-wp-multisite.html#example
 */
$args = array(
	's' => 'wordcamp asia', // the search query is here
	'posts_per_page' => -1
);

$query_search = new Network_Query( $args );

if( $query_search->have_posts() ) :

	while( $query_search->have_posts() ) : $query_search->the_post();

		echo '<h2>' . $query_search->post->post_title . '</h2>';

	endwhile;

else :
	echo '<p>Nothing found for your search criteria.</p>';
endif;

As I already mentioned before, the Network_Query class is a part of my multisite search plugin; it is similar to the original WP_Query class and accepts all the same parameters, but works for all blogs in your multisite network.

If this example is not crystal clear for you, let’s continue to a step-by-step global search engine implementation below.

Creating a Global Search Results Page

In this part of the tutorial, we will work specifically with a PHP template for our WordPress theme. Since it is a PHP template, we can say that we’re working with a classic or hybrid theme here.

1. Creating a WordPress page template where we display global search results

The long story short, you have to open your current theme folder (it would be better if you’re using a WordPress child theme) and create a file with a custom name there.

Create a WordPress page template for global multisite search results
You can choose almost any name for your file, but please avoid words search.php, searchform.php; and it would be even better if you place your file inside page-templates folder.

Once you’ve created your file, please define it as a page template. To do that, open your file and add the piece of code below at the beginning.

<?php
/*
 * Template name: Global Search
 */

The first step is almost done! Now let’s create a Page in WordPress admin, Pages > Add new, and select this new template there.

WordPress Multisite global search page template
Here, I created a new “Global Search” page and applied our custom page template to it. As you can see, I am using the block editor here, which means that I am using the hybrid theme. But using the Classic Editor is totally fine as well.

2. Displaying global search results

In this example, we will add the code from the first example in this tutorial to our page template code.

<?php
/*
 * Template name: Global Search
 */
get_header();

$args = array(
	's' => 'wordcamp asia', // the search query is here
	'posts_per_page' => -1,
);

$query_search = new Network_Query( $args );

if( $query_search->have_posts() ) :

	while( $query_search->have_posts() ) : $query_search->the_post();

		echo '<h2>' . $query_search->post->post_title . '</h2>';

	endwhile;

else :
	echo '<p>Nothing found for your search criteria.</p>';
endif;

get_footer();

The example is still over-simplified:

  • It is better to use the_title() or get_the_title() to display post titles, but here, I am using it straight from the WP_Post object, which is not perfect, to say the least. We must have at least the esc_html() function, but we will come back to it a little bit later.
  • I have also added get_header() and get_footer() functions here.
  • As you can see, I completely skipped the pagination part by adding posts_per_page => -1, but you can read more about it in a separate tutorial.

Let’s continue reading and improving our WordPress Multisite global search functionality.

3. Creating a search form

Ok, we have the search results page, but we can see that the page itself is kind of static and connected to a static search query.

To fix that, we need to create a search form, where its action attribute should point to our global search results page.

<form action="<?php echo site_url( 'network-search' ) ?>" method="GET">
	<input type="text" name="q" />
	<button>Search</button>
</form>

The next thing is to modify the $args array of Network_Query.

$search_query = ! empty( $_GET[ 'q' ] ) ? $_GET[ 'q' ] : '';

$args = array(
	's' => $search_query,
	'posts_per_page' => -1
);

The complete code will look like this:

<?php
/*
 * Template name: Global Search
 */
get_header();

$search_query = ! empty( $_GET[ 'q' ] ) ? $_GET[ 'q' ] : '';

?>
	<form action="<?php echo site_url( 'network-search' ) ?>" method="GET">
		<input type="text" name="q" value="<?php echo esc_attr( $search_query ) ?>" />
		<button>Search</button>
	</form>
<?php

$args = array(
	's' => $search_query,
	'posts_per_page' => -1
);

$query_search = new Network_Query( $args );

if( $query_search->have_posts() ) :

	while( $query_search->have_posts() ) : $query_search->the_post();

		echo '<h2>' . $query_search->post->post_title . '</h2>';

	endwhile;

else :
	echo '<p>Nothing found for your search criteria.</p>';
endif;

get_footer();

You can also check if the search query is provided; otherwise, the Network_Query will return just the latest posts:

if( $search_query ) {

4. Displaying posts’ data (how to get links to posts, display post thumbnails, etc.)

As you can see in the previous example, we displayed only post titles, and not in 100% correct way, but it is also possible to display… well.. anything you want 🙂 You can use regular WordPress functions for this.

Let’s try to display permalinks, post images, and post dates.

while( $query_search->have_posts() ) : $query_search->the_post();
	
	// we need to switch to a specific blog in order WordPress functions to work
	switch_to_blog( $query_search->post->BLOG_ID );
		
	// post titles
	echo '<h2>' . get_the_title( $query_search->post->ID ) . '</h2>';
	
	// post thumbnails
	echo get_the_post_thumbnail( $query_search->post->ID, 'medium' );

	// post date
	echo '<time>' . get_the_time( 'j F, Y', $query_search->post->ID ) . '</time>';
	
	// permalinks
	echo '<a href="' . get_permalink( $query_search->post->ID ) . '">Read more</a>';

	restore_current_blog();

endwhile;

The long story short, here is what we’re doing in the example above:

  1. When we start to display the body of a post, we need to switch to the subsite this post belongs to by using switch_to_blog(). It is not ideal to do it repeatedly a lot of times (if you have a lot of posts in your search results); in that case, you can read about the performance.
  2. After that, we can use any standard WordPress loop functions, get_the_title(), get_the_post_thumbnail(), get_the_time(), get_permalink(), etc., the only requirement is that the function must accept a post ID as an argument.

That’s it, our WordPress multisite search engine is ready!

Search Posts by Their Custom Field Values

The thing is that sometimes we need to search posts globally in a multisite network; however, not in a standard way, but using custom field values. Sure thing, my Network_Query plugin allows you to do that.

Probably, you’re already familiar with the meta_query argument, below is an example:

$args = array(
	'posts_per_page'  => -1, // let's get all posts
	'meta_query' => array(
		'relation' => 'OR',
		array(
			'key'     => 'key1', // key1 must contain "wordcamp"
			'value'   => 'wordcamp',
			'compare' => 'LIKE'
		),
		array(
			'key'     => 'key2', // OR key2 must contain "wp"
			'value'   => 'london'
			'compare' => 'LIKE'
		)
	)
);

$query_search = new Network_Query( $args );

Search Terms by Part of Their Titles and Descriptions

The plugin allows you to search not only posts (and custom post types) globally, but also categories, tags, and custom taxonomy terms. It can be achieved with a built-in function network_get_terms(); by the way, you can read more about it here.

Below are the examples:

// search for categories whose descriptions contain "wordcamp"
$network_cats = network_get_terms( 'category', 'description_like=wordcamp' );
 
if( $network_cats ){
	foreach ( $network_cats as $network_cat ){
		echo $network_cat->name;
	}
}
// search for post tags whose names contain "wp"
$network_post_tags = network_get_terms( 'post_tag', 'name_like=wp' );
 
if( $network_post_tags ){
	foreach ( $network_post_tags as $network_post_tag ){
		echo $network_post_tag->name;
	}
}

If you have any questions about the global search implementation, feel free to ask in the comments section below.

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 15 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X