WordPress / SEO

Programmatic SEO for a WooCommerce Store's Filter Pages

Turning a tire retailer's WooCommerce attribute filters into thousands of indexable landing pages: dynamic titles & meta, pretty URLs, and careful index control.

  • WordPress
  • WooCommerce
  • PHP
  • WPML
  • Technical SEO
Illustration of a filter funnel producing ranked landing pages

The opportunity

A Ukrainian tire e-commerce store on WooCommerce had a classic long-tail problem. People don’t search for “tires” — they search for “winter tires 205/55 R16”, i.e. a specific combination of season, width, profile and diameter. The store already had all of that as WooCommerce product attributes and a filter plugin that let visitors narrow down products. But those filtered views were invisible to Google: ugly query-string URLs, a generic shop <title> on every combination, and no strategy for which of the millions of possible filter combinations should actually be indexed.

The goal: turn the valuable filter combinations into real, rankable landing pages — without letting the near-infinite combinatorial space of filters flood the index with thin, duplicate junk.

What I built (all in a child theme, ~36 focused modules)

  • Dynamic titles & meta descriptions from the filter state. On a filtered shop URL, PHP reads the active filters (manufacturer, season, profile, width…) and builds a human, keyword-rich <title> and meta description on the fly — “Winter tires 205/55 R16 — buy in Ukraine” — including translating attribute slugs into proper words (zymovi → «зимові») and appending brand, price-from and delivery text. Every meaningful combination gets its own tailored snippet instead of the shop default.

  • Pretty, crawlable URLs. Custom rewrite_rules_array rules turn query-string and /shop/... paths into clean, hierarchical ones like /shyny/{category}/ and a segmented /shynu/{season}/{manufacturer}/{width}/{profile}/{diameter}/ structure — the kind of URL that both users and search engines trust.

  • Deliberate index control — the hard part. Left alone, filters generate an effectively infinite URL space, which is an SEO disaster. So there’s a rule: pages with 4 or more simultaneous filters get a noindex tag (too specific, too thin, cannibalizing). But the chosen high-value landing combinations get their noindex actively stripped via output buffering, so exactly the pages worth ranking are the ones Google is allowed to keep.

  • Pagination done right. rel="prev" / rel="next" links plus “Page N” appended to titles and meta descriptions, so paginated category pages don’t fight each other as duplicates.

  • Canonical dedup on the shop page, and hreflang corrections for the bilingual (Ukrainian / Russian) setup, patched at the output-buffer level where the SEO plugin and WPML disagreed.

  • Per-language dynamic H1s rebuilt from the selected filters, so a filtered page’s visible heading matches its title and the user’s language.

The result

Instead of one invisible shop page behind a query string, the store exposed a structured, controllable set of landing pages mapped to how people actually search for tires — with strict guardrails so only the pages worth indexing were indexed. It’s the difference between “we have a filter” and “our filters are our long-tail SEO.”

The engineering takeaway

None of this was a plugin I could install — it’s the seam between three of them (WooCommerce, a filter plugin, and an SEO plugin), and that seam is exactly where custom code earns its keep. Everything lives in the child theme as small, single-responsibility modules (one file removes the archive-title prefix, one handles canonicals, one builds the dynamic title…), so the SEO logic is readable and auditable instead of buried in a 2000-line functions.php.