Filters, Faceted Navigation and Progressive Grid Loading on Shopify
Definition
Custom facet UI over Shopify Search & Discovery: sidebar rails, swatch filters, show-more lists, mobile accordions, merchandiser-controlled filter suppression and two-axis guided filters — plus load-more and infinite-scroll behavior that survives Section Rendering API swaps and re-initializes review and analytics widgets afterwards.
The Evidence
- Evidence strength: 22 live, Deploi-attributed builds across 3 Shopify storefronts.
- Split by storefront: Nudestix 12, LUS Brands 7, Three Ships 3.
- Split by attribution: 15 Deploi-authored, 7 modifications of vendor theme code — named as such on each build page.
- Evidence quality: fifteen carry code plus client working records. Seven are documented from the code; no client-side record of the decision survives.
- Confidence: 13 strong, 9 moderate.
- Surfaces: collection pages, search results, blog indexes.
- Status: Live, verified 2026-09-06. Buy-vs-build verdict: customize.
How It's Actually Built
The shape is the same on all three storefronts, with one exception named below, and it is not the shape most people expect. The facet data stays Shopify's. Values, counts, removal URLs and price bounds come from filter.values, url_to_remove and price_range, which means the filters a merchandiser configures in Search & Discovery are the filters on the page. What gets built is the interface, the transport and the recovery.
The interface is a rewrite of the theme's own facets snippet. On both Dawn storefronts facets.liquid is ours: on one it renders a desktop rail with swatch inputs, show-more truncation and clear-all pills plus a mobile accordion whose groups open in place; on the other, the same results object renders into four arrangements — vertical, horizontal, drawer and pills — from one parameter set, because different sections need different chrome. Two merchandiser controls sit on top of it. A hidden_filter textarea suppresses named filter values per section, and an On Sale filter pre-scans its own values and removes itself from a collection that has nothing on sale.
The transport is the Section Rendering API. A filter change re-fetches the section with ?section_id= and replaces the grid container wholesale, so load-more was implemented on the same path — same URL, plus page and section_id — rather than against a JSON endpoint. One card renderer, one set of promo rules, one truth.
The recovery is the part nobody sells you. Everything bound inside the replaced container dies on every filter change, including scripts injected into it, review widgets and the analytics loader. So facets.js grew an event contract — a facetFilters:productGridUpdated custom event the collapsible sidebar and the row-reveal animation subscribe to — a loading overlay created outside the container it covers, an error path that leaves the previous grid in place, and re-initialization of review widgets on newly appended cards. Promo tiles are theme-editor blocks placed by a slot counter that runs independently of the product cursor, so a tile is additive rather than substitutive.
The Buy-vs-Build Position
The corpus's own verdict:
Facets themselves stay native (Search & Discovery); what gets built is the UI and the AJAX pipeline around them — the CUSTOMIZE verdict, demonstrated.
Filter apps are a reasonable purchase and we don't pretend otherwise. What we keep finding is that they solve the half of the problem that was already solved. The facet index is free and lives where merchandisers already work; the disclosure pattern, the swatch rendering, the suppression rules and the re-render lifecycle are theme code whether or not you rent an index. Our full reasoning is in the filters and faceted navigation decision.
The Builds
Eight of the 22 have published pages. Of the rest — the facet AJAX hardening, the four-mode filter UI, a second pagination fork, the gift-guide collection switcher, and the blog and video-library filters among them — eleven are documented and will follow. Three won't get pages of their own; none of the three cleared editorial review.
LUS Brands
- Vertical filter rail and an in-place mobile filter accordion replacing Dawn's drill-down drawer — Dawn's drill-down drawer rebuilt as an accordion, with one sort control relocated between breakpoints instead of duplicated. High complexity, collection and search.
- Collapsible desktop filter sidebar that reflows the grid instead of squeezing it — the layout question a vertical rail always raises: what happens to its column when nobody is filtering. Opening the rail rewrites the grid's desktop column class from four-up to three-up rather than compressing four columns into less space, and the open state is kept off the container the facet pipeline replaces, so it survives every Section Rendering API swap. Medium complexity, collection.
- House pagination component with a result counter — paging with nothing to rebind, which is what a facet swap needs: the whole control, including a result range computed in Liquid, arrives inside the markup the Section Rendering API returns and already reports the filtered total. Low complexity, collection and blog.
Nudestix
- Shade-level collection grid hydrated from an external faceting service — the exception on this page: a variant-level result set Liquid cannot express, hydrated from a service outside the theme. High complexity, collection.
- Main collection grid: merchandisable promo tiles, load-more and a filter blocklist — native facets, in-grid promo blocks, section-rendered load more, and a merchandiser-editable list of filter values to hide. High complexity, collection.
Three Ships
- Collection page: three filter modes, in-grid promo blocks and infinite scroll — a premium vendor theme's collection section extended with facet, tag-permalink and grouped-tag filtering. High complexity, collection.
- Tabbed multi-type search results page with faceted filtering — the same facet objects on the search template, with a tab bar over them and tag-based product suppression inside the render loop. High complexity, search.
- Filter-triggered promo cards inside the search results grid — a merchandising block that reads facet state and renders only when a chosen facet is active. Medium complexity, search and collection.
What This Rests On
- Liquid section schema and settings — 18 of the 22 builds; every merchandiser control here is a section setting or a block.
- Section Rendering API — 13 builds; the transport for filtering, sorting and paging.
- Storefront filtering — 8 builds; the native facet objects the whole capability is built over.
- Custom elements — the disclosure and price-range components the themes ship, patched rather than replaced.
- Metafields and metaobjects — per-collection filter toggles, curated variant lists, swatch color references.
- History API, Intersection Observer, Liquid pagination — URL state, scroll fallbacks, the page ladder.
What Varies by Storefront
Theme base first, because it decides how much is ours. LUS Brands runs Dawn 15.4.1 and Nudestix runs Dawn 6.0.2 — same lineage, nine major versions apart, which is why the older store still carries two generations of load-more that do not know about each other. Three Ships runs Palo Alto 5.8.0 by Presidio Creative, a paid premium theme, so the collection section there is vendor code we extended and it has to keep upgrading; the visible Deploi edits are narrow and named on that build's page.
Catalog shape decides the rest. A haircare catalog facets at product level: one card per product, attributes like hair type and concern, and native filtering fits it exactly. A shade-led cosmetics catalog does not — the unit a shopper chooses is the shade, so a 12-shade blush appears once and 11 shades hide behind a swatch. Native filters are product-scoped and cannot express that, which is the one place here where the result set left Shopify. Three Ships is a third case: the taxonomy lives in product tags predating Shopify's filter metaobjects, so that vendor section carries three mutually exclusive filter strategies — of which the live templates run the plainest, Shopify's own facets, configured in the admin.
Installed apps set the last constraint. Review widgets, wishlist buttons, an analytics loader and an infinite-scroll library all live in the DOM the filter pipeline replaces, so each storefront's re-render puts back a different set of things.
Where This Gets Hard
The maintenance cost is the re-render lifecycle, and it never goes away. Once a grid is replaced by fetched HTML, you own the re-initialization of every third-party widget on it — including the ones installed after you leave. A review app that changes its init function breaks the second page of results, not the first, which is the kind of bug that survives QA.
Patching a vendor component is the second cost. Exempting the facets accordion from Dawn's drawer behavior is a deliberate divergence inside a component the vendor keeps changing, so every theme update has to be re-checked against it. On a premium theme with a minified runtime there is no source to patch and no supported hook at all.
Moving the result set off-platform is the largest commitment here. Variant-level faceting bought exactly what that catalog needed, and the trade is that the grid now depends on an index, an endpoint and its uptime that sit outside the theme — when the service is unavailable the grid renders an error state instead of products.
So we advise against building more often than this page suggests. If the catalog is a few hundred products with product-level attributes, no swatch requirement and a stock theme, Search & Discovery and the theme's facets already do the job, and rebuilding them buys parity. If nobody will own the JavaScript after launch, a hosted filter UI fails more gracefully than an unmaintained custom one. And variant-level faceting earns its cost only when the variant genuinely is the unit of choice.
Related Capabilities
- Variant-aware content and media — the PDP-side twin of the shade-level grid: same idea, different surface.
- Metafield-driven PDP content blocks — where the per-collection toggles and curated lists that drive these grids are authored.
- Fixed bundles and kit merchandising — collection templates carrying bundle grids, filtered by the same pipeline.
The rest of the Search, Filtering & Discovery category — custom site search, variant-level collection listing, collection merchandising rails — sits beside this one in the taxonomy. The hubs linked above are the ones with published evidence today.
Answers to Help You Make Smart Decisions
Do I need a filter app to get faceted navigation on Shopify? No. Shopify's Search & Discovery filters are native, configured in the admin, and expose values, counts, removal URLs and price bounds to the theme. Of the 22 builds here, 21 kept that index and changed only the interface around it — swatches, accordions, suppression rules and the behavior after a filter re-render. One moved its result set to a service outside the theme, and only because the catalog is shade-led.
Can Shopify filter a collection by variant instead of by product? Not natively. Storefront filtering operates on products, so a 12-shade product is one card and one filter match. One build in this corpus moved the result set to a service that indexes variants and returns facet metadata with them. It works, and it means the storefront now depends on an index outside the theme that it did not previously have to run.
Will load more or infinite scroll break my filters? It breaks them if paging and filtering use different transports. Both here re-fetch the same section with the current URL plus a page parameter, so active facets and sort carry forward automatically. The real hazard is quieter: the fetched HTML replaces the grid, so anything bound inside it — reviews, wishlist, analytics — has to be re-initialized deliberately.
Do filtered collection pages stay real URLs? That depends on the strategy. Shopify's facets express state in the query string; the tag-permalink mode on one of these storefronts builds path-based URLs instead, so each filtered view is a shareable, server-rendered page with a no-JS fallback behind it. Which one fits is a catalog and taxonomy decision, not a preference.
Ready to Fix the Filtering on Your Collection Pages?
Filtering is where a shopper decides whether your catalog is worth the effort. Contact us today and we'll tell you which half of your filter problem is actually an app problem — and which half was always going to be theme code.