I believe this issue should now be resolved in core WooCommerce.

We love WooCommerce around here, but occasionally we run into a bug that hasn’t yet been merged into the core codebase. We set up a storefront many months ago for Lemon Dogs Tacos and Lemonade wherein they change their stock quite regularly. Because of this changing stock, the WooCommerce core setting to hide out of stock items came in very handy!

More recently we configured a new shop page that breaks down the products into categories on a single page for easier selection of products by customers. The page was built using WooCommerce product category shortcodes like this:

[product_category category="holiday" per_page="10" columns="5" orderby="modified" order="ASC"]

We quickly discovered somethinjg amiss. When we set per_page to the number we wanted (maybe 5 or 10 products in that category) it would only show a few of them! Yet if we set it to 100 products they would all show up.

After much frustration we finally narrowed it down to the stock status setting. It appears that the shortcode obeys the ‘hide out of stock items’ setting only for visibility, but not when it comes to counting the products! Therefore if we have 35 products in a category, with only 10 of them are in stock (but not the latest 10, depending on how they’re sorted), we would only get the in-stock products from the first 10 products out of all 35. The remaining 25 would not be checked for in-stock products and therefore they wouldn’t be displayed.

As a workaround we simply set per_page to a number equating the total number of products in the store, although in hindsight, I suppose the total number of products in the category should do the trick. Shortly after reporting the bug, WooCommerce staff supplied us with code to be thrown in functions.php that will fix the bug so we can set per_page to the correct number that we want. Here it is!

function custom_woocommerce_shortcode_products_query( $args ) {
   if ( 'yes' == get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
     $args['meta_query'][] = array(
       'key' => '_stock_status',
       'value' => 'instock',
       'compare' => 'IN'
   return $args;
add_filter( 'woocommerce_shortcode_products_query', 'custom_woocommerce_shortcode_products_query' );

About Jordan Schelew

Jordan has been working with computers, security, and network systems since the 90s and is a managing partner at Websavers Inc. As a founder of the company, he's been in the web tech space for over 15 years.

Leave a Comment