The browser treats these as different resources and re-downloads every image when we swap in the API data - even though they’re already cached from the initial Liquid render.
I see in the performance docs that myshopify.com URLs are intentional for connection reuse on storefronts. Makes sense for pure Liquid, but creates double-fetching when you mix Liquid with Storefront API.
Questions:
Is there a way to get myshopify.com URLs from the Storefront API (e.g. a parameter on image.url or transformedSrc)?
Alternatively, is there a parameter for Liquid’s image_url to return cdn.shopify.com URLs?
hii.. i can fix your problem..So the bug in your image is .Your Images were loading twice because Shopify serves them from two different domains. I fixed it by standardizing URLs so the browser reuses cached assets instead of re-downloading them.
Hi @Anton! You’ve identified the behavior correctly, and unfortunately there’s no parameter on either side to control the URL domain. This is a deliberate design choice documented in the Changes to Merchant Asset URLs changelog from May 2023. It specifically states that “the old format will continue to be used in all API responses.” Liquid uses storefront-domain URLs ({shop}.myshopify.com/cdn/...) to maximize connection reuse in the browser, while the Storefront API uses cdn.shopify.com because headless storefronts don’t benefit from that optimization. Both URL formats point to the same image and both will continue to work indefinitely.
I’ll raise this as feedback internally. The hybrid Liquid + Storefront API pattern is a valid use case that the current URL strategy doesn’t account for well. Let us know if you find a workable solution on your end - I did think of client side URL normalization but I’m not in a position to test it right now, might be worth a look!
If you update the UI after server-rendering you should be able to pass the Liquid imageURLs to the JS handling the hydration, for example many themes use the pattern of putting any data necessary for JS in a DOM json script tag.
I was suggesting their MCP sever as it’s good with questions like yours, e.g. it’s behaving like X here and Y there, is this correct behavior and is there a workaround.
I had not plugged in your question but when I do it says 1) no 2) no and 3)
The domain split and its rationale are explicitly documented in the asset URL changelog, but there’s no public indication of a planned toggle to unify domains. To get this specific mixed-Liquid+Storefront-API caching issue considered, you’d need to file feedback via Shopify Support or the Partner dashboard so it can be logged as a feature request.
Which sounds like what Donal points out in a later reply.
If I then ask it to give me a JavaScript workaround it gives:
// Choose your canonical base (pick ONE and use it everywhere)
const CDN_BASE = 'https://cdn.shopify.com'; // or `https://your-store.myshopify.com`
function normalizeShopifyImageUrl(url) {
if (!url) return url;
try {
const u = new URL(url, window.location.origin);
// Only touch Shopify image-style paths
const isShopifyCdnLike =
u.hostname.includes('cdn.shopify.com') ||
u.pathname.startsWith('/cdn/shop/') || // myshopify.com/cdn/...
u.pathname.startsWith('/s/files/'); // older cdn paths
if (!isShopifyCdnLike) return url;
// Use only the path + search to keep transforms (?width=, etc.)
return CDN_BASE + u.pathname + u.search;
} catch {
return url;
}
}
// Normalize all existing img src attributes (Liquid-rendered)
function normalizeAllLiquidImages() {
document.querySelectorAll('img[src]').forEach(img => {
const normalized = normalizeShopifyImageUrl(img.src);
if (normalized && normalized !== img.src) {
img.src = normalized;
}
});
}
document.addEventListener('DOMContentLoaded', normalizeAllLiquidImages);