Hi everyone,
What is the best approach for implementing advanced product filters on Shopify while keeping the collection page fast?
I am looking to expand my knowledge, so I hope you will share some genuine replies based on your experience.
Thanks!
Hello @olivianewuser123
From what I know a store can create 25 filters at most, and filters come back empty on any collection holding more than 5000 products.
-
Set the filters up in Search & Discovery first, then load the collection
with the parameters typed in by hand, like
/collections/all?filter.p.product_type=shoes&filter.v.option.color=red
If the products you filtered for come back correctly then the filtering is already
running on Shopify’s side and there’s no javascript involved yet. That’s your
baseline -
Build the UI from collection.filters in Liquid. Every filter_value hands
you count, url_to_add and url_to_remove, so you can grey out the options
with no results and build your reset links without composing any URLs
yourself. -
Now get rid of the page reload. Request the same path with
?section_id= and the same filter parameters,
then swap in just the grid. It returns the section HTML directly. Dawn
already works this way, open assets/facets.js and search for section_id to
see the URL it builds. -
Then click a filter with the network tab open. You want one request and
grid HTML coming back. If you see the whole collection arriving as JSON
instead, that’s the thing that gets slow as the catalogue grows.
You can use this documentation to back-up your work, it is updated and I used it to create Shopify apps before:
Filters: Storefront filtering
The 5000 limit: Liquid objects: collection
How many products are in the collection? Under a few thousand the native path
usually holds up on its own…
I’d recommend using Shopify’s native Search & Discovery filtering wherever possible, with product options, standard attributes, and metafields for filterable data.
For performance, keep filtering server-side/URL-based rather than loading the entire catalog into JavaScript. Use AJAX/section rendering for filter changes, Shopify’s responsive image handling for product cards, and avoid heavy third-party filtering apps.
If native filtering isn’t enough, I’d build a progressive enhancement on top of Shopify’s system rather than replacing it completely. This gives you a better balance of performance, SEO, accessibility, and long-term maintainability.
Best regards,
Devcoder ![]()
Unless you have a really large catalog, I would focus first on the customer journey, and ensuring you have filters created with how the customer shops in mind.
A filter can be created using product data and particularly product metafields that you can create. You can use these metafields to create the filters that the real customer journey needs.
For example, a lot of sneakerhead shoes come in very unique color ways like Obsidian Rock (aka Black) or Moon Dust (aka silver). However customers typically think of things in basic colors. You can set the variant to use the brand provided color name, while using a metafield to capture the standardized name. Then use that standardized name for the filter.
Other things to consider is typically you do not want really thin collections, or an overly large collection that doesnt have good filtering.
The theme should handle most of these things natively without issue. If you have a really large catalog (over 5k products) you may need to be more concerned.
I’d keep Shopify’s native filtering and optimize the theme around it rather than adding a second filtering engine.
- Start with 5 to 8 useful filters. Normalize metafield values first, so Blue, blue, and Navy do not create messy duplicates.
- Render results through the Section Rendering API. Replace only the product grid, filter counts, and pagination. Do not fetch every product into JavaScript.
- Debounce price inputs by about 300 ms, abort the previous request when another filter is clicked, and update the URL so back, forward, and shared links work.
- Test on a real phone with 3 or 4 filters applied. Check that one filter action creates one network request, product cards use lazy-loaded responsive images, and unavailable values are disabled.
Also keep sorting and pagination server-side. Infinite scroll can feel fast initially, but standard pagination is usually easier to maintain and debug.
One CRO check I’d add after the technical baseline: treat a filter as a discovery decision, not just a server response. Record filter impression → selection → zero-result/backtrack → product-card click → PDP add to cart; segment mobile/desktop and entry source. If a filter is used heavily but leads to zero results or no product clicks, normalize the values or change the label. If filtering is fast but collection → PDP falls, the issue is more likely taxonomy or sorting than performance. Validate this on one high-traffic collection before adding more filters.
I’d try to keep the filtering logic as close to Shopify’s native filtering as possible rather than loading a big third party filtering script. The number of filters isn’t necessarily the problem, it’s usually how much JS, product data and extra requests the filter app is adding to the collection page.
I’d also be careful with how many products are rendered before someone actually filters. Keep the initial page lightweight, avoid loading every variant and piece of metadata up front, and make sure the filtered URLs are still handled properly for SEO. I use SiteGuru to keep an eye on things like crawlability and indexation, which is useful because filtering can create a lot of URL variations if you aren’t careful.
For larger catalogs I’d be interested to hear what people are using too. Native Shopify filters seem fine for a lot of stores, but once you have hundreds or thousands of products, the UX requirements get quite different.
Hey @olivianewuser123 ,
I’d start with Shopify’s native filtering capabilities before adding a heavy third-party filtering solution. Keeping the filters relevant and structuring product data properly can make a big difference.
If custom filtering is needed, I’d try to keep the implementation lightweight and avoid unnecessary JavaScript or repeated requests on the collection page. Loading only what’s needed and testing the page on mobile is also important, since a filter that works well functionally can still hurt performance if it adds too much overhead.
For larger catalogs, I’d also test the filtering experience with real product volumes rather than assuming it will perform the same way with a small number of products.
Thank You!
I’d keep the filter set smaller than most people think, because every extra option adds work for the shopper and more chances for the collection page to feel heavy, especially on mobile.
In practice I’d start with the filters that actually change buying decisions, like size, color, price, material, and one or two category-specific ones. Then hide the rest behind search or collection structure instead of putting everything on the page at once.
The other thing I’d watch is how the theme updates the results.
If the page is reloading big chunks of the collection every time someone taps a filter, that’s usually where the slowdown happens. So I’d test whether your theme can update just the product grid and counts without rerendering the whole page.
Lastly, make sure the filter values are clean before you build anything too complicated, because messy tags and metafields create duplicate options that can make the whole experience feel broken to users.
Hello @olivianewuser123, karim326’s approach above is exactly how I’d build it too, native Search & Discovery filters plus the section_id swap to avoid full page reloads. On the metafield point raised further up: if a metafield isn’t showing as a filter option at all, check its definition under Settings > Custom data, it needs “Storefront filtering” toggled on there before Search & Discovery will pick it up, that’s a common reason a filter just doesn’t appear even when the data itself is clean. Thanks
Native Shopify collection filters are recommended to use with Search & Discovery when you can use them. Keep the filter set light, rely on relevant product and collection attributes and avoid loading unnecessary filters or scripts on the collection template. For large catalog, you will also need to take into account how many products you have migrated so far and your mobile collection page performance. I would also suggest to run some tests on network requests and performance on your theme after adding each filter group as the filters are just one side of the performance coin.
Most of the useful ground is already covered here (native Search & Discovery + Section Rendering, metafields, real-device testing), so I’ll add the things that usually bite later.
On the 5,000 limit: it’s real, and worth planning around. Collections over 5,000 products don’t display filters at all, and search results over 100,000 don’t either. Shopify’s own recommendation is to split the oversized collection into narrower ones (Tops / Jeans / Boots instead of one “Women”) rather than working around it. If your catalog is heading that way, get the collection structure right first, because no amount of filter tuning fixes it later.
Get the metafield definition types right before you backfill. The filterable types are limited: single_line_text_field, list.single_line_text_field, metaobject_reference, list.metaobject_reference, number_integer, number_decimal, boolean. The list. variants are what let one product sit in several buckets of the same filter, and switching from single to list after you’ve populated a few thousand products is genuinely painful.
Decide the AND/OR logic before designing the UI. Filters combine with AND, values within one filter with OR: Red or Blue, AND size 42. It’s easy to build a UI that implies the opposite, and then you field “the filter is broken” tickets that aren’t bugs.
Remove the dead ends. filter_value.count lets you disable or hide zero-count options, though note it only returns a number for boolean and list filters and is nil for price_range, so don’t build the whole UI around it. Always render url_to_remove plus a visible “clear all”. Zero-result pages are the quietest drop-off on a collection page, and Shopify hands you the counts for free.
Watch the pagination interaction. url_to_add and url_to_remove strip pagination parameters, which is what you want. But if you’re making your own Section Rendering requests, check you aren’t re-appending a stale page=3 and dropping customers onto an empty grid right after they narrow the results.
Extend it to /search. The same filters work on search results, not just collections, provided your theme supports them on the search template. Worth verifying, since search traffic usually converts better than collection browsing and it’s a common gap.
Then decide what gets indexed. Pick the filtered combinations you actually want in Google and canonicalise the rest to the clean collection URL. Otherwise advanced filtering quietly generates thousands of near-duplicate URLs.
Disclosure: I build Rapid Search, a search & filter app, so factor that in. It’s also why I agree with the native-first advice here: filter apps are usually slow for one reason, they send the whole catalog to the browser as JSON. Ours is 17 KB and sends back ready-rendered HTML instead. Check those two things on any app you try: how much it adds to the page, and what a filter click actually downloads.