Hide Specific Products from the WooCommerce Shop Page (by Tag or Category)
WooCommerce has no built-in setting to hide specific products from the shop page while still letting them remain purchasable through direct links. The closest option is the “Catalog visibility” dropdown on each product (Hidden, Search results only, Shop only, Catalog and search), but that’s per-product and inconvenient when you want to hide an entire category or a tag group.
A common case: you’re staging a product launch with a “Coming Soon” tag and want those products invisible on the shop page until launch day. Or you keep a “Discontinued” category around so old SEO links keep working but you don’t want the products in your main listings. The snippet below hides products by tag, category, or both, using a single pre_get_posts hook.
/**
* Hide products by tag or category from the WooCommerce shop page.
*
* Replace the term IDs with your own. Find them under
* Products > Tags or Products > Categories (hover the term and read
* the tag_ID number from the URL).
*/
add_action('pre_get_posts', function ($query) {
if (is_admin() || !$query->is_main_query() || !is_shop()) {
return;
}
$hidden_tag_ids = array(1155); // Coming Soon
$hidden_category_ids = array(1156); // Discontinued
$tax_query = array('relation' => 'AND');
if (!empty($hidden_tag_ids)) {
$tax_query[] = array(
'taxonomy' => 'product_tag',
'field' => 'term_id',
'terms' => $hidden_tag_ids,
'operator' => 'NOT IN',
);
}
if (!empty($hidden_category_ids)) {
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => $hidden_category_ids,
'operator' => 'NOT IN',
);
}
$query->set('tax_query', $tax_query);
});
Replace the IDs in $hidden_tag_ids and $hidden_category_ids with the term IDs you want hidden. To find a term ID, go to Products > Tags (or Categories), hover any term, and read the tag_ID parameter in the URL at the bottom of the browser.
Why This Beats Per-Product Visibility
The native catalog visibility setting works one product at a time. If you have 200 discontinued products, updating each one is tedious and easy to forget when adding new items. With this snippet, you just slap the “Discontinued” tag on the product and the shop page hides it automatically. Untag it later and it reappears, no admin clicks needed.
The hidden products are still reachable. If someone has the direct URL, the product page still works, the add-to-cart still functions, and search engines that already indexed the page won’t 404. Only the main shop loop excludes them.
Optional: Hide from Search Too
If you also want the hidden products to disappear from the site search results, change the is_shop() check to include search and product category archives.
// Hide from shop page, product category archives, and search
if (is_admin() || !$query->is_main_query()) {
return;
}
if (!is_shop() && !is_product_taxonomy() && !is_search()) {
return;
}
Use this replacement for the early-return block at the top of the main snippet. The rest of the function stays the same.
Verification
- Add the snippet to your child theme’s
functions.phpor a custom plugin - Tag one of your products with the “Coming Soon” tag (or assign the test category)
- Visit the shop page on the frontend and confirm the product no longer appears
- Visit the product’s direct URL and confirm the product page still loads and is purchasable
- Remove the tag and confirm the product reappears on the shop page
Need Help?
Learn how to add custom code to WordPress or reach out for custom development help.
About the Author
More Code Snippets
-
Reorder the Columns on the WooCommerce Orders List
Put your WooCommerce orders list columns in whatever order works…
-
Set the Default Country on WooCommerce Checkout
Pre-fill the WooCommerce checkout country (and optionally state) dropdown with…
-
Bulk Delete Expired Unused WooCommerce Coupons (Batched, Safe)
One-time bulk cleanup utility for stores with thousands of expired,…