All things Shopify and commerce
I have a weird issue with the attribute data. I have read similar cases, but I haven’t found the correct answer. I have this code that adds a value fetched from the URL params and stores it in sessionStorage (just in case) and in cart.json, so I can have this value in my orders and generate reports based on this data. Recently, I added a "default" value to one of these fields so that if it is not loaded in the params or session, I get a "default value." This way, if for any reason I need to modify this value in the orders, I have this "key=value" available and don’t have to depend on a third party to allow me to add it. Does that make sense?
After adding this "default value," we noticed that several orders are arriving without this value, which concerns us because our business model depends on having reliable information in all cases. Am I executing the code incorrectly? I’ve tested multiple cases, and in all of them, the value from cart.json is coming through correctly (verified through console.log), but it is not being sent with the order when it passes through the checkout.
Here is my script, and I have it in the theme.liquid.
<script> document.addEventListener("DOMContentLoaded", async function () { console.log("🚀 Script cargado en:", window.location.href); // Obtener 'sref' y 'ml-shared-cart-id' de la URL const urlParams = new URLSearchParams(window.location.search); let specialistRef = urlParams.get('sref') || sessionStorage.getItem('sref') || "0000"; let shareCart = urlParams.get('ml-shared-cart-id') || sessionStorage.getItem('shareCart') || ""; console.log("🔍 'sref' en URL o SessionStorage:", specialistRef); console.log("🔍 'ml-shared-cart-id' en URL o SessionStorage:", shareCart); // Guardar valores en sessionStorage si vienen en la URL if (urlParams.get('sref')) { sessionStorage.setItem('sref', specialistRef); } if (urlParams.get('ml-shared-cart-id')) { sessionStorage.setItem('shareCart', shareCart); } // Obtener datos actuales del carrito const cartResponse = await fetch('/cart.js'); const cartData = await cartResponse.json(); let currentSpecialistRef = cartData.attributes?.specialist_ref || ""; console.log("📦 'specialist_ref' actual en el carrito:", currentSpecialistRef); // Lógica de actualización: // 1. Si el carrito tiene un 'specialist_ref' diferente de 0000 y viene otro diferente de 0000 → ACTUALIZAR // 2. Si el carrito tiene '0000' o está vacío → ACTUALIZAR con el mejor valor disponible // 3. Si el carrito ya tiene un valor válido y el nuevo es '0000' → NO MODIFICAR if ( (currentSpecialistRef !== "0000" && specialistRef !== "0000" && currentSpecialistRef !== specialistRef) || (currentSpecialistRef === "" || currentSpecialistRef === "0000") ) { fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ attributes: { specialist_ref: specialistRef, share_cart: shareCart || "" } }), }) .then(response => response.json()) .then(data => { console.log("✅ Notas del carrito actualizadas:", data); }) .catch(error => console.error("⚠️ Error actualizando notas del carrito:", error)); } else { console.log("✅ 'specialist_ref' ya es válido y no se modifica."); } }); </script>
I added two data attributes where in one, the specialist_ref is present, and in the other, it is not (both orders were placed on the same day, one following the other)
thanks for any help!
Hey @vitahuber,
The core issue seems to be that while your cart attributes (specialist_ref and share_cart) are being properly set in the cart.json, they're not consistently passing through to your orders. This is a common challenge in Shopify when working with cart attributes.
Here's what's likely happening:
Here's a solution approach:
// Add this code to your theme.liquid file, after your existing script {% if first_time_accessed %} <script> if (Shopify && Shopify.Checkout && Shopify.Checkout.step === "contact_information") { // Get values from sessionStorage const specialistRef = sessionStorage.getItem('sref') || "0000"; const shareCart = sessionStorage.getItem('shareCart') || ""; // Add hidden fields to the checkout form to persist cart attributes document.addEventListener('DOMContentLoaded', function() { const form = document.querySelector('form'); if (form) { // Create and append hidden input for specialist_ref const specialistRefInput = document.createElement('input'); specialistRefInput.type = 'hidden'; specialistRefInput.name = 'checkout[attributes][specialist_ref]'; specialistRefInput.value = specialistRef; form.appendChild(specialistRefInput); // Create and append hidden input for share_cart const shareCartInput = document.createElement('input'); shareCartInput.type = 'hidden'; shareCartInput.name = 'checkout[attributes][share_cart]'; shareCartInput.value = shareCart; form.appendChild(shareCartInput); console.log("Added hidden fields to checkout form:", specialistRef, shareCart); } }); } </script> {% endif %}
// Change the timing of your existing script document.addEventListener("DOMContentLoaded", async function () { // Your existing code... // Add a more aggressive update approach try { const updateResponse = await fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ attributes: { specialist_ref: specialistRef, share_cart: shareCart || "" } }), }); const updateData = await updateResponse.json(); console.log("✅ Cart attributes updated:", updateData.attributes); // Store values in localStorage (more persistent than sessionStorage) localStorage.setItem('sref', specialistRef); localStorage.setItem('shareCart', shareCart || ""); } catch (error) { console.error("⚠️ Error updating cart attributes:", error); } });
// Add this to your theme.liquid after your main script {% if template contains 'cart' %} <script> // Capture values on the cart page to ensure they're available at checkout document.querySelector('form[action="/cart"]').addEventListener('submit', function() { // Get current values const specialistRef = sessionStorage.getItem('sref') || localStorage.getItem('sref') || "0000"; const shareCart = sessionStorage.getItem('shareCart') || localStorage.getItem('shareCart') || ""; // Add to note field as fallback const noteField = document.querySelector('[name="note"]'); if (noteField) { const noteText = noteField.value || ""; noteField.value = noteText + "\nspecialist_ref: " + specialistRef + "\nshare_cart: " + shareCart; } }); </script> {% endif %}
This three-pronged approach should ensure your attributes consistently pass through to orders:
Based on your description, the issue is likely in the handoff between cart and checkout. These changes should resolve the inconsistency you're seeing.
Cheers!
Shubham | Untechnickle
Helping for free: hello@untechnickle.com
Don't forget to say thanks, it'll make my day - just send me an email!
Get Revize for Free | Let your shoppers edit orders post-purchase | Get Zero Support Tickets | #1 Order Editing + Upsell App
Can this solution work if I don’t have Shopify Plus in my store? I understand that on basic plans we don’t have access to edit the checkout. Is that correct?
You're absolutely right about Shopify Plus - without it, you can't customize the checkout directly. Let me adjust my solution for a standard Shopify plan.
First, let's strengthen your existing script to make it more reliable:
Values being applied - sref:", specialistRef, "share_cart:", shareCart);
Then, add this reliable fallback to your cart page:
{% if template contains 'cart' %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Make one final update before checkout
const cartForm = document.querySelector('form[action="/cart"]');
if (cartForm) {
cartForm.addEventListener('submit', function() {
const specialistRef = localStorage.getItem('sref') || sessionStorage.getItem('sref') || "0000";
const shareCart = localStorage.getItem('shareCart') || sessionStorage.getItem('shareCart') || "";
// Backup plan: Add to cart note which reliably transfers to order notes
const noteField = document.querySelector('textarea[name="note"]');
if (noteField) {
let noteValue = noteField.value || "";
// Only add if not already there
if (!noteValue.includes("specialist_ref:")) {
noteValue += "\n--- System Data ---\nspecialist_ref: " + specialistRef + "\nshare_cart: " + shareCart;
noteField.value = noteValue;
}
}
});
}
});
</script>
{% endif %}
This approach has two safety nets:
The inconsistency you're seeing is a known limitation with standard Shopify plans. This solution won't be as clean as what you could do with Shopify Plus, but it should ensure you never lose that critical data.
Let me know if you need any clarification or have other questions!
Cheers!
Shubham | Untechnickle
Helping for free: hello@untechnickle.com
Don't forget to say thanks, it'll make my day - just send me an email!
Get Revize for Free | Let your shoppers edit orders post-purchase | Get Zero Support Tickets | #1 Order Editing + Upsell App
Hi, I tried adapting this solution (we don’t have notes on the cart page, so I pushed them like the attributes. I also added the deletion of data from localStorage so that the next purchase made by the same customer, or at least the same browser, doesn’t get assigned the same values, as that’s not what we want). I am testing to see if notes have a higher success rate than attributes. So far, I have two orders with both values loaded, and one where neither notes nor attributes appear (I can assume this cart "started" before I uploaded the change and didn’t have the updated script, so I have some doubt about that, but feel free to comment if there are any changes). My script ended up like this; I think it’s fine, but any advice is more than welcome. (In the console, when I fetch the cart.json, both notes and attributes appear).
<script>
document.addEventListener("DOMContentLoaded", async function () {
console.log("🚀 Script cargado en:", window.location.href);
// Obtener 'sref' y 'ml-shared-cart-id' de la URL
const urlParams = new URLSearchParams(window.location.search);
let specialistRef = urlParams.get('sref') || sessionStorage.getItem('sref') || localStorage.getItem('sref') || "0000";
let shareCart = urlParams.get('ml-shared-cart-id') || sessionStorage.getItem('shareCart') || localStorage.getItem('shareCart') || "";
console.log("🔍 'sref' en URL o SessionStorage:", specialistRef);
console.log("🔍 'ml-shared-cart-id' en URL o SessionStorage:", shareCart);
// Store in both sessionStorage and localStorage (belt and suspenders approach)
sessionStorage.setItem('sref', specialistRef);
localStorage.setItem('sref', specialistRef);
sessionStorage.setItem('shareCart', shareCart);
localStorage.setItem('shareCart', shareCart);
console.log("Values being applied - sref:", specialistRef, "share_cart:", shareCart);
// Obtener datos actuales del carrito
const cartResponse = await fetch('/cart.js');
const cartData = await cartResponse.json();
let currentSpecialistRef = cartData.attributes?.specialist_ref || "";
console.log("📦 'specialist_ref' actual en el carrito:", currentSpecialistRef);
// Lógica de actualización de atributos del carrito
const updateData = {
attributes: {
specialist_ref: specialistRef,
share_cart: shareCart
},
note: JSON.stringify({
specialist_ref: specialistRef,
share_cart: shareCart
})
};
// Actualizar atributos y notas del carrito
try {
const updateResponse = await fetch('/cart/update.js', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updateData)
});
if (updateResponse.ok) {
console.log("✅ Datos guardados en el carrito, limpiando localStorage...");
localStorage.removeItem('sref');
localStorage.removeItem('shareCart');
} else {
console.warn("⚠️ Error al actualizar el carrito, datos en localStorage no eliminados.");
}
const updateResponseData = await updateResponse.json();
console.log("Datos del carrito actualizados:", updateResponseData);
} catch (error) {
console.error("❌ Error al actualizar los atributos y las notas del carrito:", error);
}
});
</script>
Discover how to increase customer engagement on your store with articles from Shopify A...
By Jacqui Apr 23, 2025Hey Community 👋 Did you know that March 15th is National Everything You Think Is W...
By JasonH Apr 1, 2025Discover how to increase the efficiency of commerce operations with Shopify Academy's l...
By Jacqui Mar 26, 2025