Hi everyone,
We are currently migrating our Checkout UI Extension and Discount Function away from attributes since applyAttributeChange is being deprecated.
We have successfully updated our UI extension to write values to Cart Metafields instead. However, we are hitting a wall trying to read those same metafields inside our Discount Function (run.graphql).
The attributes still work fine, but the metafields return null or an empty array, even though we have verified they exist on the backend (and eventually persist to the Order via cart_to_order_copyable).
1. Our current cart_lines_discounts_generate_run.graphql (Simplified)
We need to know the exact syntax to access these within the Cart object of a Discount Function.
query CartInput {cart {# This works:leadSourceAttr: attribute(key: “lead_source”) {value}# --- WHAT IS THE CORRECT SYNTAX HERE? ---
# We need to access namespace: "app--123495843--custom"
# We have tried:
# metafield(namespace: "...", key: "...") { value }
# -----------------------------------------}}
2. Evidence of the issue
When we test the cart via the Storefront/Admin API using the $cartId, the attributes return data perfectly, but the metafields return null.
Query:
query getCart($cartId: ID!) {
cart(id: $cartId) {
leadSourceAttr: attribute(key: “lead_source”) {
value
}
metafield(key: “lead_source”, namespace: “$app:custom”) {
id
value
}
metafields(identifiers: {key: “lead_source”, namespace: “$app:custom”}) {
id
value
}
}
}
Response:
{
“data”: {
“cart”: {
“leadSourceAttr”: { “value”: “Replicated Site” },
“metafield”: null,
“metafields”:
}
}
}
What we’ve checked:
-
The metafield namespace is correct (app--289268465665--bydesign).
-
The UI extension is successfully applying the change.
-
We are using a Custom App.
Is there a specific Metafield Visibility or Access Setting required for the Function API to “see” cart-level metafields that were just created in the checkout session? Any help would be appreciated!
Cart attributes themselves aren’t being deprecated! Shopify just renamed the UI extension hook/method from applyAttributeChange to applyCartAttributeChange (to distinguish it from other new hooks they added).
You actually have to keep using attributes for this. The Cart object in the Functions API (run.graphql) doesn’t support reading cart metafields yet—it only supports attribute.
So you can safely revert your function back to reading the attribute, and just update your UI extension code to use applyCartAttributeChange (or useApplyCartAttributeChange if you’re using React). Saves you a massive headache trying to get metafields to work where they aren’t supported yet.
Hi ShopIntegrations,
Thank you for the heads-up! That would explain why I’m hitting a wall with Cannot query field "metafield" on type "Cart" in my run.graphql.
I’m currently developing on the 2026-01 API using Preact, but I’m struggling to find the official documentation or the specific package export for applyCartAttributeChange.
Could you share a link to the documentation or a quick snippet of how you’re importing/calling it? Currently, I’m using shopify.applyMetafieldChange as a workaround, but I’d much rather stick to attributes if they aren’t actually being deprecated.
Appreciate the help!
ShopIntegrations is right that the Cart object in discount function input queries doesn’t expose metafield or metafields. You can only read attribute and lines etc. So cart metafields written during checkout won’t be visible to your discount function regardless of access settings.
For the Preact side, the direct API method is what you already have access to through the shopify global. The rename was from applyAttributeChange to applyCartAttributeChange. In Preact (non-React), you call it directly off the extension API object:
const result = await shopify.applyCartAttributeChange({
type: "updateAttribute",
key: "lead_source",
value: "Replicated Site",
});
That’s the direct API call, no React hook needed. If you were using React you’d use the useApplyCartAttributeChange hook from @shopify/ui-extensions-react/checkout, but since you’re on Preact you just call the method directly on the shopify global.
Then in your discount function’s run.graphql, keep doing exactly what was already working:
query CartInput {
cart {
leadSourceAttr: attribute(key: "lead_source") {
value
}
lines {
id
quantity
merchandise {
__typename
... on ProductVariant {
id
}
}
}
}
}
The attribute(key: "...") field on Cart is fully supported in the function input query. Your run.ts then reads it from input.cart.leadSourceAttr.value as before. No need to touch metafields at all for this use case.
Hi everyone,
Thanks for the quick responses! I’m still a bit stuck—I just ran a console.log(Object.keys(shopify)) in my extension (using api_version = “2026-01”), and applyCartAttributeChange is not listed among the available methods.
I’ve also searched the official Shopify Dev docs for ‘applyCartAttributeChange’ and I’m getting zero hits.
Could this be specific to a specific @shopify/ui-extensions version or a ‘Developer Preview’ flag? Since I’m on Preact and calling the shopify global directly, if it’s not in the Object.keys, I can’t call it.
If anyone has a link to the specific changelog or documentation where this rename was announced for the 2026-01 or unstable versions, that would be a huge help. I’d much rather revert to attributes than fight with metafields if the Function API doesn’t support them on the Cart object yet!