For discussing the development and usage of Checkout UI extensions, post-purchase extensions, web pixels, Customer Accounts UI extensions, and POS UI extensions
I'm currently facing an issue while trying to utilize input query variables within the index.js file in my Shopify function. Despite reviewing the documentation https://shopify.dev/docs/apps/functions/input-output/variables-queries, I've been unable to find a solution.
Basically, I want to apply a discount on the products that belong to the collection I am passing.
Here's the input.graphql file
query GetCartContents($selectedCollectionIds: [ID!]) {
cart {
lines {
quantity
merchandise {
__typename
... on ProductVariant {
id
product {
id
inAnyCollection(ids: $selectedCollectionIds)
}
}
}
}
}
discountNode {
metafield(namespace: "product-discount", key: "function-config") {
value
}
}
}
and here's my product-discount index.js file
(input) => {
const configuration = JSON.parse(
input?.discountNode?.metafield?.value ?? "[]"
);
const discounts = [];
const selectedCollectionIds = {
selectedCollectionIds: ["gid://shopify/Collection/451434709290"],
};
for (const line of input.cart.lines) {
if (
line.merchandise &&
line.merchandise.id &&
line.merchandise.product
) {
const product = line.merchandise.product;
// Issue: How to pass the selectedCollectionIds to inAnyCollection?
const isInSelectedCollection = product.inAnyCollection;
console.log(isInSelectedCollection, "isInSelectedCollection");
}
}
if (!discounts.length) {
return EMPTY_DISCOUNT;
}
return {
discounts,
discountApplicationStrategy: DiscountApplicationStrategy.Maximum,
};
};
My main challenge is understanding how to pass the values from selectedCollectionIds to the inAnyCollection function.
If anyone within the Shopify community has experience with this or can provide insights into how to properly utilize input query variables within the index.js file, I would greatly appreciate your guidance. Any tips, code snippets, or explanations would be incredibly helpful in resolving this issue.
Thank you all in advance for your assistance and support.
Solved! Go to the solution
This is an accepted solution.
I was also confused about this and just figured it out.
When building the discount form, the discount object metafield value needs to have a property called "selectedCollectionIds" that stores the selected ids. For example:
const discount = {
functionId,
combinesWith: form.combinesWith,
startsAt: form.startDate,
endsAt: form.endDate,
metafields: [
{
namespace: metafields.config.namespace,
key: metafields.config.key,
type: "json",
value: JSON.stringify({
quantity: parseInt(form.config.quantity),
percentage: parseFloat(form.config.percentage),
selectedCollectionIds: form.config.selectedCollectionIds || []
})
}
]
};
Next, in the shopify.function.extension.toml file add the metafield namespace and key for your app as an input variable. For example:
[input.variables]
namespace = "$app:product-discount"
key = "function-config"
Then the "$selectedCollectionIds" variable in the graphql file will pull from the selectedCollectionIds property in the discount metafield value.
Hi Yedla_dinesh,
Based on the provided code snippets, it looks like you're trying to use the selectedCollectionIds
variable inside the JavaScript function but this variable is defined in the GraphQL query context.
The inAnyCollection
field in the GraphQL API is expecting an array of IDs passed as a variable (selectedCollectionIds
in your case). But in your JavaScript function, it's being used as a property of product
object and not as a function that you can pass arguments to.
To solve this issue, you should first ensure that your GraphQL query is correctly passing the selectedCollectionIds
variable to the inAnyCollection
field.
So, the query should look something like this:
query GetCartContents($selectedCollectionIds: [ID!]!) {
cart {
lines {
quantity
merchandise {
__typename
... on ProductVariant {
id
product {
id
inAnyCollection(ids: $selectedCollectionIds)
}
}
}
}
}
discountNode {
metafield(namespace: "product-discount", key: "function-config") {
value
}
}
}
In your JavaScript function, the inAnyCollection
field will be a boolean property of the product
object (true if the product is in any of the selected collections, and false otherwise). You can then use this property to apply discounts to the appropriate products:
(input) => {
const configuration = JSON.parse(
input?.discountNode?.metafield?.value ?? "[]"
);
const discounts = [];
for (const line of input.cart.lines) {
if (
line.merchandise &&
line.merchandise.id &&
line.merchandise.product &&
line.merchandise.product.inAnyCollection // Use inAnyCollection field as a boolean property
) {
// Apply discount
// ...
}
}
if (!discounts.length) {
return EMPTY_DISCOUNT;
}
return {
discounts,
discountApplicationStrategy: DiscountApplicationStrategy.Maximum,
};
};
Please note, the selectedCollectionIds
variable should be passed to the GraphQL API when you're making the API call, not inside the JavaScript function.
Hope this helps,
Liam | Developer Advocate @ 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 Shopify.dev or the Shopify Web Design and Development Blog
Thanks for your reply, @Liam . I have tried to pass selectedCollectionIds as an array, but it's still not working.
Let's say I have an output like the following in metadata:
selectedCollectionIds: ["gid://shopify/Collection/123", "gid://shopify/Collection/321", "gid://shopify/Collection/987"]
Could you guide me on how to utilize this metadata in the inAnyCollection function to receive a true or false value in return?
This is an accepted solution.
I was also confused about this and just figured it out.
When building the discount form, the discount object metafield value needs to have a property called "selectedCollectionIds" that stores the selected ids. For example:
const discount = {
functionId,
combinesWith: form.combinesWith,
startsAt: form.startDate,
endsAt: form.endDate,
metafields: [
{
namespace: metafields.config.namespace,
key: metafields.config.key,
type: "json",
value: JSON.stringify({
quantity: parseInt(form.config.quantity),
percentage: parseFloat(form.config.percentage),
selectedCollectionIds: form.config.selectedCollectionIds || []
})
}
]
};
Next, in the shopify.function.extension.toml file add the metafield namespace and key for your app as an input variable. For example:
[input.variables]
namespace = "$app:product-discount"
key = "function-config"
Then the "$selectedCollectionIds" variable in the graphql file will pull from the selectedCollectionIds property in the discount metafield value.