I've got a Woocommerce site that uses categories and products within those categories but how do I get my search form to only display results of products within the category the user currently is in. I've looked around and the closest I've got to is this:


function shop_filter_cat($query) {
  if (!is_admin() && is_post_type_archive( 'product' ) && $query >is_main_query()) {
    $query->set('tax_query', array(
                array ('taxonomy' => 'product_cat',
                                   'field' => 'slug',
                                    'terms' => 'type-1'

And this is brilliant but I don't want to specify the category as 'terms' => 'type-1' I want the search to only show results of products that the user is currently in e.g. if the user selects t-shirts as a category and then searches for 'batman' i want results to only show batman t-shirt results and not batman hat results or any other results. Thank you so much in advance!!

HTML (my searchform.php):

<form role="search" method="get" class="search-form" action="<?php echo home_url(); ?>">

    <input type='textbox' name="s" class="form-control form-inline" id="item-search" value="<?php the_search_query();?>" placeholder="Search items.."/>
    <button class="item-search-btn"><span class="glyphicon glyphicon-search"></button>
      if ( function_exists( 'woocommerce_product_search' ) ) {
        echo woocommerce_product_search( array( 'limit' => 40 ) );
  • 1
    If you remove the action property of the form, it will post to itself - in this case a category archive - and WordPress will indeed only search in that category. May 9 '16 at 16:54
  • @TheDeadMedic so I don't need to use the pre_get_post function above?
    – T.Doe
    May 9 '16 at 17:02
  • 1
    If that solution works to your requirements, then no that's it! May 9 '16 at 17:03
  • How did you go with this @T.Doe?
    – Tim Malone
    Jul 6 '16 at 4:05

You don't need to! With a little understanding of how URLs and query vars work, we can do this entirely within the URL of the page, with no additional PHP code

First we have a URL:


Then we have a rewrite rule. The rule has a regex pattern that matches the URL, and a second bit that says were all the bits that match go, e.g.

"/abc/(.+)" -> "index.php?p=$match[1]"

This gives converts /abc/123 into index.php?p=123, which becomes WP_Query( array( 'p' => 123 ) ). WordPress then takes a look at the new WP_Query, makes it the main query ( the post loop ), and does a little bit of logic to decide which template to load. In this case it sees the p and declares this to be a singular page, so single.php will probably be loaded. See the template hierarchy for more details on that.

The important part is, we can pass extra parameters! /abc/123 matches, but so does /abc/123?s=test. This results in index.php?p=123&s=test, and WP_Query( array( 'p' => 123, 's' => 'test')).

Since s is the search query param, we can use this new found knowledge to do what you need!

So lets say your user is in the tshrit category, which has the URL:


We can use


Now we have a search of the tshirts product category for 'test'. This is great because now we have a URL that's always a search of that category. We could have tracked the tshirt category in a cookie or a session, but this would lead to a single URL showing multiple things to different people, and all the caching problems and SEO issues that come with it.

How would we build the search form?

<form action="" method="get">
    <input type="text" name="s" value="<?php echo get_search_query(); ?>">

Notice 2 things:

  • The text input has the name s
  • We want to submit the page we're currently on. We could do PHP voodoo to get the current URL, but we don't need to, so we set the action attribute to nothing, and let the browser handle it
  • I specified the value so that you know what it was you just searched for using get_search_query
  • This won't work with POST

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.