Articles on: Developers

Shopify Cart Data Validation Script for Custom Products

Summary


This script solves a timing issue in Shopify where custom product images and prices don't load immediately when items are added to the cart. Without this solution, customers might see incomplete product information (missing images, $0 prices, or blank titles), which could lead to confusion or checkout errors.


What It Does


  • Detects when custom products (marked with _mmqProduct property) are added to the cart
  • Checks if critical product data is missing (price, image, title, product ID, or URL)
  • Displays a user-friendly overlay with a loading message to prevent interaction with incomplete data
  • Continuously polls Shopify's cart API every 6 seconds until all product information is fully loaded
  • Automatically refreshes the page once complete data is available

Problem It Solves


Shopify's backend processing for custom products can be delayed, causing a gap between when a product is added to the cart and when its full details (especially images and pricing) become available. This script bridges that gap by:


  • Preventing customers from seeing or interacting with incomplete product data
  • Ensuring accurate pricing and product information before checkout
  • Providing clear feedback that the system is working ("We are creating your custom product...")
  • Automatically resolving the issue without requiring manual page refreshes

The implementation is theme-specific (shown here for Dawn Theme) but can be adapted to any Shopify theme by adjusting the cart container selector.<br/>

This code snippet is designed for the Dawn Theme but can be easily adapted for any Shopify theme.


When products are added to the Shopify cart, they receive a _mmqProduct property. The script checks for this property to determine if it should execute.

Here's how it works:


  • First, it verifies whether the cart contains products with the _mmqProduct property
  • If found, it checks whether these products are missing critical dataโ€”specifically price or image information (configurable via variables at the start of the script)
  • When missing data is detected, the script displays an overlay on the cart page to prevent user interaction
  • It then waits for Shopify to finish processing the product data, checking at customizable intervals until the information is complete

This ensures customers don't proceed with incomplete product information in their cart.


Code


{% if template.name contains 'cart' %}
<script>
// Mimeeq Script for Cart Checking Variants Start
console.group('[Mimeeq Cart Debug]');
console.log('๐ŸŸฆ Script loaded and running');
console.log('๐Ÿ’ก To test overlay, run: window.mimeeqDebugOverlay()');

const checkPrice = true;
const checkImage = true;
const waitTime = 6000;

const items = {{ cart.items | json }};
console.log('๐Ÿ“ฆ Cart items:', items);

const isMmqProduct = items.some(i => i.properties && i.properties._mmqProduct);
const isMissingData = items.some(i => {
const missingPrice = checkPrice && (!i.price || i.price === 0);
const missingImage = checkImage && !i.image;
const missingTitle = !i.product_title;
const missingProductId = !i.product_id;
const missingUrl = !i.url;
const isMissing = missingPrice || missingImage || missingTitle || missingProductId || missingUrl;
if (isMissing) console.log('๐Ÿ” Item missing data:', i);
return isMissing;
});

console.log('๐Ÿงฉ isMmqProduct:', isMmqProduct);
console.log('โš ๏ธ isMissingData:', isMissingData);

function showMimeeqOverlay(debugMode = false) {
const cartContainer = document.querySelector('.cartitems--list');
if (!cartContainer) {
console.warn('โš ๏ธ No .cartitems--list element found');
return;
}

// --- Create overlay ---
const overlay = document.createElement('div');
overlay.id = 'mimeeq-overlay';
Object.assign(overlay.style, {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
background: 'rgba(255, 255, 255, 0.65)', // soft white-gray blur
backdropFilter: 'blur(10px)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: '9999',
pointerEvents: 'all',
transition: 'opacity 0.3s ease',
opacity: '0'
});

// --- Spinner (left of text) ---
const spinner = document.createElement('div');
Object.assign(spinner.style, {
width: '22px',
height: '22px',
border: '3px solid rgba(0,0,0,0.1)',
borderTop: '3px solid #ac7349',
borderRadius: '50%',
animation: 'mimeeq-spin 1s linear infinite',
flexShrink: '0',
marginRight: '12px'
});

// Spinner animation keyframes (add once)
if (!document.getElementById('mimeeq-spinner-style')) {
const styleTag = document.createElement('style');
styleTag.id = 'mimeeq-spinner-style';
styleTag.textContent = `
@keyframes mimeeq-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;
document.head.appendChild(styleTag);
}

// --- Message box ---
const messageBox = document.createElement('div');
Object.assign(messageBox.style, {
background: '#fff',
borderRadius: '8px',
padding: '20px 28px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 4px 16px rgba(0,0,0,0.12)',
fontFamily: 'system-ui, sans-serif',
fontSize: '16px',
color: '#000',
whiteSpace: 'nowrap',
maxWidth: '600px'
});

// --- Message text ---
const messageText = document.createElement('div');
messageText.innerText = 'We are creating your custom product. The page will refresh once itโ€™s ready.';

messageBox.appendChild(spinner);
messageBox.appendChild(messageText);
overlay.appendChild(messageBox);

// --- Attach to container ---
cartContainer.style.position = 'relative';
cartContainer.appendChild(overlay);

// --- Fade in effect ---
requestAnimationFrame(() => { overlay.style.opacity = '1'; });

console.log(debugMode ? '๐Ÿž Debug overlay shown' : '๐Ÿ“ Overlay shown');
}

function hideMimeeqOverlay() {
const overlay = document.getElementById('mimeeq-overlay');
if (!overlay) return;
overlay.style.opacity = '0';
setTimeout(() => overlay.remove(), 300);
}

window.mimeeqDebugOverlay = () => { showMimeeqOverlay(true); };
window.mimeeqHideOverlay = () => { hideMimeeqOverlay(); };

if (isMmqProduct && isMissingData) {
console.log('๐Ÿš€ Conditions met โ€” starting cart data check loop');
let finishCheck = false;
showMimeeqOverlay(false);

const getCartData = async () => {
console.log('๐Ÿ”„ Checking cart data...');
try {
const response = await fetch('/cart.js');
const { items } = await response.json();
const missingData = items.some(i => {
const missingPrice = checkPrice && (!i.price || i.price === 0);
const missingImage = checkImage && !i.image;
const missingTitle = !i.product_title;
const missingProductId = !i.product_id;
const missingUrl = !i.url;
return missingPrice || missingImage || missingTitle || missingProductId || missingUrl;
});
if (!missingData) {
finishCheck = true;
console.log('โœ… All data loaded โ€” refreshing page...');
window.location.reload();
}
} catch (error) {
console.warn('โŒ Cart refresh check failed:', error);
}
};

const interval = setInterval(async () => {
if (finishCheck) {
clearInterval(interval);
console.log('๐Ÿ›‘ Interval cleared');
} else {
await getCartData();
}
}, waitTime);
} else {
console.log('โ„น๏ธ Conditions not met โ€” script exited');
}

console.groupEnd();
// Mimeeq Script for Cart Checking Variants End
</script>
{% endif %}



Updated on: 19/02/2026

Was this article helpful?

Share your feedback

Cancel

Thank you!