Hey everyone, I’m trying to apply some discount using shopify functions on customers with certain tags. Passing static strings in the graphql query, into the field “hasAnyTags”, seems to work, but using input variables I can’t seem to make it work. Below I have attached some screenshots with the query, metafields and the result I’m getting. Am I missing something?
Found a solution, apparently the metafield type cannot be “json_string”, it has to be “json”. Maybe someone will find this useful
You missing this tags return an array and variable calling code like ${} dollar sign $ and parentheses write inside parentheses your variable name
(tags: [“${customerTag}”])
I had the same problem but in the end I had to drop the idea of adding tags to customer
instead I just made admin settings to select customers and then passed the customer data and and discounted products data into a Shopify discount Note Metafield and then continued the function from there. I would like to know one thing that you used a parameter like in the code below $customerTag. how did you add customer get this on functions and how did you passed the tags ?
query RunInput($customerTag: [String!]) {
cart {
buyerIdentity {
customer {
amountSpent {
amount
}
metafield(namespace: "custom", key: "customerDiscount") {
value
}
hasTags(tags: $customerTag) {
hasTag
tag
}
}
}
}
}
If I understood the question correctly, you are asking how I’m getting the customer tags to search for as a variable in the query?
You can see in the last screenshot that the discount node function has a metafield of type “json” and a value as an object with a key “customerTag”. To use this key in the graphql query, the names of the variable and the name of the metafield’s object key need to match.
So because I have in the metafield a key:
customerTag: ["EXM: Vip"]
and the variable in the graphql is also “customerTag”, the shopify function passes the value in the variable.
Hope this helps.)
No, it doesn’t work like that). The variable is already an array of strings:
$customerTags: [String!]
And you can not pass variables like you showed in graphql.
Yes you are right
Thanks
I am stuck in one more place can you help me with that ? I added the metafield as you said. the query is okay and when I send the data that works fine too
but customer tag is missing from my response
I have added the the tag to customer
I also received a positive response from the admin when I called the setMetafield API
Here’s how I send my data
can you tell me what went wrong here ?
It appears that the value of your customerTag metafield is [“customerTag”], which when passed into hasTags is asking the question, "does this customer have the tag customerTag’? The screenshot shows the only tag on the customer is actually customerDiscount. So the value of your metafield should be [“customerDiscount”].
You can find the docs for input query variables here.
I fixed the confusion of customer tags and customer discounts but the problem remains the same I have updated the code Can you please have a look and tell me what’s going wrong here.
Here is the Query I am using now
and here is the toml file
After updating the toml file I deployed the app and ran npm run dev and made a Discount using my app

The metafield was created no errors came but this time no discount was given
below is a copy of my response
{
"discountNode": {
"metafield": {
"value": "{\"discount_title\":\"CQ Discount \",\"customerObj\":{\"customer_discount_amount\":150,\"customer_amount_type\":\"value\",\"customerDiscountMessage\":\"Customer Gets $150 discount\",\"customerDiscountProducts\":[{\"handle\":\"the-collection-snowboard-hydrogen\",\"id\":\"gid://shopify/Product/6947630973062\",\"optionId\":\"gid://shopify/ProductOption/9030156288134\"},{\"handle\":\"the-collection-snowboard-liquid\",\"id\":\"gid://shopify/Product/6947631300742\",\"optionId\":\"gid://shopify/ProductOption/8965429821574\"},{\"handle\":\"the-collection-snowboard-oxygen\",\"id\":\"gid://shopify/Product/6947631235206\",\"optionId\":\"gid://shopify/ProductOption/8965429723270\"}]},\"productsObj\":{\"product_discount_amount\":10,\"product_amount_type\":\"percentage\",\"productDiscountMessage\":\"pr\",\"discountProducts\":[]}}"
}
},
"cart": {
"buyerIdentity": {
"customer": {
"id": "gid://shopify/Customer/6618661027974",
"email": "hamza.mujahid.hussain@gmail.com",
"hasTags": []
}
},
"lines": [
{
"merchandise": {
"id": "gid://shopify/ProductVariant/40359002505350",
"product": {
"id": "gid://shopify/Product/6947631300742",
"handle": "the-collection-snowboard-liquid"
}
}
},
{
"merchandise": {
"id": "gid://shopify/ProductVariant/40359002275974",
"product": {
"id": "gid://shopify/Product/6947631136902",
"handle": "the-multi-managed-snowboard"
}
}
}
]
}
}
And below is the code that sets my metafield
const addDataToFunction = async (ownerId, metafieldKey, metaFieldNameSpace, metafieldValue, metafieldType) => {
const jsonField = JSON.stringify(metafieldValue)
const response = await admin.graphql(
`#graphql
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields {
key
namespace
value
createdAt
updatedAt
}
userErrors {
field
message
code
}
}
}`,
{
variables: {
metafields: [
{
key: metafieldKey,
namespace: metaFieldNameSpace,
ownerId: ownerId,
type: metafieldType,
value: jsonField
},
]
},
},
);
const data = await response.json();
console.log("---------------------------metaField Responce---------------------------");
console.log("metaField Responce", JSON.stringify(data));
return json({ data });
}
Now can you tell what is going wrong because I’m going in circles here ![]()
Based on your previous post, it looks like you are setting the customerDataTags metafield on the AppInstallation. It needs to be set on the function owner – in this case, the discount.
Also, app-owned metafields should be prefixed $app:, not app:.
You can find the docs for input query variables here.
Based on your reply
I used “gid://shopify/DiscountAutomaticNode/123” to set the Metafield.
Is this the correct Id to set discount metafeild?
I also changed the nameSpace to $app:customerNameSpace in my code and in my toml file
const addDataToFunction = async (ownerId, metafieldKey, metaFieldNameSpace, metafieldValue, metafieldType) => {
const jsonField = JSON.stringify(metafieldValue)
const response = await admin.graphql(
`#graphql
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields {
key
namespace
value
createdAt
updatedAt
}
userErrors {
field
message
code
}
}
}`,
{
variables: {
metafields: [
{
key: metafieldKey,
namespace: metaFieldNameSpace,
ownerId: ownerId,
type: metafieldType,
value: jsonField
},
]
},
},
);
const data = await response.json();
console.log("---------------------------metaField Responce---------------------------");
console.log("metaField Responce", JSON.stringify(data));
return json({ data });
}
addDataToFunction("gid://shopify/DiscountAutomaticNode/123", "customerDataTags", "$app:customerNameSpace", { "customerTag": ["customerDiscount", "customerDiscount2", "customerTag"] }, "json")
But the main output is the same I think the problem is with the Global Id now I am giving it Can you please tell me where am I going to get the gid to set my metafield.
The GID of the discount looks correct. This JavaScript you are using to set the value, is it part of the same app as your function? Otherwise the function wouldn’t be able to see the metafield. I’d recommend using the GraphiQL built into ‘shopify app dev’ in the latest Shopify’s CLI (not the GraphiQL app) to confirm that the metafield was set correctly on the discount.
Are you sure the metafield value is not making it into the function variable now? Are you getting any errors about unset variables? hasTags is still empty in your Function input? You can try temporarily adding the metafield to your input query to debug its value as well.
Finally found the answer I was making a mistake by using mutation MetafieldSet the problem was, I needed to set metafield value to my Shopify Function and I was already sending a metafield value to my function but I also wanted to send another at the same time let me show you what I did because even I could not understand what I did
so this is what happened
const response = await admin.graphql(
`#graphql
mutation discountAutomaticAppCreate($automaticAppDiscount: DiscountAutomaticAppInput!) {
discountAutomaticAppCreate(automaticAppDiscount: $automaticAppDiscount) {
userErrors {
field
message
}
automaticAppDiscount {
discountId
title
startsAt
endsAt
status
appDiscountType {
appKey
functionId
}
}
},
}`,
{
variables: {
automaticAppDiscount: {
title: discount_title,
functionId: process.env.FUNCTIONID,
startsAt: getTodayDateString(),
endsAt: null,
metafields: [
{
namespace: "$app:customerNameSpace",
key: "customerDataTags",
type: "json",
value: customJson,
}
]
}
},
},
);
Now I am simply doing this and now I don’t need the owner ID
const response = await admin.graphql(
`#graphql
mutation discountAutomaticAppCreate($automaticAppDiscount: DiscountAutomaticAppInput!) {
discountAutomaticAppCreate(automaticAppDiscount: $automaticAppDiscount) {
userErrors {
field
message
}
automaticAppDiscount {
discountId
title
startsAt
endsAt
status
appDiscountType {
appKey
functionId
}
}
},
}`,
{
variables: {
automaticAppDiscount: {
title: discount_title,
functionId: process.env.FUNCTIONID,
startsAt: getTodayDateString(),
endsAt: null,
metafields: [
{
namespace: "$app:customerNameSpace",
key: "customerDataTags",
type: "json",
value: customJson,
},
{
namespace: "custom",
key: "discountOBJ",
type: "json",
value: resultJson,
}
]
}
},
},
);
This way I am sending 2 metafields and now everything seems to works fine ![]()
I’m passing:
"type": "json",
"value": JSON.stringify(discountDetails)
But I"m having same error as you. Any idea why this is happening?
Here’s my variable:
const discountDetails = {
selectedCollectionIds: [
'gid://shopify/Collection/310827712556'
],
tags: [
'CL Og test',
'testing3',
'VIP2024234'
]
}
Please check the console before sending data in metafields; sometimes data is not properly converted into strings.
I’m use this way and its working on my side I hope this is for your help.
const [fields, setFields] = useState([{ paymentMethod: '', position: '' }]);
const submitData = () => {
const rulesData = JSON.stringify(fields);
const formData = new FormData();
formData.append('rulesData', rulesData);
};
export const action = async ({ request }) => {
const { admin } = await authenticate.admin(request);
const formData = await request.formData();
const rulesData = formData.get('rulesData');
const paymentCustomizationInput = {
functionId: process.env.SHOPIFY_PAYMENT_METHOD_SORTING_ID,
title: functionTitle,
enabled: checkData,
metafields: [
{
namespace: "$app:order-sorting",
key: "function-configuration",
type: "json",
value: rulesData,
},
],
};
const response = await admin.graphql(
`#graphql
mutation createPaymentCustomization($input: PaymentCustomizationInput!) {
paymentCustomizationCreate(paymentCustomization: $input) {
paymentCustomization {
id
}
userErrors {
message
}
}
}`,
{
variables: {
input: paymentCustomizationInput,
},
}
);
const responseJson = await response.json()
return json({ responseJson });
}












