Description
- fix cart page: product shows a random image, not the primary image
- buy me a coffee

#1. Install Code
You can use this code to Code Injection > Footer
<!-- 07.26c16v2 Product Image in Cart Page -->
<script>
(function () {
var productCache = {};
function slug(s){ return String(s).toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,''); }
function getProductData(url) {
var key = url.split('?')[0];
if (productCache[key]) return productCache[key];
productCache[key] = fetch(key + '?format=json&noredirect', { headers: { 'Accept': 'application/json' } })
.then(function (r) { return r.json(); })
.then(function (j) { return j.item || null; })
.catch(function () { return null; });
return productCache[key];
}
function findRow(imgEl) {
var el = imgEl;
for (var i = 0; i < 8 && el; i++) {
if (el.querySelector && el.querySelector('a[href*="/p/"]')) return el;
el = el.parentElement;
}
return null;
}
function parseVariantText(row) {
var vEl = row.querySelector('.cart-row-variants');
if (!vEl) return null;
var txt = (vEl.textContent || '').trim();
if (!txt) return null;
var attrs = {};
txt.split(/[\n\u2022|]/).forEach(function (part) {
var idx = part.indexOf(':');
if (idx > -1) attrs[slug(part.slice(0, idx))] = slug(part.slice(idx + 1));
else if (part.trim()) attrs['_' + Object.keys(attrs).length] = slug(part);
});
return Object.keys(attrs).length ? attrs : null;
}
function assetBase(im) {
return (im && im.assetUrl) ? im.assetUrl.split('?')[0] : null;
}
function pickAsset(item, wantAttrs) {
var gallery = item.items || [];
var mainBase = item.assetUrl ? item.assetUrl.split('?')[0] : null;
if (!wantAttrs) return mainBase;
var wantVals = Object.keys(wantAttrs).map(function (k) { return wantAttrs[k]; });
for (var i = 0; i < gallery.length; i++) {
var base = assetBase(gallery[i]);
if (!base) continue;
var fn = slug(base.split('/').pop());
if (wantVals.every(function (v) { return v && fn.indexOf(v) > -1; })) return base;
}
var variants = item.variants || [];
for (var k = 0; k < variants.length; k++) {
var va = variants[k].attributes || {};
var vSlugs = Object.keys(va).map(function (kk) { return slug(va[kk]); });
if (wantVals.every(function (v) { return vSlugs.indexOf(v) > -1; })) {
if (variants[k].image && variants[k].image.assetUrl) return variants[k].image.assetUrl.split('?')[0];
if (gallery[k]) return assetBase(gallery[k]);
}
}
return mainBase;
}
function fixCart() {
document.querySelectorAll('.cart-row-img').forEach(function (imgDiv) {
var row = findRow(imgDiv);
var link = row && row.querySelector('a[href*="/p/"]');
if (!link) return;
var wantAttrs = parseVariantText(row);
getProductData(link.getAttribute('href')).then(function (item) {
if (!item) return;
var newBase = pickAsset(item, wantAttrs);
if (!newBase) return;
var cur = imgDiv.getAttribute('style') || '';
var m = cur.match(/url\(["']?([^"')]+)/);
var curBase = m ? m[1].split('?')[0] : '';
if (curBase === newBase) return;
var fmt = (m && /[?&]format=[^&]+/.test(m[1]))
? m[1].match(/[?&]format=[^&]+/)[0].replace('&', '?')
: '?format=300w';
imgDiv.style.backgroundImage = 'url("' + newBase + fmt + '")';
});
});
}
fixCart();
new MutationObserver(fixCart).observe(document.body, { childList: true, subtree: true });
})();
</script>

#2. Customize
nothing now