I’m using WooCommerce and WooCommerce Product Categories widget to browse my products. But I need filter all the products in the shop by a product attribute I created before and keep browsing with the widget. The solution I found is using a query string param like "myAtt=my-att-slug" to show only the products with the slug previously mentioned.

In this way, I'm using URLs like:

  • www.mysite.com/shop?myAtt=my-att-slug
  • www.mysite.com/product-category/category1?myAtt=my-att-slug
  • www.mysite.com/product-category/category1/subcategory11?myAtt=my-att-slug
  • www.mysite.com/product-category/category2?myAtt=my-att-slug

At this point, I'm filtering the products by two taxonomies: product_cat and myAttr.

To accomplish that, I modified the WP_Query object and added a taxonomy filter to the query. It works great for the products but not for the product category list rendered by the widget. It seems like it's using another WP_Query instance or query values.

How can use the same WP_Query instance for the shop and the widget?

Thanks for any help!!!

The following is how I modified the WP_Query instances and it works great. And I hope is the right solution in WordPress way. I did the following in the function.php on my theme:

First, I registered my custom variable that I use in the query string param.

function add_query_vars_filter( $vars ){
    $vars[] = 'myAttr';
    return $vars;
add_action( 'query_vars', 'add_query_vars_filter' );

Next, I filtered the shop query...

function filter_pre_get_posts( $wp_query ) {
    if (!is_archive() || !$wp_query->is_main_query() ) {

    $myAttr = get_query_var('myAttr');
    if (isSet($myAttr ) && !empty($myAttr )) {
        $wp_query->set('tax_query', array(
                'taxonomy' => 'pa_my-attr',
                'field' => 'slug',
                'terms' => $myAttr ,
                'include_children' => true,
                'operator' => 'IN'
add_action('pre_get_posts', 'filter_pre_get_posts' );

Thanks again!

  • not much point in asking questions about your code without showing it Commented Sep 19, 2016 at 17:15
  • you're right... I just edited the question Commented Sep 19, 2016 at 17:23
  • so this is the code you use on the page, and you want it to work for the widget aswell? Commented Sep 19, 2016 at 17:54
  • @MarkKaplun at first I thought they both use the same object but not. Then, is possible to filter the action where WP_Query is created for the widget? Thanks again. Commented Sep 20, 2016 at 1:12

1 Answer 1


The reasons your pre_get_posts filter does not work on the widget are

  1. the condition !$wp_query->is_main_query() makes the filter handle only the main query and nothing else

  2. Your special parameter myattr is "self populating" only on the main query but it is not propagating automatically to other queries.

To make it work on the widget, the first thing you will need to do is remove the conditions that bails out if it is not the mail query (your attribute should not be set in other queries so should not make a difference).

Then it gets complicated. you can get the attribute from the mail query by changing get_query_var('myattr') into global $wp_the_query; $wp_the_query->get('myattr','')

but in this case it will affect all queries on the page, which might be ok depending on what you have there

The other option is to find a way to change the query of the widgets itself and inject your attribute, which seems pointless as the actuall change you do to the query is simple, but might be worth it if you want to maintain the changes in only one place

  • thanks @mark-kaplun your answer set me in the right direction Commented Sep 20, 2016 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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