Issue with Shopify Product Discount Function - Only Last Discount Applied

Issue with Shopify Product Discount Function - Only Last Discount Applied

Deepak_23
Shopify Partner
3 0 0

Hi everyone,

I'm building a Shopify Remix app for a volume discount feature and using GraphQL automatic discounts along with the Shopify Product Discount Function. I'm facing an issue where:

  • When I create different discounts for two different products, only the last discounted product in the cart gets the discount applied.
  • If I remove one product from the cart, the remaining product gets the correct discount applied as expected.

It seems like the discount function is not applying multiple discounts properly when different products with their own discounts are in the cart. I have set discountApplicationStrategy: DiscountApplicationStrategy.All, but the issue persists.

Has anyone faced a similar issue? How can I ensure that each eligible product gets its respective discount applied correctly?

Here’s my run.js file for reference:

// @TS-check
import { DiscountApplicationStrategy } from "../generated/api";

/**
* @typedef {import("../generated/api").RunInput} RunInput
* @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
* @typedef {import("../generated/api").Target} Target
* @typedef {import("../generated/api").ProductVariant} ProductVariant
*/

/**
* @type {FunctionRunResult}
*/
const EMPTY_DISCOUNT = {
  discountApplicationStrategy: DiscountApplicationStrategy.First,
  discounts: [],
};

/**
* @param {RunInput} input
* @returns {FunctionRunResult}
*/
export function run(input) {
// Parse configuration from metafield
let configuration;
try {
  configuration = JSON.parse(input?.discountNode?.metafield?.value ?? "{}");
} catch (error) {
  console.error("Error parsing configuration metafield:", error);
  return EMPTY_DISCOUNT;
}

  if (!configuration.discountValues || !Array.isArray(configuration.discountValues)) {
    return EMPTY_DISCOUNT;
  }

  // targets will be only products that are in configuration variants
  const targets = input.cart.lines
    .filter(line => {
      const variant = line.merchandise;
        // Ensure `variants` exists and is an array
    if (!configuration.variants || !Array.isArray(configuration.variants)) {
      console.error("No variants defined in configuration.");
      return false;
    }
      return configuration.variants.some(v => v === variant.id);
    })
    .map(line => {
      const variant = /** @type {ProductVariant} */ (line.merchandise);
      return /** @type {Target} */ ({
        productVariant: {
          id: variant.id
        }
      });
    });
  if (!targets.length) {
    console.error("No cart lines qualify for volume discount.");
    return EMPTY_DISCOUNT;
  }
  const discounts = [];
 
  // Sort discount values by quantity in descending order
  const sortedDiscountValues = configuration.discountValues.sort((a, b) => b.quantity - a.quantity);

  for (const target of targets) {
    const line = input.cart.lines.find(line => line.merchandise?.id === target?.productVariant?.id);
    if (!line) continue;
    const eligibleDiscount = sortedDiscountValues.find(discountValue => line.quantity >= discountValue.quantity);
    for (const discountValue of sortedDiscountValues) {
      if (line.quantity >= discountValue.quantity && eligibleDiscount.quantity > 0) {
        // If line quantity is enough for this discount, create a discount for this line item
        const discount = {
          targets: [target],
          message: eligibleDiscount.discount_message,
          value: eligibleDiscount.discount_type === "Percentage"
          ? { percentage: { value: parseFloat(eligibleDiscount.discount_percent) } }
          : { fixedAmount: { amount: parseFloat(eligibleDiscount.discount_fixed) } }
        };
        discounts.push(discount);
        // Do not break the loop, continue checking the other line items
      }
    }
  }
  return {
    discounts,
    discountApplicationStrategy: DiscountApplicationStrategy.All
  };
};
Replies 3 (3)

Small_Task_Help
Shopify Partner
915 32 85

Hi,

 

Hope this will help

 

Seems like your function is only applying a discount to one product at a time instead of all eligible products.

Try to fix using steps

- Understand the Loop Problem
- Ensure Every Product Gets Its Own Discount
- Modify the code

Example of code

for (const target of targets) {
  const line = input.cart.lines.find(line => line.merchandise?.id === target?.productVariant?.id);
  if (!line) continue;

  const eligibleDiscount = sortedDiscountValues.find(discountValue => line.quantity >= discountValue.quantity);
  
  if (eligibleDiscount) {
    // If line quantity is enough for this discount, create a discount for this line item
    const discount = {
      targets: [target],
      message: eligibleDiscount.discount_message,
      value: eligibleDiscount.discount_type === "Percentage"
        ? { percentage: { value: parseFloat(eligibleDiscount.discount_percent) } }
        : { fixedAmount: { amount: parseFloat(eligibleDiscount.discount_fixed) } }
    };
    discounts.push(discount);
  }
}

 

 

To Get Shopify Experts Help, Click Here or E-mail - hi@ecommercesmalltask.com
About Us - We are Shopify Expert India
At Google My Business - Ecommerce Small Task - Hire Shopify Developers Ahmedabad
Deepak_23
Shopify Partner
3 0 0

Hi  ,

First of all, thanks a lot for your help and for sharing the example code! I really appreciate it.

I tried implementing your example code in my Shopify discount function, but I’m still facing the same issue where the discount is only applied to one product in the cart instead of both eligible products.

I checked my function logs, and here’s what I found:

  • Cart Lines Input: Both product variants are correctly passed in the cart.
  • discountNode Metafield: Only a single variant is passed here instead of both.
  • Discounts Output: The same variant is appearing twice in the discount output instead of applying the discount separately to each eligible variant.

Here’s my function log output for reference:

✔ 2025-03-05T07:34:31.308603Z (success) - d70e8d

Input
{
"cart": {
"lines": [
{
"merchandise": {
"id": "gid://shopify/ProductVariant/41778763169843",
"typename": "ProductVariant"
},
"quantity": 2
},
{
"merchandise": {
"id": "gid://shopify/ProductVariant/41778762842163",
"typename": "ProductVariant"
},
"quantity": 2
}
]
},
"discountNode": {
"metafield": {
"value": "{\"title\":\"Volume Discount product\",\"discountValues\":[{\"discount_type\":\"Percentage\",\"quantity\":\"1\",\"discount_percent\":\"\",\"discount_fixed\":\"\"},{\"discount_type\":\"Percentage\",\"quantity\":\"2\",\"discount_percent\":\"10\",\"discount_fixed\":\"\"}],\"variants\":[\"gid://shopify/ProductVariant/41778763169843\"]}"
}
}
}


Logs

Parsed Configuration: [object Object]
Discounts from function: [
{
"targets": [
{
"productVariant": {
"id": "gid://shopify/ProductVariant/41778763169843"
}
}
],
"message": "XP-VD: Buy 2+, Save 10%\"",
"value": {
"percentage": {
"value": 10
}
}
},
{
"targets": [
{
"productVariant": {
"id": "gid://shopify/ProductVariant/41778763169843"
}
}
],
"message": "XP-VD: Buy 2+, Save 10%\"",
"value": {
"percentage": {
"value": 10
}
}
}
]

 

Output

{
"discountApplicationStrategy": "ALL",
"discounts": [
{
"message": "XP-VD: Buy 2+, Save 10%\"",
"targets": [
{
"productVariant": {
"id": "gid://shopify/ProductVariant/41778763169843"
}
}
],
"value": {
"percentage": {
"value": 10
}
}
},
{
"message": "XP-VD: Buy 2+, Save 10%\"",
"targets": [
{
"productVariant": {
"id": "gid://shopify/ProductVariant/41778763169843"
}
}
],
"value": {
"percentage": {
"value": 10
}
}

It looks like the issue might be related to how the discountNode metafield is handling multiple variants. Do you think I should be structuring the metafield differently, or is there something missing in how I’m applying discounts to multiple products?

Would love to hear your thoughts on this! Thanks again for your help. 😊

Deepak_23
Shopify Partner
3 0 0

Hi ,

First of all, thanks a lot for your help and for sharing the example code! I really appreciate it.

I tried implementing your example code in my Shopify discount function, but I’m still facing the same issue where the discount is only applied to one product in the cart instead of both eligible products.

I checked my function logs, and here’s what I found:

  • Cart Lines Input: Both product variants are correctly passed in the cart.
  • discountNode Metafield: Only a single variant is passed here instead of both.
  • Discounts Output: The same variant is appearing twice in the discount output instead of applying the discount separately to each eligible variant.

Here’s my function log output for reference:

✔  2025-03-05T07:34:31.308603Z (success) - d70e8d

 Input

{
  "cart": {
    "lines": [
      {
        "merchandise": {    
          "id": "gid://shopify/ProductVariant/41778763169843",
          "typename": "ProductVariant"
        },
        "quantity": 2
      },
      {
        "merchandise": {
          "id": "gid://shopify/ProductVariant/41778762842163",
          "typename": "ProductVariant"
        },
        "quantity": 2
      }
    ]
  },
  "discountNode": {
    "metafield": {
      "value": "{\"title\":\"Volume Discount product\",\"discountValues\":[{\"discount_type\":\"Percentage\",\"quantity\":\"1\",\"discount_percent\":\"\",\"discount_fixed\":\"\"},{\"discount_type\":\"Percentage\",\"quantity\":\"2\",\"discount_percent\":\"10\",\"discount_fixed\":\"\"}],\"variants\":[\"gid://shopify/ProductVariant/41778763169843\"]}"
    }
  }
}

Logs

Parsed Configuration: [object Object]
Discounts from function:  [
  {
    "targets": [
      {
        "productVariant": {
          "id": "gid://shopify/ProductVariant/41778763169843"
        }
      }
    ],
    "message": "XP-VD: Buy 2+, Save 10%\"",
    "value": {
      "percentage": {
        "value": 10
      }
    }
  },
  {
    "targets": [
      {
        "productVariant": {
          "id": "gid://shopify/ProductVariant/41778763169843"
        }
      }
    ],
    "message": "XP-VD: Buy 2+, Save 10%\"",
    "value": {
      "percentage": {
        "value": 10
      }
    }
  }
]

Output

{
  "discountApplicationStrategy": "ALL",
  "discounts": [
    {
      "message": "XP-VD: Buy 2+, Save 10%\"",
      "targets": [
        {
          "productVariant": {
            "id": "gid://shopify/ProductVariant/41778763169843"
          }
        }
      ],
      "value": {
        "percentage": {
          "value": 10
        }
      }
    },
    {
      "message": "XP-VD: Buy 2+, Save 10%\"",
      "targets": [
        {
          "productVariant": {
            "id": "gid://shopify/ProductVariant/41778763169843"
          }
        }
      ],
      "value": {
        "percentage": {
          "value": 10
        }
      }

It looks like the issue might be related to how the discountNode metafield is handling multiple variants. Do you think I should be structuring the metafield differently, or is there something missing in how I’m applying discounts to multiple products?

Would love to hear your thoughts on this! Thanks again for your help. 😊