Discussing Shopify Functions development, deployment, and usage in Shopify apps.
Hi,
I'm currently trying to build a Shopify Discount Function that will target products based off a tag. If I hardcode the tag value into the input query the function works however I would like this to be dynamic, along with the percentage off. I followed along with the using input variable documentation and my input query currently looks like this:
query RunInput ($tags: [String!]) { cart { lines { quantity
merchandise { __typename ...on ProductVariant { id product { hasAnyTag(tags: $tags), } } } } } discountNode { metafield(namespace: "$app:product-discount", key: "function-configuration"){ value } } }
I also have updated my shopify.extension.toml to include the input variable and the function-configuration metafield, however after I use the Shopify GraphQL app to create my discount using the function id and passing through the json data for the metafield, upon running the function the product is not discounted even if it is tagged correctly and the value field in my discountNode show as null. Here is the log for further context:
{ "cart": { "lines": [ { "quantity": 1, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/47070228152616", "product": { "hasAnyTag": false } } } ] }, "discountNode": { "metafield": null } }
Any insight into what the issue with my code may be or what I may be missing would be beyond appreciated.
Thank you!
PS: Here is the run function as well
* @Anonymous {RunInput} input
* @returns {FunctionRunResult}
*/
export function run(input) {
/**
* @type {{
* percentage: number
* }}
*/
const configuration = JSON.parse(
input?.discountNode?.metafield?.value ?? "{}"
);
if(!configuration.percentage){
return EMPTY_DISCOUNT;
}
const targets = input.cart.lines
// Only include cart lines with a quantity of two or more
// and a targetable product variant
.filter(line =>
line.merchandise.__typename == "ProductVariant" && line.merchandise.product.hasAnyTag)
.map(line => {
const variant = /** @type {ProductVariant} */ (line.merchandise);
return /** @type {Target} */ ({
// Use the variant ID to create a discount target
productVariant: {
id: variant.id
}
});
});
if (!targets.length) {
// You can use STDERR for debug logs in your function
console.error("No cart lines qualify for product discount.");
return EMPTY_DISCOUNT;
}
// The @Shopify/shopify_function package applies JSON.stringify() to your function result
// and writes it to STDOUT
return {
discounts: [
{
// Apply the discount to the collected targets
targets,
// Define a percentage-based discount
value: {
percentage: {
value: configuration.percentage.toString()
}
}
}
],
discountApplicationStrategy: DiscountApplicationStrategy.First
};
};
Things to double check:
Nick Wesselman | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Hey Nick thanks for the reply!
Both the namespace and key match what is inside of my toml and I used the extensions.input.variables
In terms of metafield on the discount I assume you mean within the input variable which in my case I had as such
"metafields": [
{
"namespace": "$app:product-discount",
"key": "function-configuration",
"type": "json",
"value": "{\"tags\":[\"testing\",\"testtest\"], \"percentage\": 25.0}"
}
Are you sure you are setting the metafield on the discount you are creating? The one associated with your function id? Your metafield is null on your input json as well, so I suspect you are not properly saving the metafield on the discount. You can query the discounts on your shop w/ GraphiQL to confirm.
Nick Wesselman | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Hey Nick, it appears that does seem to be the issue so my question then becomes do the namespace and key need to be different for each metafield, and could that have something to do with why it's not updating? For example in my extension.toml for my input variable does that metafeild need to differ from the function-configuration metafield I have for changing the percentage within the discountNode, or would it more likely be how I'm triggering my creation mutation within the GraphQL app? Sorry if this is not super clear, but I really appreciate the help and insight so far.
Editing this as I was able to figure a way to change the metafields and update their values, but it only happens if I do an update to the function, if I pass the metafield values through on the create mutation the fields keep setting to null, not sure why it's working on update but not creation?
I'd suggest opening a new discussion in the Metafields and Custom Data board, with the mutation you are executing.
Nick Wesselman | Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit the Shopify Help Center or the Shopify Blog
Were you able to get a solution to this? I'm experiencing the exact same thing as you.