Free Shopify store auditSpeed, SEO and conversion leaks — no cost, no obligation.
Claim it
Thriftizer Solutions LLPShopify Select Partner
Book a Growth Audit
Shopify Aug 9, 2026 8 min read

Rebuilding WooCommerce Product Filters in Shopify Search & Discovery

Shopify collection filters read from variant options and metafields, not tags. Here's how we map WooCommerce attributes across, plus the price-band and filter-URL traps that cost traffic.

If you came here looking for where Shopify collection filters live: they're in the free Search & Discovery app, under Filters, and they can only read from a fixed set of sources. Variant options, product type, vendor, price, stock status, and metafields you've defined and marked as filterable. That last one is the whole migration. Every WooCommerce attribute that isn't driving price or stock becomes a metafield, and if you don't create those definitions before you import products, you'll import twice.

The rest of this is the mapping work: what goes where, what breaks, and the bits we still get wrong on the first pass.

WooCommerce attributes and Shopify options are not the same object

In WooCommerce, an attribute is a taxonomy. You register Fabric once, it gets terms (Cotton, Linen, Rayon), and any product can carry it whether or not it's used for variations. A product can have twelve attributes. Layered nav plugins read the taxonomy and build a filter out of it. Attributes are cheap and there's no ceiling worth worrying about.

Shopify splits that idea in two. Variant options are the things that create SKUs, and you get three of them per product. Everything else descriptive has to live in a metafield, which is a typed field attached to the product, with its own definition, its own storefront access setting, and no relationship to the variant matrix at all.

So a Woo store with nine attributes doesn't map cleanly. Three of them, at most, survive as options. The other six get rebuilt as metafields, and that's fine, because most of them were never doing variant work anyway. They were there so the sidebar had something to show.

Sort every attribute into one of three buckets

Before touching an export, we put every Woo attribute in a spreadsheet and assign it:

  • Variant option. The customer's choice changes the SKU, the price, the stock number or the image. Size, colour, pack size, storage capacity. Cap of three, and you want to spend that cap carefully.
  • Filterable metafield. True of the product regardless of which variant is picked. Fabric, occasion, sleeve length, skin type, wattage, certification, country of origin.
  • Delete. There's always a pile of these. Attributes with one term. Attributes used on nine products out of four thousand. An attribute called "New" that someone added in 2019 and never removed.

The awkward one is an attribute that's variant-level but you've already spent your three options. A lehenga with Size, Colour and Blouse Stitching Type is full. If Fabric also varies between variants of the same product, you have a decision, not a solution: either split into separate products, or store fabric at product level and accept that the filter is telling a partial truth. We store it at product level and move on. Per-variant descriptive attributes turn into a maintenance problem nobody feeds after month three.

Define metafields first, then import

The definition decides whether a filter is even possible, so this order matters. Practical rules from doing it repeatedly:

  • Use list types for anything multi-valued. An occasion filter where a kurta is both "Festive" and "Wedding" needs a list of single-line text values, not a comma-jammed string. Get this wrong and you'll have a filter value literally reading "Festive, Wedding".
  • Single-line text, text lists, boolean and metaobject references are the workhorses for filtering. Check the current supported types in Search & Discovery before you commit, because a decimal or a rich-text field will import cleanly and then refuse to appear as a filter.
  • Storefront access on, always. A metafield with no storefront access is invisible to filters and to your theme.
  • Namespace and key discipline. custom.fabric is fine. Nine namespaces invented by three different people is how you end up with two fabric filters showing different values.
  • Metaobjects when the value needs its own data. Colour needs a hex code for swatches. Certification needs a logo. That's a metaobject, not a text list.

Then map the Woo CSV columns onto those metafield columns and import with Matrixify or the equivalent. Nothing exotic. The pain is never the import, it's the values.

The attribute terms are dirtier than you think

Here's a real shape of problem from a homewares catalogue. The Woo Material attribute had 47 distinct terms across roughly 4,200 products. Deduped, it was 11: Cotton, Linen, Jute, Cane, Teak, Mango Wood, Brass, Ceramic, Stoneware, Glass, Terracotta. The other 36 were spellings, plurals, and blends typed free-hand by whoever added the product that week. "Solid Teakwood", "Teak wood", "TEAK".

A 47-value filter is worse than no filter. Nobody scrolls it, and the counts split so thin that half the values return one product. So you build a mapping table, 47 rows in, 11 out, apply it in the CSV before import, and keep the sheet because you will need it again when the client sends 300 new SKUs.

Across six metafields on 4,200 products, that's up to 25,200 values to set. Most cells are blank or inherited from a category default, so the real editing is smaller, but budget the day. This is also where the dual-write question comes up: automated collection conditions and metafield filters don't draw from the same well, so if you also want a live collection of everything brass, you'll be writing a tag alongside the metafield. Annoying, and there's no clever way around it.

Price filters, and why rupee bands go stale

Shopify gives you one price control: a range with a min and a max. Woo stores frequently ran bucketed price filters instead, the "Under ₹999 / ₹1,000–1,999 / ₹2,000–4,999" pattern, which converts better on mobile because it's two taps instead of dragging a slider with your thumb.

The obvious workaround is a price_band metafield. It works until a sale. Take a ₹2,400 kurta in the ₹2,000–4,999 band. Festive discount at 30% puts it at ₹1,680, which belongs in ₹1,000–1,999. Do that store-wide and every band on every discounted product is wrong for the length of the campaign, and wrong again when the sale ends. Two rewrites of 4,200 rows per campaign.

Either automate the band write with a Flow job triggered on price change, or use the native range slider and stop pretending. We usually take the slider for stores under a few thousand SKUs and only build bands where the merchandising team has asked for them by name.

Three things you lose in the move

Per-collection filter sets. Filters in Search & Discovery are defined at store level. Values with no matching products hide themselves on a given collection, which covers most cases, but you can't easily say "show Wattage only inside Lighting". If your Woo setup had hand-tuned sidebars per category, someone is going to notice.

AND within a group. Native behaviour is OR inside a filter and AND between filters. Cotton or Linen, and Under ₹2,000. If your old sidebar could find products tagged both Cotton and Linen, that logic doesn't exist here.

Indexable filter URLs. This is the one that actually costs money. Woo layered nav and product-tag archives often accumulate real organic traffic on pages like /product-tag/brass-planter. Shopify's filtered URLs use query parameters and aren't built to rank. If those pages are pulling search traffic, audit them before you switch, then rebuild the winners as proper collections with their own handle, title and copy, and redirect. Skipping this step is the most common reason a technically clean Shopify migration reads as a traffic drop in month two. We flag it on nearly every Woo project and it still gets deprioritised about a third of the time.

The theme side: swatches, order, and not reloading the page

Filter values render in the order the app sets, and alphabetical is rarely right. Size should read XS, S, M, L, XL, not L, M, S, XL, XS. Fix the order in the app, or in the metaobject option values, not in your head.

Colour swatches in current Shopify themes come from option values backed by metaobjects with a colour or image field. If you migrated colour as plain text you'll get text pills, which is acceptable and boring. Converting to metaobjects afterwards is possible and tedious.

Check that filter clicks re-render the product grid through the Section Rendering API rather than reloading the document. Most modern themes do this correctly; heavily modified ones often don't, and a full reload on every filter tap on a 3G connection in a tier-2 city is how a functioning filter still loses the sale. Same principle as the rest of store speed work: measure the interaction, not the homepage score.

When native collection filters run out

Search & Discovery is genuinely good and it's free, so start there. It stops being enough at fairly predictable points: catalogues past roughly 10,000 SKUs where you need per-collection filter configurations, stores that need AND logic or true price bucketing, and any store where on-site search is the primary navigation path and native keyword matching keeps missing. Native search indexes titles, descriptions, tags, SKUs, vendor and type. It does not understand that a shopper typing "gift for mum under 2000" means anything.

That's the gap our own app was built for. FilterPro adds configurable filters and AI-driven search on top of the same product data, so you keep the metafield structure you just built and change what reads it. If native filters are working for you, don't install anything.

A sane order of work

  1. Export Woo attributes with usage counts. Kill anything under 1% coverage.
  2. Assign each survivor to option, metafield, or bin.
  3. Build the term mapping sheet. Get the client to sign off on the canonical values.
  4. Create metafield definitions with correct types and storefront access.
  5. Import products with metafield columns mapped.
  6. Configure filters in Search & Discovery, set value order, test on the three collections with the most SKUs.
  7. Redirect the old layered-nav and tag URLs that had traffic.

If you're mid-migration and want a second pair of eyes on the attribute mapping before the import runs, send us the export and the current sidebar screenshots through a free audit. It's a two-hour read on our side and it's much cheaper than re-importing 25,000 metafield values.

Previous postNext post

Ready to scale your D2C brand profitably?

Let's build a growth engine that drives more traffic, more conversions and more profit.

Book a Growth Audit
📅 Free Audit💬 WhatsApp