preview_theme_id: How Shopify Theme Preview Links Really Work
Your client says the new template is broken. It isn’t — they clicked a link and the preview parameter didn’t come with them. Here is what these URLs actually do.
The two parameters that do all the work
Shopify theme previewing comes down to two query parameters that get confused constantly, because they look similar and do completely different things.
| Parameter | What it selects | Sticky across clicks? |
|---|---|---|
preview_theme_id | Which theme renders the page | Yes — for the rest of the session |
view | Which alternate template renders this resource | No — one request only |
preview_theme_id selects the theme
Add it to any storefront URL and Shopify renders that page with the theme you named instead of the live one:
https://client-store.myshopify.com/?preview_theme_id=123456789
Shopify sets a session cookie from that first request, which is why the client can then browse the whole storefront and keep seeing your theme. This is the part that works well.
view selects an alternate template
Shopify themes support alternate templates — product.bundle.json, page.lookbook.json, collection.sale.json. Normally a template only renders when a merchant assigns it to a specific product or page in the admin. ?view= lets you force it without assigning anything:
# Render product.bundle.json for this product, on theme 123456789
https://client-store.myshopify.com/products/variety-pack?preview_theme_id=123456789&view=bundle
# Render page.lookbook.json for this page
https://client-store.myshopify.com/pages/about?preview_theme_id=123456789&view=lookbook
The false bug this creates in every review round
Here's the sequence that eats an afternoon roughly once per project.
You've built a new bundle template. You send the client a link with ?view=bundle. They open it and it looks great. Then they do the thing any reasonable person does during a review: they click another product to check it there too.
That click goes to /products/some-other-thing with no view parameter. Shopify renders the default product template — correctly, on your theme. The client sees the old design and reports that the new template has stopped working, or works "only sometimes."
You now spend an hour proving a bug that doesn't exist. Worse, if the client has already told their own stakeholder the redesign is broken, you're doing that in public.
The related trap: sending the wrong resource
?view=bundle on a product that isn't a bundle renders your bundle template with unrelated product data — wrong images, wrong price, wrong copy length. Technically the template is fine. To the client it looks like a broken page, and their feedback will be about content problems you can't fix because they aren't real.
Preview each template on the page it actually applies to
The durable fix is to stop relying on ?view= as the mechanism a client experiences, and instead review each template on a resource where that template is genuinely the right one.
In practice that means keeping a deliberate list: this template, that URL. product.bundle previews on the actual variety pack. page.lookbook previews on the real lookbook page. collection.sale previews on the sale collection. When you know the real URLs, the preview link stops being a trick and starts being a page.
Give them an index, not a pile of links
Instead of pasting six URLs into an email, hand over one link that lists the templates in scope with a short label for each. That does three things a list of raw URLs can't: it tells the client what's in scope, it survives across revision rounds, and it means you're never asked to reissue links.
Other things that break preview links
Password-protected storefronts. If the store isn't launched, the client hits the password gate before they see anything. Send the storefront password in the same message — the round trip to ask for it costs you a day.
Shopify's own share-preview links are time-limited. The share link generated from the admin expires on Shopify's schedule, not your project's. Fine for a one-off look, unreliable as the link you put in a statement of work.
Cookies and stale sessions. Because preview_theme_id sets a session cookie, a client who previewed an older theme last week can land on the wrong one. If someone reports seeing an old build, have them open the link in a private window before you investigate anything else.
Apps and scripts behave differently. Some apps only inject on the published theme, so a preview can legitimately be missing a widget that will appear live. Worth saying up front so the client doesn't log it as a bug.
Analytics pollution. Client review traffic on the real storefront lands in the merchant's analytics. Usually negligible, occasionally worth mentioning to a data-sensitive client before they notice a spike.
| Client says… | Most likely cause | Check first |
|---|---|---|
| "The new design is gone" | Navigated away, view dropped | Reopen from the review index |
| "It looks like the old version" | Stale preview cookie | Private window |
| "It asks for a password" | Storefront password enabled | Send the password |
| "The reviews widget is missing" | App only injects on the live theme | Confirm app behaviour |
| "The product is wrong" | view forced onto an unrelated resource | Map to a real matching page |
How ThemeSync handles preview links
- Template mapping stores the real URL for each template. Using read-only Admin API access, you pick the actual product, collection, page or article a template applies to, so previews render on representative pages instead of arbitrary ones.
- Preview links are generated with both parameters correct. Each mapped template produces a URL combining the theme id and the right
viewfor that resource — no hand-assembled query strings. - Clients get one review portal, not a pile of links. A single page lists every template in scope with labels and page types, so the client always has a way back when navigation drops them onto a default template.
- The link is stable across revision rounds. Because it points at the theme rather than a snapshot, the same URL keeps working as you push changes.
- It works on development themes. Nothing has to be published, and no draft copy of your source has to sit in the client's admin for a review to happen.
Takeaways
preview_theme_idchooses the theme and persists for the session.viewchooses the template and lasts exactly one request.- That asymmetry is why clients report the redesign as broken after a single click. It's a link problem, not a build problem.
- Forcing
?view=onto an unrelated product produces feedback about content issues that aren't real. - Preview each template on a resource it genuinely applies to, using real store data.
- Hand over one review index rather than a list of URLs, and say what to do if a page looks wrong.
- Send the storefront password up front, and reach for a private window before debugging "it looks old."
Preview links your client can’t accidentally break
ThemeSync maps every template to the real page it applies to and gives clients one review portal that keeps working across revision rounds — all on a development theme.
Try ThemeSync Free →