How to Assign "Best Price" Discount to the First-Added Sample in Cart (Shopify Functions Only)

Hi all,

I’m building a Shopify Function to assign the “best price” (first pricing slab) to the first sample variant added to a customer’s cart. Each additional sample gets the next slab price, and so on. I want the oldest sample (the one added first) to always receive the best price—no matter how the cart is reordered or updated later.

The challenge:
Shopify seems to reorder the cart lines (for example, the newest added item often appears first in the cart lines array). This causes the “best price” to move to the newest sample instead of sticking with the original first-added sample. I am not able to set any custom metafields or attributes at add-to-cart time to persist the order of addition.

My question:
Is there any way, using only Shopify Functions and the data available in the cart, to always assign the best price to the first-added (oldest) sample, regardless of how Shopify reorders the cart lines? Or is this impossible without persisting extra state (like a metafield or attribute)?

If anyone has solved a similar problem, I’d really appreciate any advice or workarounds!

Thanks!

My shopify function code

// STEP 1: Import required types from Shopify’s generated API
import {
FunctionResult,
DiscountApplicationStrategy,
} from “../generated/api”;

/**

  • Type definitions (for documentation only)
    */
    ///

// STEP 2: Define a constant to represent an empty discount result
const EMPTY_DISCOUNT: FunctionResult = {
discountApplicationStrategy: DiscountApplicationStrategy.Maximum,
discounts: ,
};

// STEP 3: Utility to safely parse JSON, fallback to default value
function parseJSON(jsonString: string | undefined, defaultValue: any): any {
try {
return JSON.parse(jsonString || “{}”);
} catch {
console.warn(“Invalid JSON”);
return defaultValue;
}
}

// STEP 4: Determine if a line item is a “sample variant”
function isSampleVariant(line: any): boolean {
const parsed = parseJSON(line.merchandise.metafield?.value, {});
return parsed.isSampleVariant === true;
}

// STEP 5: Match the current line item to an applicable discount offer
function findMatchedOffer(line: any, offers: any): any | undefined {
if (!line.merchandise?.product?.pid || !Array.isArray(line.merchandise.product.pid)) {
return undefined;
}

// Check if any product tag matches the offer’s tag
return offers.find((offer) =>
offer.pt.some((offerTag: string) =>
line.merchandise.product.pid.some(
(tagObj: any) => tagObj.hasTag && tagObj.tag === offerTag
)
)
);
}

// STEP 6: Calculate price based on matching slab and total sample count
function calculatePrice(slabs: any, totalSampleCount: number): number {
// Handle edge case when no samples have been added yet
if (totalSampleCount === 0) {
const slab = slabs.find((s) => parseInt(s.q) === 1);
return slab ? parseFloat(slab.v) : 0;
}

// Increment to consider the next sample being added
const qty = totalSampleCount + 1;

// Find the highest matching slab for the current quantity
const matchingSlab = slabs
.slice()
.reverse()
.find((s) => qty >= parseInt(s.q));

return matchingSlab ? parseFloat(matchingSlab.v) : parseFloat(slabs[0]?.v || “0”);
}

// STEP 7: Main function - calculates and returns discounts for sample variants
export function run(input: any): FunctionRunResult {
// Step 7.1: Extract and parse offers from shop metafield
const offers = parseJSON(input.shop.metafield?.value, );

// Step 7.2: Initialize total sample counter and empty discount list
let totalSampleCount = 0;
const discounts: any = ;

// Step 7.3: Iterate over each cart line
input.cart.lines.forEach((line: any) => {
if (!isSampleVariant(line)) return;

const productPrice = parseFloat(line.cost.amountPerQuantity.amount) || 0;
const totalProductPrice = productPrice * 100; // Convert to cents

const matchedOffer = findMatchedOffer(line, offers);
if (!matchedOffer || matchedOffer.ds === "0") return;

const slabs = matchedOffer.r || [];

// Step 7.4: Apply slab discount per unit in quantity
for (let i = 0; i < line.quantity; i++) {
  const price = calculatePrice(slabs, totalSampleCount);
  let masterAmount = price * 100; // Convert to cents
  let finalAmount = (totalProductPrice - masterAmount) / 100; // Back to dollars

  // Step 7.5: Push a fixed amount discount for this variant
  discounts.push({
    targets: [
      {
        productVariant: {
          id: line.merchandise.id,
        },
      },
    ],
    message: matchedOffer.m ? `${matchedOffer.m}` : undefined,
    value: {
      fixedAmount: {
        amount: parseFloat(finalAmount).toFixed(2),
        appliesToEachItem: true,
      },
    },
  });

  // Increment sample count for slab calculation
  totalSampleCount++;
}

});

// Step 7.6: Return all applicable discounts if any, else return empty
if (discounts.length > 0) {
return {
discounts,
discountApplicationStrategy: DiscountApplicationStrategy.All,
};
} else {
return EMPTY_DISCOUNT;
}
}