Skip to content
ThemesIonic — home
WooCommerce

Filtering Products in WooCommerce

WooCommerce filters products natively, but only on global attributes. Most "my filters do not work" problems are custom attributes that were never taxonomies in the first place.

4 min read intermediate

WooCommerce filters products out of the box, and the reason yours does not is almost certainly the difference between a global attribute and a per-product one. Before buying anything, open Products then Attributes and check whether the things you want to filter by are listed there. If they are only typed into the Attributes tab of individual products, no filter plugin on the market will fix that, because there is nothing to filter — those values are stored as product metadata, not as terms.

The distinction that decides everything

A global attribute created under Products then Attributes is registered as a taxonomy. Its values are terms, they have archives, they can be counted, and WooCommerce can build a query from them. A custom attribute added on a single product's data panel is a string in that product's meta. It renders in the additional information table and does nothing else.

Converting is not difficult but it is not automatic: create the global attribute, add its terms, then assign terms to every product. On a large catalogue this is a CSV job rather than a manual one, and the product CSV importer will set global attribute terms if the column is formatted for taxonomy values. Do this once, properly, before evaluating plugins. It is also the prerequisite for variations, so if you are already building variable products the work is shared.

What core already provides

WooCommerce ships layered navigation for the shop and its archives:

  • Filter Products by Attribute, one instance per attribute, with AND or OR matching.
  • Filter Products by Price, a range control derived from the visible products.
  • Filter Products by Rating.
  • Active Product Filters, which shows what is applied and lets it be removed.

The same capabilities exist as blocks for block themes, alongside the product listing blocks, and WooCommerce has been consolidating them into a single filters block, so what appears in your inserter depends on the version you are running. Either way, filtering is applied through query string parameters on the archive URL — attribute filters, a minimum and maximum price, a rating — which is why filtered pages are linkable, shareable and cacheable, and why they are also a caching hazard.

Performance is handled by a product attributes lookup table that WooCommerce maintains specifically so layered navigation does not have to join meta tables. If filter counts look wrong after a bulk import, regenerate it from WooCommerce then Status then Tools before assuming a bug.

When a filter plugin is genuinely justified

Requirement Native Plugin
Filter by global attributes, price, rating Yes
Filter by category or tag within an archive Partly, via navigation Cleaner
Filter by custom taxonomy or custom field No Yes
Filter by stock status Depends on version Yes
Colour swatches, image buttons, sliders No Yes
Update results without a page reload No Yes
Filter on any page, not just archives No Yes
Hide options with no matching products Counts only Yes

The middle rows are the honest reasons to buy. Presentation is a real reason too — swatches convert better than checkboxes in fashion and paint — but be clear that you are buying presentation, not capability.

The traps

AJAX filtering and history. Filters that update results without reloading must still change the URL, or customers cannot share or bookmark a filtered view and the back button takes them out of the shop entirely.

Caching. Filtered URLs multiply cache entries and, worse, a cache that strips query strings will serve unfiltered results while the filter UI shows the filter as active. Confirm the behaviour before launch rather than after; the configuration lives with whichever cache plugin you run.

Empty results. A filter set that returns nothing should say so and offer a way back. If instead the archive appears blank with no explanation, you are in the same territory as products not showing and it is worth ruling out visibility and catalogue settings first.

Index bloat. Every filter combination is a URL. Decide deliberately which are worth indexing — usually a small number of high-intent ones — and keep the rest out.

Theme compatibility. AJAX filters replace the products container, so they need to know your theme's markup. A filter plugin that works on a default theme and breaks on a heavily customised archive is not defective; it is guessing. If you have reworked the loop, expect to configure a container selector, and keep those changes in the same place as the rest of your archive customisations.

Where to start

Fix the attribute data first. Add the native widgets or blocks and live with them for a week. Then buy a plugin for the specific thing you found missing, because the shortlist for "swatches and AJAX" is different from the shortlist for "filter by a custom field", and buying before you know which one you need is how shops end up with two filter plugins fighting over the same archive. If what you actually needed was a dense, sortable list rather than a filtered grid, a product table may be the better answer entirely.

Frequently asked

Because it is a custom attribute defined on the individual product rather than a global one created under Products then Attributes. Only global attributes are taxonomies, and only taxonomies can be filtered by layered navigation.
Uncontrolled they can, because every combination of filters is a distinct URL and search engines will crawl a large number of near-duplicate pages. Let one or two genuinely useful filtered views be indexable and keep the rest out of the index.
Filtering happens through query string parameters, so a full page cache that ignores the query string will serve the unfiltered page to everybody. Either exclude filtered URLs from the cache or make the cache vary on those parameters.

Related guides