I know many people asked for this question but I didn't find a proper way to do it. How to add a simple meta_query (product_cat) before the execution of the shop page's query.

Maybe by using a filter ?



3 Answers 3


The shop page is actually an archive page for posts of type 'product'. Its template is in woocommerce/archive-product.php.

You need to use the pre_get_posts action to preprocess the query before the loop, conditional_tags to recognize that you are in the product archive page, and a taxonomy query to filter the product categories, which belong to the taxonomy 'product_cat'.

For example, the following (placed in your theme's functions.php or in a plugin) will display only products with product category 'type-1':


 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'

You can also exclude categories by using 'operator' => NOT IN, and 'terms' can be an array of product category slugs.

A good introduction to query customization is http://www.billerickson.net/customize-the-wordpress-query/


This worked for me:

[product_category category="YOUR CATEGORY" per_page="8" columns="3" orderby="date" order="desc"]

If you want to show products from a specific category on your shop page you can insert the below code in your themes function.php file.

// Execute before the loop starte
add_action( 'woocommerce_before_shop_loop', 'techlyse_before_action', 15 );
function techlyse_before_action() {
    //To ensure Shop Page
    if ( is_shop() ) {
        $query_args['tax_query'] =  array(
                'taxonomy' => 'product_cat',   
                'field' => 'id',  //If you want the category slug you pass slug instead of id and 1330 instead of category slug. 
                'terms' => 1330 
        query_posts( $query_args );

// Execute after the loop ends
add_action( 'woocommerce_after_shop_loop', 'techlyse_after_action', 15 );
function techlyse_after_action() {
    //To ensure Shop Page
    if ( is_shop() ) {
        //Reset the Query after Loop
  • This is not the right way to do it but I found this helpful for another situation so thank you.
    – MarcGuay
    Nov 23, 2021 at 19:52

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.