Programmatic SEO for ecommerce: which filter pages to index
A scoring rule for turning faceted filter combinations into landing pages, plus Google's robots.txt, canonical and 404 guidance, and the Shopify trap.
Programmatic SEO for ecommerce mostly means faceted navigation. Every category and attribute combination, such as “black leather sofas under $1,000”, can already be a URL. Only a small share of those combinations have search demand and enough products to deserve a place in Google’s index. This post gives a scoring rule for promoting a filter combination to a real landing page. It also covers what to do with everything else according to Google’s faceted-navigation guidance, the Shopify canonical trap, and when a store should skip the whole idea.
How is programmatic SEO for ecommerce different from directory or SaaS programmatic SEO?
The programmatic SEO examples you usually see are Yelp, Tripadvisor, Wise and Zapier, as in Semrush’s guide and Victorious’s. Those sites create templated pages from a dataset. A store has the opposite problem. Its filters already generate thousands of URLs, so the work is mostly selection and control.
Three things follow from that. This framing is my own synthesis; no single source states it.
- The page data is the live product set. It changes with stock, so a page that was fine last month can be empty today.
- Crawl waste is the main risk. In Google’s 2025 year-end crawling report, Gary Illyes put faceted navigation at 50% of crawling challenges. Action parameters made up 25% and irrelevant parameters 10%. His explanation: the crawler “cannot make a decision about whether that URL space is good or not.”
- The ranking guides don’t cover it. Neither the Semrush nor the Victorious guide mentions faceted navigation, canonicals, robots.txt or Shopify. A “programmatic SEO for ecommerce template” in those guides means templated product descriptions.
Which filter combinations should get their own indexable landing page?
Practitioners mostly agree on the conditions. Andy Chadwick’s furniture store write-up is the clearest published example. It is a single self-reported site from 2021, and its rules were:
- One or two facets (colour, material, style, size) produce an indexable URL with its own title, meta description and copy.
- Price facets are never indexed, because they had no search volume.
- Two values from the same facet, or three or more facets, are not indexable.
- Filter order always resolves to one URL.
- Non-indexable URLs canonicalize to the seed category.
Indexable URLs fell from about 1,500 to 150, and organic visibility rose about 230% within two months. The author calls the gains modest in absolute terms.
Practical Ecommerce makes the demand case. A query like “gold Cross ballpoint pen black ink” signals much more purchase intent than “pen”. Multi-select within one facet, such as gold plus silver plus black enamel, rarely matches anything people type.
Here is the scoring rule I’d use. A combination needs to pass every row:
| Test | Pass condition | Source |
|---|---|---|
| Demand | Matches a real query with volume and buying intent | Chadwick, Practical Ecommerce |
| Facet shape | One or two facets, never two values from the same facet | Chadwick, Practical Ecommerce |
| Price | Excluded unless the price query has its own demand | Chadwick |
| Product count | At least about five products (see next section) | seoClarity, WisePIM |
| Stock stability | Doesn’t drop to zero every few weeks | Scandiweb, Xictron |
| Unique page | Own title, H1, copy and one canonical URL | Chadwick |
The last row matters because of Google’s spam policies. They list “Creating substantially similar pages that are closer to search results than a clearly defined, browseable hierarchy” as doorway abuse. A filter page with a swapped H1 and nothing else fits that description closely. The same thin-copy problem shows up as canonical clusters, which I covered in programmatic SEO duplicate content clusters.
How many products does a filtered page need before it’s worth indexing?
Google gives no number. The practitioner rules of thumb are:
- More than one, probably more than two: Eric Enge at Search Engine Land.
- Don’t index below 3 to 5: seoClarity.
- “Many teams use somewhere around five”: WisePIM.
- Enough products to fill at least the first screen, in a range that doesn’t empty out every few weeks: Scandiweb.
I’d combine the last two. Set a floor of five products, and check it against stock history rather than today’s count. Xictron makes the same point: the assortment shouldn’t drop to zero every week. A page that passes on Monday and fails on Friday will flip between indexable and thin, and that is the worst state to be in.
For scale, the agency 1Digital estimates that most stores should index roughly 20 to 200 filter pages. That figure is unverified, but it matches the Chadwick result of 150.
Should filtered URLs be blocked in robots.txt, canonicalized or noindexed?
Google’s faceted-navigation help page became official documentation in December 2024. It ranks the options clearly:

- robots.txt first, for URLs you don’t need in Search. Google’s example disallows patterns like
/*?*color=and keeps one unfiltered listing crawlable. Putting filters in a URL fragment (#) also works, because Google generally ignores fragments. rel="canonical"is weaker. It “may, over time, decrease the crawl volume of non-canonical versions.” Google’s example points a multi-filter URL at a version with fewer filters.rel="nofollow"works only if every link to the URL carries it.
The page never mentions noindex. Google’s crawl-budget doc says Google “will still request, but then drop” noindexed pages, so noindex keeps a URL out of the index and still costs crawl. The canonicalization doc also advises against using noindex to choose a canonical. Many agency guides still treat noindex as the default for low-value facets. On a large filter space, I wouldn’t.
You also can’t stack these on one URL. A page blocked in robots.txt can’t show Google its canonical or noindex tag, and Google may still index it without content. If you switch from noindex to robots.txt, expect a transition period. I walk through that kind of audit in how to noindex programmatic pages with Search Console data.
This is the decision flow for every filter URL, combining Google’s guidance with the scoring rule above:
flowchart TD
A[Filter combination URL] --> B{Zero results or nonsensical?}
B -->|Yes| C[Return 404]
B -->|No| D{Real query with demand?}
D -->|No| E[Block or canonicalize]
D -->|Yes| F{One or two facets?}
F -->|No| E
F -->|Yes| G{Enough stable stock?}
G -->|No| E
G -->|Yes| H[Build real landing page]For the facets you do keep, Google asks for the standard & separator, a consistent filter order and blocked duplicate filters, so that one filter set maps to one URL. Commas, semicolons and brackets are often not treated as separators.
What should an empty or nonsensical filter combination return: 404, redirect or a thin page?
Return a 404 at the URL itself. Google’s faceted doc says to do this for combinations with no results, for duplicated or nonsensical filters, and for pagination pages that don’t exist. It also says not to redirect them to a generic error page.
A 200 page that says “no products found” is the worst option. The crawl-budget doc says “soft 404 pages will continue to be crawled, and waste your budget.”
There is one exception. Google’s ecommerce URL-structure doc says to use noindex for empty categories, or a 404 if the category was removed from browse and search. My reading: return a 404 for zero-result or nonsensical filter combinations. Use noindex for a real landing page that is only temporarily out of stock.
How do you handle Shopify’s default collection canonicals?
Shopify blocks most of the filter space by default. Its robots.txt help page lists Disallow: /collections/*+* for tag combinations and /collections/*sort_by* for sorted URLs. A live store’s file, such as Allbirds’ robots.txt, also has Disallow: /collections/*filter*&*filter*. Any URL with two or more filter. parameters is uncrawlable, while a single filter stays crawlable.

Single-filter URLs reportedly canonicalize to the base collection. Shopify doesn’t document this: its canonical_url object is described only as “the canonical URL for the current page.” Since March 16, 2026, filter URLs also use stable group IDs instead of text values. Shopify says old URLs keep working. Some third-party posts claim old URLs now return the unfiltered collection, but that claim is unverified.
Put together, a Shopify filtered view is a poor home for a landing page: it is canonicalized away, sometimes blocked, and now has an opaque URL. Sources such as Shero Commerce and Amsive recommend this setup instead:
- Build a real smart collection, such as
/collections/black-leather-sofas, with a self-referencing canonical, unique copy, sitemap inclusion and internal links. - Leave filter URLs canonicalized or blocked.
- Change
product.url | within: collectiontoproduct.url, so product cards link to/products/.... This matches Google’s advice to link internally to the canonical.
Be careful with robots.txt.liquid. Shopify calls edits “unsupported” and warns that “Incorrect use of the feature can result in loss of all traffic.” A dev-forum report says robots.default_groups returns an older rule set (63 rules against the 45 Shopify actually serves). A customization can therefore change your rules without you noticing.
Tag-page canonicals are disputed across sources, and themes and apps change them. Check a live page’s source, then use Search Console URL Inspection to see which canonical Google actually chose. More on that is in the indexing hub.
When are programmatic pages the wrong answer for an online store?
Skip them, or cut back, in these cases:
- Thin catalog. If most combinations would hold three items, you have nothing to promote.
- Unstable stock. Pages that keep dropping to zero fail the stability test, however good the keyword is.
- No demand. Chadwick’s price facets had no search volume, so they were never indexed.
- Core collections are already struggling. The Shugert case, vendor-reported, describes a Shopify store with about 800 products. It had 11,400 URLs in Coverage against about 900 indexable pages, and 6,000+ URLs in “Discovered, currently not indexed”. Its core collections were last crawled 45 to 60 days earlier. Eight weeks after the crawl-control fix, the “Discovered” count fell by more than half.
In both published cases, the gains came from removing URLs. Chadwick cut indexable pages by 90%, and Shugert cut crawlable waste.
If your main category pages aren’t crawled often and don’t rank, fix those first. Then promote the five or ten combinations that pass every row of the scoring table, and return a 404 for the empty ones.