missing attributes data in orders

missing attributes data in orders

vitahuber
Visitor
3 0 0

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)

order sin datos.jpgorder con datos.jpg

thanks for any help!

Replies 4 (4)

TheUntechnickle
Shopify Partner
456 49 114

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:

  1. Your script correctly updates the cart.json with the attributes
  2. However, during checkout, these attributes might not be automatically transferred to the order
  3. The inconsistency (some orders having the value, others not) suggests a race condition or timing issue

Here's a solution approach:

  1. Ensure attributes persist through checkout by making a modification to your checkout process:

 

 

// 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 %}
  1. Modify your current script to ensure it always executes before checkout:

 

 

// 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);
    }
});
  1. Add a fallback mechanism using Shopify's order note feature:

 

 
// 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:

  1. Your original script updates cart.json
  2. The checkout form receives hidden fields with the same attributes
  3. As a last resort, the values are added to the order notes

 

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

vitahuber
Visitor
3 0 0

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?

TheUntechnickle
Shopify Partner
456 49 114

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:

 

document.addEventListener("DOMContentLoaded", async function () {
    // Get values from multiple sources for redundancy
    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') || "";

    // 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);

    // Always update cart attributes on every page to ensure consistency
    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);
    } catch (error) {
        console.error("
Error updating cart attributes:", error);
    }
});

 

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:

  1. Your cart attributes should pass through to orders most of the time
  2. When they don't, the values will be in your order notes as a backup

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

vitahuber
Visitor
3 0 0

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>