Why JSON Templates Break When You Move Them Between Stores
The template worked perfectly on your build store. On the client’s store half the sections are empty. Nothing is broken — the settings point at IDs that only existed somewhere else.
Why this happens at all
Shopify themes separate structure from content, which is normally an advantage. A section defines how a featured collection renders; the JSON template records which collection to render and where the section sits.
The catch is how "which" gets stored. When you pick a collection in the theme editor, Shopify writes the record's identifier into the JSON:
{
"sections": {
"featured": {
"type": "featured-collection",
"settings": {
"collection": "412698312905",
"products_to_show": 8
}
}
}
}
412698312905 is meaningful on exactly one store. Push that file anywhere else and Shopify looks for a collection with that ID, finds nothing, and renders the section with no products. No error. No warning in the editor. Just an empty band on the page.
Everything that doesn’t travel
Collection pickers are the most common case, not the only one. Anything a merchant selects from their own catalogue is stored as a reference.
| Setting type | Stored as | Symptom on another store |
|---|---|---|
| Collection picker | Numeric collection ID | Section renders with no products |
| Product picker | Numeric product ID | Featured product block is blank |
| Page picker | Numeric page ID | Empty rich-text area or dead link |
| Blog / article picker | Numeric blog or article ID | Latest-posts section shows nothing |
| Metaobject reference | Metaobject GID | Section renders, all fields empty |
| Dynamic source (metafield) | Namespace and key binding | Falls back to blank if the definition is absent |
| Uploaded image | Files-API reference | Broken or missing image |
| App block | App-specific block ID | Block dropped, or the template errors |
| Menu / link list | Menu handle | Empty navigation, or falls back to main-menu |
Two of these deserve extra caution.
App blocks reference a specific app installation. If the target store doesn't have the app, the block can prevent the template loading properly rather than just rendering empty — a harder failure than a blank section.
Metaobjects and metafields fail in the most confusing way, because the section renders its full layout with every field empty. It looks like a CSS bug. It isn't.
The workflow that avoids it
The root cause is building against store A and delivering to store B. Two ways out, and they suit different projects.
Option 1: build against the real store
Develop on a theme attached to the client's actual store from day one. Every collection you pick is a real collection, every product is a real product, and there's nothing to translate at the end.
This is the better default for client work, and it needs a development theme so you aren't putting unfinished work into their theme list. It also means the client reviews real content rather than placeholder data, which surfaces content problems early instead of at launch.
Option 2: migrate deliberately
Sometimes you can't build on the real store — it doesn't exist yet, or the merchant won't grant access until contracts are signed. Then migration is a task with its own budget, not a copy-paste.
- Push code first, configuration second. Get Liquid, CSS and JS onto the target store and confirm it renders.
- Strip store-specific references before pushing JSON. Better an empty picker you know about than a broken one you don't.
- Recreate metafield and metaobject definitions before the templates that use them. Bindings can't resolve against definitions that don't exist.
- Install apps before pushing templates containing their blocks.
- Re-pick every reference on the target store and keep a checklist so you can prove you covered them all.
- Screenshot every template afterwards. Empty sections are obvious in a screenshot and invisible in a diff.
Finding the references before your client does
Store-specific references are greppable. Long digit strings and gid:// URIs in JSON files are almost always IDs:
# Numeric IDs in section settings (10+ digits)
grep -rnE '"[a-z_]+": "[0-9]{10,}"' templates/ config/settings_data.json
# Metaobject and other global IDs
grep -rn 'gid://shopify' templates/ config/
# App blocks embedded in templates
grep -rn '"type": "shopify://apps' templates/
Run that before a migration and you have your work list. Run it after and you have your verification. Either way, the crucial follow-up is visual: load every template and look at it. A missing product reference is a diff you'll skim past and a blank section you can't miss.
How ThemeSync handles this
- You build against the client's real store from day one. A cloud development theme runs on their store with their catalogue, so pickers reference real records and there's no migration step to get wrong.
- Templates can be sanitised before pushing. When work does have to move between stores, store-specific and dynamic references can be stripped and restored deliberately rather than pushed blind.
- App blocks and dynamic sources are detected. Templates carrying app blocks or metafield bindings are identified up front, so you know which ones depend on store setup before you move them.
- Template mapping makes empty sections visible. Every template is opened on the real page it applies to, so a section with nothing in it shows up during review instead of after launch.
- Screenshot runs cover every mapped template. Capturing all templates across devices catches blank sections and mobile gaps in one pass.
Takeaways
- Theme code is portable. Theme configuration is not — it holds IDs belonging to one store.
- Collection, product, page, blog, metaobject, image, menu and app-block references all break when moved.
- Failures are silent. Sections render empty rather than erroring, so the client finds them.
- The best fix is not needing one: build against the client's real store on a development theme.
- When you must migrate, push code first, strip references, recreate metafield definitions and install apps before pushing templates.
- Grep for long numeric IDs and
gid://to build the work list, then verify visually on desktop and mobile.
Build on the client’s real store from day one
ThemeSync runs a development theme on your client’s actual store with their real catalogue — so section references are correct from the first commit and there’s nothing to migrate.
Try ThemeSync Free →