Why We Switched from theme_store_id to schema_name and What the Data Showed
What our instrumentation revealed about theme_store_id and why we replaced it.
Of 175k+ unique theme IDs in our dataset, only 66k had a valid theme_store_id. The identifier our entire theme automation was built on covered 37% of real-world merchant themes. We thought it covered everything.
If you’re building a Shopify app that touches the storefront, you already know the pain. 1000+ themes in the Shopify theme store, countless custom and agency-built themes, and merchants who expect your app to just work regardless of which one they’re on. No configuration, no support ticket, no “please contact our team.” Just works.
That’s the bar we set for Wishlist Plus. Install it like you install Twitter on your phone. It works on day one, on your storefront, whatever that storefront looks like.
The mechanism we built to get there was theme presets, i.e a map of known themes to the exact CSS selectors needed to inject our UI correctly.
We use a productLinkSelector and an attachButtonSelector to position the wishlist button on a product card on collections grids. Our header implementation needs selectors to find the cart icon in the header and so on. Get the selectors wrong and the experience breaks. Get them right and it’s invisible (merchants never think about it).
The key to this whole system was theme_store_id. You look up the window.Shopify.theme.theme_store_id find your matching preset, apply the right selectors. This was the assumed approach. Inherited wisdom passed down through the codebase. Nobody had questioned it.
We should have questioned it sooner.
Theme presets aren’t new. Apps have been shipping selector maps since the Shopify’s ecosystem first matured enough to need them. The first principles haven’t changed, you still need to know which theme you’re on to inject correctly. What has changed is the scale. 1000+ themes, countless custom builds, and a theme identifier that was never designed to scale with the ecosystem it was supposed to describe.
The quiet tax
The failure mode wasn’t dramatic. The system didn’t fall over. What happened instead was subtler: when a merchant’s theme had no matching theme_store_id in our preset map, the experience broke for that merchant specifically. They’d raise a support ticket. Support would investigate, identify the theme, add the preset manually, fix it for that merchant. Everyone moved on.
On the surface, this looked like a support team doing its job. What it actually was: our automation silently failing for a large chunk of merchants, and humans absorbing the cost of a broken assumption in the codebase.
There’s no alert for “theme coverage is poor.” No dashboard that says “X% of installs fell through to the generic fallback.” What you get instead is a support queue that feels manageable, because you have no baseline to compare it against. The system looked healthy. It wasn’t.
We didn’t know how large those gaps were until we had the data to look.
The number that changed everything
We’d built an system that gave us real visibility into what was actually live on merchant storefronts. This was data we’d never had clean access to before. When we started re-examining our theme presets during a revamp of our Collections button, we pulled that data and looked at our theme_store_id coverage properly for the first time.
175k+ unique theme IDs in our dataset.
Only 66k had a valid theme_store_id.
That’s ~37% coverage. We were flying blind on 63% of the themes in our merchant base.
The assumption that had been quietly running our theme identification layer covered barely a third of the real world.
The fix was hiding in a changelog
We have Shopify’s RSS feed piped into Slack. While we were re-examining our preset logic, a changelog entry caught my eye: schema_name.
Shopify had introduced schema_name specifically to address the gaps in theme_store_id coverage, a more consistently populated identifier for theme identification. The question was how much better it actually was in practice. So we cross-referenced it against the same dataset.
140k+ of those same theme IDs had a valid schema_name.
Coverage jumped from 37% to above ~85%.
That was the moment. We refactored the entire theme identification layer to use schema_name as the primary identifier. The preset map that had previously keyed on theme_store_id now keys on schema_name. Every theme lookup, now running through the new identifier.
The before and after in the code was straightforward once the decision was made. The hard part was realising the decision needed to be made at all.
The honest caveat
This isn’t a complete solution. Custom and agency-built themes often have their own schema_name values that aren’t regulated by Shopify. We don’t maintain presets for those and we don’t want to, they’re one-offs that don’t scale. Those merchants still fall through to a generic fallback. It’s a known gap we live with.
Going from 37% to 85%+ coverage doesn’t mean the problem is solved. It means it’s dramatically smaller. The tickets that remain are genuinely one-off situations that need human attention regardless of which identifier you use. That's a different, more tractable problem.
What this means for you
If you’re building a Shopify app that relies on theme identification, presets, selector maps, theme-specific behaviour of any kind please check your theme_store_id coverage. Pull your data if you have it.If you don’t have the instrumentation to check, that’s a separate problem worth solving first.
You can read schema_name the same way you’d read theme_store_id, it’s right there at window.Shopify.theme.schema_name
And if you’re not monitoring Shopify’s RSS changelog, start. This fix was sitting in a changelog entry. It wasn’t announced loudly. It wasn’t in a developer blog post. It was just there, waiting for someone to connect the dots.
The dots were worth connecting.
Building on Shopify storefronts at scale? I’d love to compare notes. Find me on X or LinkedIn.





AWESOME Ishaan!
You are bringing to bear the CONTEXT that you have been accruing over time, which enables you to detect patterns and gaps even, unconsciously. Nice job!