
Ecommerce Faceted Navigation and SEO - Which Filters to Index and Which to Block (noindex, canonical, robots.txt)
Faceted navigation in an online store raises two questions at once: which filter combinations should be pages in Google, and which ones the crawler should not visit at all. The decision rule: a filter that has demand (it appears in Google's autocomplete or has at least about 50 searches a month) and at least about 10 products gets a fixed, friendly URL with an HTML link, its own title and a self-referencing canonical. Everything else (further combinations, size, price, sorting, products per page) should not be HTML links, and if it creates URLs, you block them in robots.txt. Use noindex and canonical to clean up URLs that are already indexed. Never combine them with a robots.txt block, because Google will then see neither.
Which ecommerce filters to index and which to block: a rule with thresholds, noindex vs canonical vs robots.txt vs nofollow in one table, a check of filters in 11 Polish stores, Shopify, WooCommerce, PrestaShop and IdoSell defaults, URL counts at two scales, robots.txt rules, a script and two pitfalls.
/// THIS POST IN SHORT
This post covers what each method does to the crawler (robots.txt, noindex, canonical, nofollow, # URLs, filters without links), the results of my check of filters in 11 Polish online stores, how Shopify, WooCommerce, PrestaShop and IdoSell handle filters by default, how many URLs filters create at two store sizes, a script for checking how filters are handled and two pitfalls I found in large stores.
Can filters hurt SEO at all - the first decision
They can, but you do not always need to act. Google says plainly that faceted navigation is "by far the most common source of overcrawl issues" site owners report. Every filter combination is a new URL, so with a few hundred filter values the number of possible URLs runs into the tens of thousands.
| Store situation | Are filters a problem | What to do |
|---|---|---|
| Filters work without changing the URL, or only after # in the URL | Not for crawling (Google ignores the part after #) | Nothing, but add selected filters with demand as separate pages |
| Filters change the URL but are not HTML links | Minor - Google rarely reaches them | Check in Search Console that these URLs do not get indexed |
| Filters are a href links in the product listing | Major with hundreds of values | Rules: which ones to link and index, block the rest |
| Thousands of parameter URLs in the Search Console Pages report | Yes, the problem is already there | noindex first, then a block (order below) |
| Store with up to a few hundred products and a few filters | Usually not | Sorting and products-per-page rules are enough |
Robots.txt, noindex, canonical, nofollow - what affects crawling and what affects indexing
This is the most important table in the post. Most filter mistakes come from confusing two things: blocking crawling (the crawler does not fetch the URL) and blocking indexing (the URL does not appear in results).
| Method | Limits crawling | Removes from the index | Consolidates signals with the category | When to use |
|---|---|---|---|---|
| robots.txt Disallow | Yes, immediately | No - a blocked URL can stay indexed without content | No | Filters without demand, sorting, products per page |
| Meta robots noindex | No (a little over time) | Yes, after the page is refetched | No | Cleaning up filters that are already indexed |
| rel="canonical" to the category | A little over time; per Google less effective than robots.txt | Usually, but it is a signal, not a directive | Yes | Filters almost identical to the category (e.g. sorting, minor attributes) |
| rel="nofollow" on filter links | Weakly - only works on every link to the URL | No | No | Rarely; Google considers it less effective |
| Filters after # in the URL | Yes - Google ignores the part after # | Not applicable | Not applicable | JavaScript stores, filters that need no indexing |
| Filter without an a href link (button, form) | Yes, in practice | Not applicable | Not applicable | The default for filters without demand |
| A fixed, friendly URL with a link and a self canonical | No - the crawler should go there | No - the page should be indexed | Not applicable | Filters with demand and at least about 10 products |
Three Google rules worth knowing: robots.txt is not for canonicalisation (a blocked URL can stay indexed), noindex is not for choosing the canonical version within a site, and canonical is a strong signal but takes time. If you do index filters, Google recommends the standard & separator in parameters, a fixed filter order in the path and a 404 status for combinations with no products.
Which filters to index - the rule and examples
A filter becomes a landing page when it meets three conditions at once: it has demand, it has at least about 10 products and it answers a different intent than the parent category. I showed how to collect demand and map queries to filters in the post on ecommerce keyword research.
| Filter type | Example | Usually | Why |
|---|---|---|---|
| Brand within a category | salomon hiking boots | Index | High demand, a stable product list |
| Attribute with demand | bentonite cat litter, gore-tex boots | Index | People type the attribute together with the category |
| Gender, type, use | women's hiking boots | Better as a subcategory | A separate intent and a stable range |
| Colour | black hiking boots | Only colours with demand | Most colours have no searches |
| Size | hiking boots size 38 | Do not index | Availability changes daily |
| Price, sale, availability | under PLN 300, on sale | Do not index | The list changes from day to day |
| Two filters at once | salomon + gore-tex + black | Only selected pairs with demand | Combinations multiply URLs fastest |
| Sorting and products per page | sort=price, limit=96 | Always block | The same list in a different order |
How 11 Polish online stores handle filters - my check
How I checked: on 15 October 2026 a script in a Chromium browser opened one category in each of 17 Polish online stores, counted filter controls and a href links to filters, then clicked filters (one, then a second) to see which URL appeared. For every filter URL it checked the HTTP status, meta robots, canonical and whether robots.txt blocks it for Googlebot. I could establish filter handling in 11 stores. In the other 6, filters did not change the URL after a click or the script could not click them, so I do not assess them.
| Store | Filter URL | a href links to filters | Filter URL handling | Verdict |
|---|---|---|---|---|
| eobuwie.pl | path, e.g. /marka:salomon | yes, selected | index, self canonical; an empty filter returns 404 | Model setup |
| zooplus.pl | path, e.g. /bentonitowy | yes | index, self canonical; 109-167 products | Model setup: attribute with demand as a subcategory |
| modivo.pl | path, e.g. /marka:reebok | yes | index, self canonical, also for brands with 2-6 products | Thin pages indexed |
| morele.net | path with commas: ,,,,,496,,,0,,,,/1/ | yes | some filters index, others noindex, follow | Selective; commas as a separator |
| smyk.com | parameter ?plec=Dziewczynka | no | noindex, no canonical | Correct |
| sportano.pl | parameters ?nowosc=1&wyprzedaze=1 | yes, a few | noindex, nofollow, no canonical | Correct |
| bee.pl | parameter params[tg]=38 | no | noindex, nofollow and a canonical to the category | Two conflicting signals |
| swiatksiazki.pl | parameter ?customFilters=... | no | index, canonical to the category | Canonical only |
| melisa.pl | parameter ?marka=... | no | index, canonical to the category; price and sorting blocked in robots.txt | Canonical only for brands |
| taniaksiazka.pl | parameter params[tg]=10 | no | noindex, nofollow, canonical to the category and a robots.txt block | Google sees neither noindex nor canonical |
| kontri.pl (IdoSell) | parameter ?filter_sizes=... | no | index, canonical to the category and a *?filter_* robots.txt block | Google does not see the canonical |
What this shows:
- The most common method is a canonical to the category (5 of 11 stores), and 4 stores give filters noindex. 4 stores index filters as pages with their own path URL, one of them even with just a few products.
- 6 of 11 stores do not link filters with a href, so their URLs only appear after a click. That effectively limits crawling without any rules.
- 2 stores combine noindex or canonical with a robots.txt block. That is the pitfall described below.
- The number of filter values is striking. On the tablets category page of morele.net I counted 459 filter controls, and 282 in the trousers category of smyk.com. With 459 values, combinations of just two filters give up to about 105,000 URLs - which is why indexing everything is out of the question.
Filters on Shopify, WooCommerce, PrestaShop and IdoSell - default settings
The platform decides your starting point. I checked the default rules in store robots.txt files and in the PrestaShop source code.
| Platform | What filter URLs look like | Default robots.txt | What to do |
|---|---|---|---|
| Shopify | collections and tags (/collections/boots/black), filters ?filter.v.option...= | Blocks sorting (sort_by), tag combinations with + and two or more filters at once; a single filter is crawlable | Indexable filters with demand as separate collections; check single filters in Search Console |
| WooCommerce | parameters ?filter_colour=black, filter plugins with their own parameters | WordPress blocks only /wp-admin/ by default | Add rules for filter and sorting (orderby) parameters; indexable filters as categories or tags |
| PrestaShop | faceted navigation module, parameter ?q=Colour-Black | The robots.txt generator blocks ?q= and &q= as well as order= and n= | Filters with demand as separate categories or a landing page module with friendly URLs |
| IdoSell | parameters ?filter_...= | In the store I checked, a *?filter_* block | Do not combine the block with a canonical; landing pages for filters with demand |
| Next.js and headless stores | anything - you decide | no default rules | Selected filters in the path in a fixed order, server-rendered, 404 for empty combinations, no a href links for the rest |
The most common platform problem: the default block works, so nobody creates pages for filters with demand. In PrestaShop and in the IdoSell store from my check, all filters are blocked, so a query like "salomon hiking boots" has no chance of landing on a filter page - you need a separate category or landing page for it. I build such pages for filters with demand in store templates as part of my ecommerce SEO work.
How many URLs filters create - two scales
An estimate assuming filters create URLs and are links. The number of two-filter combinations is n × (n - 1) / 2, where n is the number of filter values in a category.
| Assumption | Store A: 500 products | Store B: 20,000 products |
|---|---|---|
| Categories | 40 | 600 |
| Filter values per category (average) | 60 | 400 |
| Single filters (categories × values) | 2,400 | 240,000 |
| Two-filter combinations in one category | up to 1,770 | up to 79,800 |
| Indexable filters with demand (target) | 20-40 | 300-1,500 |
| Implementing the rules (estimate from my quotes, Oct 2026) | 8-16 hours | 40-80 hours |
The takeaway: in a small store the problem often does not appear on its own, but it is worth blocking sorting from the start and adding a few dozen filter pages with demand. In a large store without rules the crawler can face hundreds of thousands of filter URLs for a few thousand products, and new products wait longer to be indexed - I explain how Google allocates resources in the post about crawl budget.
An example robots.txt for filters
Rules for a typical store with filters in parameters. Replace the parameter names with yours and test them in the robots.txt report in Search Console before deploying.
User-agent: *# sorting and products per pageDisallow: /*?*sort=Disallow: /*?*orderby=Disallow: /*?*limit=# filters in parameters (indexable filters have their own path URLs)Disallow: /*?*filter_Disallow: /*?*price_from=Disallow: /*?*price_to=# internal search resultsDisallow: /searchSitemap: https://yourstore.com/sitemap.xml
Add these rules only after filter URLs with parameters have dropped out of the index (see the pitfall below). Filter pages with demand have path URLs, e.g. /hiking-boots/brand-salomon, so the rules do not block them.
Script: check how a store handles filter URLs
The script takes a list of filter URLs (e.g. from a crawl, logs or the Search Console Pages report) and checks, for each, the HTTP status, meta robots, the X-Robots-Tag header, canonical and the robots.txt block. At the end it lists URLs with conflicting signals.
# pip install requestsimport csv, re, sysfrom urllib.parse import urlparse, urljoinfrom urllib import robotparserimport requestsUA = "Mozilla/5.0 (compatible; filter-audit)"urls = [u.strip() for u in open(sys.argv[1]) if u.strip()]host = urlparse(urls[0]).scheme + "://" + urlparse(urls[0]).netlocrp = robotparser.RobotFileParser(host + "/robots.txt"); rp.read()def check(url): r = requests.get(url, headers={"User-Agent": UA}, timeout=20, allow_redirects=False) html = r.text if "html" in r.headers.get("content-type", "") else "" meta = re.search(r'<meta[^>]+name=["\']robots["\'][^>]*content=["\']([^"\']+)', html, re.I) canon = re.search(r'<link[^>]+rel=["\']canonical["\'][^>]*href=["\']([^"\']+)', html, re.I) robots = ((meta.group(1) if meta else "") + " " + r.headers.get("x-robots-tag", "")).lower() canonical = urljoin(url, canon.group(1)) if canon else "" return {"url": url, "status": r.status_code, "robots_txt_blocked": not rp.can_fetch("Googlebot", url), "noindex": "noindex" in robots, "canonical": canonical, "canonical_self": canonical.rstrip("/") == url.rstrip("/")}rows = [check(u) for u in urls]with open("filters.csv", "w", newline="") as f: w = csv.DictWriter(f, fieldnames=rows[0].keys()); w.writeheader(); w.writerows(rows)for r in rows: if r["robots_txt_blocked"] and (r["noindex"] or (r["canonical"] and not r["canonical_self"])): print("CONFLICT: robots.txt block hides noindex/canonical:", r["url"]) elif r["noindex"] and r["canonical"] and not r["canonical_self"]: print("CONFLICT: noindex plus a canonical to another page:", r["url"]) elif r["status"] == 200 and not r["noindex"] and r["canonical_self"]: print("INDEXABLE filter - check demand and product count:", r["url"])
Note: the robotparser in Python's standard library does not fully handle * and $ in robots.txt rules the way Google does. With wildcard rules, check the result in the Search Console robots.txt report or use a Google-compatible parser.
Pitfall 1: a robots.txt block hides noindex and canonical
The most common mistake I found: the store gives filters noindex or a canonical to the category and blocks them in robots.txt at the same time. That was the case at taniaksiazka.pl (noindex, nofollow, canonical and the rule Disallow: /*?params*=*) and kontri.pl (canonical and the rule Disallow: *?filter_*). Google does not fetch a blocked URL, so it sees neither noindex nor canonical. URLs indexed earlier can stay in the index as "Indexed, though blocked by robots.txt", with no content and no signals passed to the category.
The correct order for a clean-up:
- 1.Keep filter URLs crawlable and give them noindex (filters with no value) or a canonical to the category (filters almost identical to the category). Do not use both at once - Google does not recommend noindex for choosing the canonical version.
- 2.Remove a href links to filters without demand from product listings.
- 3.Wait until the number of these URLs in the Search Console Pages report drops clearly.
- 4.Only then add a robots.txt block, if the filters still use up crawling.
Pitfall 2: indexed filters with a few products
The other extreme: the store indexes every brand filter because it has a mechanism for it. At modivo.pl, brand filter pages in the leggings category had index and a self canonical even with 2, 4 or 6 products. There are thousands of such pages, each with an almost empty listing, and after a few models sell out they become empty. The fix: a product-count threshold in the template. Below the threshold the filter gets noindex and disappears from the links, above it returns to the index. An empty filter returns 404, as eobuwie.pl does and as Google recommends.
What not to do
- Do not block in robots.txt the URLs you have just given noindex or a canonical.
- Do not give one page both noindex and a canonical to the category.
- Do not index every filter combination - only those with demand and at least about 10 products.
- Do not link every filter value with a href in the product listing.
- Do not leave sorting and products per page indexable.
- Do not redirect empty filter combinations to an error page - return 404 at the same URL.
- Do not rely on nofollow - it only works when every link to the URL has it, including external ones.
FAQ
I describe the order of all store work in the ecommerce SEO strategy. If you want me to review the filters in your store and implement the rules in its templates, see ecommerce SEO.
/// RELATED_SERVICES
Need these concepts implemented? Explore the services related to this topic.
/// SOURCES
- 01Google Search Central - Managing crawling of faceted navigation URLs
- 02Google Search Central Blog - Crawling December: Faceted navigation (17.12.2024)
- 03Google Search Central - How to specify a canonical URL
- 04Google Search Central - Introduction to robots.txt
- 05Google Search Central - Help Google understand your ecommerce site structure
- 06PrestaShop - generator robots.txt (classes/Tools.php)
- 07Shopify Help Center - Editing robots.txt.liquid
- 08Google Search Console Help - Page indexing report
/// RELATED_RECORDS
Ecommerce Keyword Research - How to Map Queries to Categories, Filters and Products
How to do ecommerce keyword research and map queries to categories, filters, product pages and guides: a mapping rule with thresholds, a keyword map from 1,109 Google suggestions and real store product counts, Search Console, Keyword Planner, Senuto and Ahrefs with prices, a sheet template and a cannibalisation script.
Ecommerce SEO Strategy - a 3, 6 and 12-Month Roadmap
How to build an ecommerce SEO strategy ranked by revenue: a one-day diagnosis from Search Console, a priority matrix, a 3, 6 and 12-month roadmap with KPIs, SEO vs Google Ads cost at two scales, an audit of product data in 26 Polish online stores and a quick-wins script.
Allegro and Amazon in the AI Era - How to Increase Product Visibility on Marketplaces
Allegro's AI Assistant has been open to everyone since 7 May 2026, more than 300 million customers used Amazon's Rufus in 2025, and Amazon blocks ChatGPT's bots. How Allegro relevance works, how to prepare listings for AI assistants, why to combine a marketplace with your own store and how to keep one source of product data.
Signal received?
Terminate
Silence
Initiate protocol. Establish connection. Let's build something loud.
