How can I dynamically query discountNode metafield in my app?

Topic summary

A developer is building a Remix-based Shopify discount app and needs help dynamically querying discountNode metafields.

Current Issue:

  • The app successfully navigates to specific discount pages from a DataTable
  • The GraphQL query uses a hardcoded discount ID (gid://shopify/DiscountAutomaticNode/1095825490072)
  • Need to make the query work dynamically for any discount

What’s Working:

  • Discount creation with metafields (namespace: “volume-discount”, key: “function-configuration”)
  • Query structure for retrieving discount details and metafields
  • Support for multiple discount types (CodeBasic, CodeBxgy, AutomaticApp, etc.)

Solution Provided:
Another user (Hirano_00) offered sample code showing how to:

  • Extract the discount ID from route parameters (params.id)
  • Pass it dynamically to a getDiscount function
  • Structure the loader properly in app/routes/app.discount.$functionId.$id.tsx

The discussion remains open for clarification on the provided solution.

Summarized with AI on November 12. AI used: claude-sonnet-4-5-20250929.

Hi Guys I am doing an app with remix for discounts, all is going good and I am coding a DataTable where the merchant can edit the discount, when the discount is clicked it takes the merchant to the specific page successfully, but I dont know how to query the metafields for that specific discount dynamically so it works everywhere.

Here is what i have so far in my query:

export async function loader({ request }) {
const { admin } = await shopify.authenticate.admin(request);
const discountCodeId = gid://shopify/DiscountAutomaticNode/1095825490072;
const response = await admin.graphql({ discountNode(id: "${discountCodeId}") { id metafield(namespace: "volume-discount", key:"function-configuration"){ value } discount { ... on DiscountCodeBasic { title } ... on DiscountCodeBxgy { title } ... on DiscountCodeFreeShipping { title } ... on DiscountAutomaticApp { title } ... on DiscountAutomaticBasic { title } ... on DiscountAutomaticBxgy { title } ... on DiscountAutomaticFreeShipping { title } } } });

const parsedResponse = await response.json();

return json({
discount: parsedResponse.data,
});
}

and this is how I create the it:

export const action = async ({ params, request }) => {
const { functionId } = params;
const { admin } = await shopify.authenticate.admin(request);
const formData = await request?.formData();
const {
title,
method,
code,
combinesWith,
usageLimit,
appliesOncePerCustomer,
startsAt,
endsAt,
configuration,
} = JSON.parse(formData.get(“discount”));

const baseDiscount = {
functionId,
title,
combinesWith,
startsAt: new Date(startsAt),
endsAt: endsAt && new Date(endsAt),
};

if (method === DiscountMethod.Code) {
const baseCodeDiscount = {
…baseDiscount,
title: code,
code,
usageLimit,
appliesOncePerCustomer,
};

const response = await admin.graphql(
#graphql mutation CreateCodeDiscount($discount: DiscountCodeAppInput!) { discountCreate: discountCodeAppCreate(codeAppDiscount: $discount) { userErrors { code message field } } },
{
variables: {
discount: {
…baseCodeDiscount,
metafields: [
{
namespace: “$app:volume-discount”,
key: “function-configuration”,
type: “json”,
value: JSON.stringify({
quantity: configuration.quantity,
percentage: configuration.percentage,
bundles: configuration.bundles
}),
},
],
},
},
}
);

const responseJson = await response.json();
const errors = responseJson.data.discountCreate?.userErrors;
return json({ errors });
} else {
const response = await admin.graphql(
#graphql mutation CreateAutomaticDiscount($discount: DiscountAutomaticAppInput!) { discountCreate: discountAutomaticAppCreate(automaticAppDiscount: $discount) { userErrors { code message field } } },
{
variables: {
discount: {
…baseDiscount,
metafields: [
{
namespace: “$app:volume-discount”,
key: “function-configuration”,
type: “json”,
value: JSON.stringify({
quantity: configuration.quantity,
percentage: configuration.percentage,
bundles: configuration.bundles
}),
},
],
},
},
}
);

const responseJson = await response.json();
const errors = responseJson.data.discountCreate?.userErrors;
return json({ errors });
}
};

Hi @jacobovelasquez_1 ,

I have created a sample code.

If there is anything here that’s unclear please do let me know!

app/routes/app.discount.$functionId.$id.tsx

export const loader = async ({ params, request }: LoaderFunctionArgs) => {
  const { admin } = await shopify.authenticate.admin(request);
  const { id } = params;
  const discountNode = await getDiscount(admin, id!);
  return json({ discountNode });
};

const getDiscount = async (
  admin: AdminApiContext