A product nobody can browse to
Outside every category, or only in the default one, a product exists but cannot be browsed to — no menu, no listing, no filter, almost no internal links.
The symptom
The product is published. Its URL works. Search finds it. But there is no path through the shop that leads to it: it is in no category, or it is in the one WordPress created by itself, usually called Uncategorized.
You normally discover it the way everyone does — a customer asks whether you still sell something, and you find it perfectly fine, sitting in the catalogue, reachable only if you already know it exists.
What it costs
Categories are not a filing preference in WooCommerce. They are the navigation:
- It is in no listing. Not in the category page, not in menus built from categories, not in “related products”, which WooCommerce derives from shared categories and tags.
- Almost nothing links to it. Internal links are how a search engine finds pages and decides how important they are. A product with no category is typically linked from the sitemap and nowhere else — so it is crawled late and ranked low, if at all.
- Filters skip it. Category-scoped filters and price sliders operate within a category. Outside every category means outside every filter.
- Feeds get it wrong. Google Merchant Center and marketplaces map your categories to theirs. With nothing to map, items land in a generic bucket or get rejected.
The default category deserves its own note. A product in Uncategorized is worse than one in no category at all, because it looks assigned. It passes a quick eyeball check and every automated report that only asks “does this product have a category”.
How to check it yourself
Start by finding the ID of the default category:
wp option get default_product_cat
Then list published products that have no product category other than that one:
wp db query "SELECT p.ID, p.post_title
FROM wp_posts p
WHERE p.post_type = 'product' AND p.post_status = 'publish'
AND p.ID NOT IN (
SELECT tr.object_id FROM wp_term_relationships tr
JOIN wp_term_taxonomy tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy = 'product_cat' AND tt.term_id <> <DEFAULT_ID>
)"
Substitute the ID from the first command for <DEFAULT_ID>. From the admin, the quick version is
Products → Categories → click the count next to Uncategorized — but that misses products in no
category at all, which is why the query asks the question the other way round.
How to fix it
- Assign real categories. Bulk edit handles this well: filter the product list, select all, Bulk actions → Edit, add a category.
- Then delete the default category, or rename it into a real one. As long as Uncategorized
exists, WordPress keeps quietly assigning products to it whenever nothing else is picked. You
cannot delete the default term directly — set a different one as default first
(
wp option update default_product_cat <ID>), then delete the old one. - Check your import mapping. As with most catalogue faults that arrive in bulk, one import run is usually responsible.
When it is a false positive
- Stores that navigate by attributes or tags rather than categories. A legitimate design, and this check is measuring something you do not use. Hide it once and it stays hidden.
- Single-product stores, where there is nothing to categorise.
- Products deliberately kept out of browsing — a hidden bundle, an upsell reachable only from another product, a link sold to one customer. In that case the right setting is catalogue visibility: hidden, which says the same thing explicitly. Merchlint excludes hidden products for exactly this reason.
How Merchlint finds it
Merchlint reads the product_cat terms attached to each published product, treats the default
category as equivalent to no category, and skips products whose catalogue visibility is already set
to hidden. The finding shows which categories the product does have — including the default one,
so “assigned to Uncategorized” is visibly a different case from “assigned to nothing”.
Confidence: F — fact from the database. Term relationships are read directly; nothing is inferred from the front end.
This check runs in the free version, on every product, with no cap.
Disagrees with what you see in your store? Write to us — we read every message. contact@merchlint.com