I am trying to query some custom data from the properties attribute from cart lines but failing.
Neither of the following works. Any suggestions? Is it possible?
query RunInput {
cart {
lines {
id
quantity
attribute(key: "properties") {
value
}
}
}
}
query RunInput {
cart {
lines {
id
quantity
attribute(key: "properties") {
custom_data: value
}
}
}
You canāt use all properties. Instead, you should use the āpropertiesā key. For example:
attribute(key: ādiscountā) {
key
value
}
Thanks, but Iām not trying to get all the properties. Iām trying to get the attribute āpropertiesā, the key is āpropertiesā. Custom data is added to that when the product is added to cart.
From the cart.json:
Are you sure itās dependent on the Cart Line properties field? If it is associated with the cart, you should do it like this.
query RunInput {
cart {
attribute(key: "properties") {
value
}
lines {
id
quantity
}
}
}
I managed to figure it out. Data added to the properties attribute are considered to be custom properties, so one just has to target the key of that custom property.
query RunInput {
cart {
lines {
id
quantity
custom_data: attribute(key: "_custom_data") {
value
}
}
}
2 Likes
FYI, Thereās a better way to do this using Inline Fragments:
query RunInput {
cart {
lines {
id
quantity
attributes {
... on Attribute {
key
value
}
}
}
}
}
That will give you an array of all the attributes:
"attributes": [
{
"key": "test1",
"value": "true"
},
{
"key": "test2",
"value": "false"
}
]
This does not work with Shopifyās cart function input where Iāve tried.
attributes
doesnāt exist in the schema. I am only able to grab them individually based on keys, not a list.
What API version are you using? Itās definitely supported in latest.
Hi @rogueyoshi . This is a screenshot of the Storefront API. Functions APIs have their own GraphQL schemas. Generally, functions cannot query unbounded lists, for performance reasons. Thus you need to specify the specific attribute.
https://shopify.dev/docs/api/functions/reference/product-discounts/graphql/common-objects/cartline
3 Likes
Thanks for the clarification @Nick_Wesselman !
If this is the case, is there no way to preserve all of the properties from an expanded product?
I understand I can take the specific values by using the key for each attribute I want, but I have forms with a bunch of inputs/selects that add specific custom properties and the property names arenāt all the same every time.
All I want is all the attributes/properties from the expanded product to be kept through to the order notes when I run a cart expand on it, but as soon as I look at the order details all of the original properties on item that I expanded are gone and it breaks the functionality that I need.
It even shows them in the checkout screen on the parent of the expanded items but it doesnāt carry through to the order notes where we need them in order to see all the options chosen.
I recently had the same issue. What I ended up doing was adding attributes to ExpandedItems in the cart transform code. ExpandedItem attributes are available in api version 2024-04 and up.
1 Like
Yeah thatās what Iām afraid of, the integration Iām building is for a huge variety of different options and properties that will be possible to have on a product.
Thereās no way for me to predict or know exactly what each of the properties keys will be as they will be different on all the products. I think that approach only works if you have the same properties/property names every single time on the products you are expanding.
Gotcha. My issue was somewhat similar. I took all the key/value pairs and put them in a nested array and then stringified that nested array and use it as a value in a hidden custom cart attribute. That way I could query the custom attribute and then parse it in my cart transform extension code.
2 Likes
Thatās smart, I will see if I can make something like that route work, basically add all the properties to one hidden property that stays the same and build them on the expanded items off of that. Thank you!
Would be a really nice feature if you could just preserve them from the base product.
Hi @aashby13 first of all! thank you so so so much! I was so stuck.
I was able to get my properties with the custom-data, but now Iām not sure how to set this in the function:
export function run(input) {
const targets = input.cart.lines
// Only include cart lines with a quantity of two or more
.filter(line => line.custom_data && line.custom_data?.value)
.map(line => {
return /** @type {Target} */ ({
// Use the cart line ID to create a discount target
cartLine: {
id: line.id
}
});
});