How to Hide Out of Stock Products
By default, when a product is out of stock it is still going to be displayed on your shop pages, but instead of “Add to cart” button there is going to be “Read more” button, like this:

But if you are reading this, I suppose you do not want them to be displayed, right? 🤔
Hide Out of Stock Items Everywhere
First things first – WooCommerce has a special options which allows to hide these out of stock products everywhere on the website. Just go to WooCommerce > Settings > Products Tab > Inventory.

All the products still will be available by the direct URL which is great, because somebody could add a product to his browser favourites. But will be hidden on:
- shop page,
- product category and product tag archive pages,
- search results,
- related products, upsells and cross-sell sections.
Hide Out of Stock Products from Specific Locations, for example from Related Products section only
Products has a meta key _stock_status
which can be instock
or outofstock
.
I’ve seen an example on the internet, where a guy suggested to pass meta_query
parameter to the woocommerce_output_related_products_args
filter hook. I want to clarify one moment – this hook is not about passing args into WP_Query
. The filter hook supports only posts_per_page
, columns
, orderby
and order
parameters. That’s all!
So if you really need to hide your out of stock items from some specific places on the website and it is not ok for you to use the first method, I recommend to check pre_option_{option name}
filter hook.
The code for your functions.php
:
function misha_hide_out_of_stock_option( $option ){
return 'yes';
}
add_action( 'woocommerce_before_template_part', function( $template_name ) {
if( $template_name !== "single-product/related.php" ) {
return;
}
add_filter( 'pre_option_woocommerce_hide_out_of_stock_items', 'misha_hide_out_of_stock_option' );
} );
add_action( 'woocommerce_after_template_part', function( $template_name ) {
if( $template_name !== "single-product/related.php" ) {
return;
}
remove_filter( 'pre_option_woocommerce_hide_out_of_stock_items', 'misha_hide_out_of_stock_option' );
} );
- On line 1 you can see the function which returns “yes” (hide out of stock products) no matter what option is set in WooCommerce settings
- We filter this option on line 11, but we create a filter only before our specific WooCommerce template part is included, that’s why it is inside an action
woocommerce_before_template_part
and there is also a condition on line 7. - Once the template is included, we don’t want this option to be filtered for the rest of the website page, so we remove the filter on line 21 and do it inside an action
woocommerce_after_template_part
- If you want to do the same for upsells, just replace template name on lines 7 and 17 to
single-product/up-sells.php
, for cross-sells in the Cart page –cart/cross-sells.php
.
In case you would like to hide out of stock products from archive pages (search page, shop page, product category pages), you’d better use pre_get_posts
action hook, example:
add_action( 'pre_get_posts', 'misha_hide_out_of_stock_in_search' );
function misha_hide_out_of_stock_in_search( $query ){
if( $query->is_search() && $query->is_main_query() ) {
$query->set( 'meta_key', '_stock_status' );
$query->set( 'meta_value', 'instock' );
}
}
As I already mentioned above and now you see it in the code, it is all about adding meta key parameter _stock_status
to the query.
Read also

Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
I added the code to my functions.php to disable the ‘out of stock’ items in the related products section, but now it’s not showing any related products anymore. Also no items which are still for sale.
Do you know what could be the problem? Thanks in advance!
hi Misha,
nice code, i dont think peeps are reading so were and they have not relised that theres two functions displaying in first code functions section, prehaps define clearer for others.