How to Add an Advanced Search to Your WordPress Site

Contributing Editor

The majority of WordPress search forms set a single querystring parameter named ‘s’:

<form method="get" action="<?php bloginfo('url'); ?>">
<fieldset>
<input type="text" name="s" value="" placeholder="search&hellip;" maxlength="50" required="required" />
<button type="submit">Search</button>
</fieldset>
</form>

There’s nothing wrong with that and I thought it was the only option for many, many years.

However, more advanced queries are possible without the aid of plugins (although plenty are available). Deep within the WordPress core, the application parses several other querystring parameters and uses them to return a more focused set of search results. There is some rudimentary documentation which lists the parameter names:

  • attachment
  • attachment_id
  • author
  • author_name
  • cat
  • category_name
  • comments_popup
  • day
  • error
  • feed
  • hour
  • m
  • minute
  • monthnum
  • name
  • p
  • page_id
  • paged
  • pagename
  • post_parent
  • post_type
  • preview
  • second
  • static
  • subpost
  • subpost_id
  • tag
  • tag_id
  • tb
  • w
  • year

I’m not convinced all these work as expected and some are a little pointless, but they match the parameters you can pass to WP_Query. We can therefore create an advanced search form using HTML with a smidgen of PHP to automate the options.

Refine Search by Category

You can limit results to a category by passing its slug to the category_name parameter, e.g.


http://yoursite.com/?s=search+term&category_name=kittens

Our search form can allow the user to refine their search to specific categories:

<form method="get" action="<?php bloginfo('url'); ?>">
<fieldset>
<input type="text" name="s" value="" placeholder="search&hellip;" maxlength="50" required="required" />
<select name="category_name">
<option value="">all categories</option>
<option value="kittens">cute kittens</option>
<option value="puppies">adorable puppies</option>
</select>
<button type="submit">Search</button>
</fieldset>
</form>

If you’d rather list all categories, add the following code between the <select> and </select> tags:

<?php
// generate list of categories
$categories = get_categories();
foreach ($categories as $category) {
	echo '<option value="', $category->slug, '">', $category->name, "</option>\n";
}
?>

Refine Search by Tag

Search results can be limited to a tag by passing its slug to the tag parameter, e.g.


http://yoursite.com/?s=search+term&tag=cockroach

Your search from could therefore limit results to certain tags, e.g.

<form method="get" action="<?php bloginfo('url'); ?>">
<fieldset>
<input type="text" name="s" value="" placeholder="search&hellip;" maxlength="50" required="required" />
<select name="tag">
<option value="">any tag</option>
<option value="cockroach">cockroaches</option>
<option value="snake">snakes</option>
</select>
<button type="submit">Search</button>
</fieldset>
</form>

Similarly, you can generate a list of all tags for the select field:

<?php
// generate list of tags
$tags = get_tags();
foreach ($tags as $tag) {
	echo '<option value="', $tag->slug, '">', $tag->name, "</option>\n";
}
?>

Advancing Advanced Search

What if you want to refine the search by multiple values? For example, the user could choose two or more tags and resulting pages must have them all set. We cannot achieve this using URL parameters alone but let’s start by defining an HTML search form:

<form method="get" action="<?php bloginfo('url'); ?>">
<fieldset>
<input type="text" name="s" value="" placeholder="search&hellip;" maxlength="50" required="required" />
<p>Refine search to posts containing chosen tags:</p>
<?php
// generate list of tags
$tags = get_tags();
foreach ($tags as $tag) {
	echo 
		'<label>',
		'<input type="checkbox" name="taglist[]" value="',  $tag->slug, '" /> ',
		$tag->name,
		"</label>\n";
}
?>
<button type="submit">Search</button>
</fieldset>
</form>

Note that I’ve used a PHP array parameter named taglist. You can use any name other than those already reserved by WordPress (see the list above).

We can now intercept a search submission in our WordPress theme’s functions.php file. The advanced_search_query function detects whether a search is active then sets the WP_Query tag_slug__and parameter accordingly.

// advanced search functionality
function advanced_search_query($query) {

	if($query->is_search()) {
		
		// tag search
		if (isset($_GET['taglist']) && is_array($_GET['taglist'])) {
			$query->set('tag_slug__and', $_GET['taglist']);
		}
	
		return $query;
	}

}

Finally, we use the pre_get_posts action hook to run our advanced_search_query function before a query is executed:

add_action('pre_get_posts', 'advanced_search_query', 1000);

Adding advanced search facilities to WordPress is remarkably easy yet few developers realize it’s possible … perhaps because documentation and examples are a little sparse. I discovered it by accident so I hope you find this code useful in your next WordPress project.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • sujhon

    nice and helpfull article…. tnk u for shareing

  • Anonymous

    you could also use the posts_search action to adjust the SQL query used in the search. For example one of our sites wanted to search posts by tag name, without listing the tags. So I made it search for tags using there search term and displayed the posts within them tags

  • Anonymous

    will try in my next project.
    btw, thanks for the code.

  • Anonymous

    Thanks. I’ve had to build advanced search functions and forms this year and I’ve saved this as a future reference. Any developer working with custom post types will want to understand this if they would like to see their cpt included in search results.

    BTW, if you feel that the codex is lacking, please take time to contribute! Don’t forget that WordPress only exists because developers like you contribute wherever possible. You could be the one person who makes all the difference on this particular subject. More info on how to contribute to the codex here:
    http://codex.wordpress.org/Contributing_to_WordPress#Documentation

  • adechriz

    very clear explanation,
    I have been practicing it and got this permalink on search result page : http://domain.com/?s=searchquery&taxonomy1=term1&taxonomy2=term2&taxonomy3=term3

    I have not entered ‘pre_get_posts’ function on function.php because you are using tags in this article while i’m using custom taxonomy?

    please tell me how i can do this?