Shopify Tiered Discounts in 2026: Buy More, Save More with Functions

By Eoin Villarin, 2026-11-15

How to create tiered quantity discounts on Shopify after Scripts were retired: built-in options, discount apps and a working JavaScript Discount Function with metafield tiers.

How do I create tiered discounts on Shopify?

Create tiered quantity discounts on Shopify with a Shopify Function built on the Discount Function API, or with a Functions-powered discount app from the Shopify App Store. The Function counts cart quantity, picks the matching tier and returns a productDiscountsAdd operation. Public apps work on any plan; custom apps with Functions need Shopify Plus.

Key takeaways

  • Shopify Scripts stopped running on June 30, 2026, so tiered discounts now need Shopify Functions.
  • Product and order discounts use the cart.lines.discounts.generate.run target.
  • Store the tiers as JSON in the $app function-configuration metafield so they change without a deploy.
  • Public discount apps work on any plan; custom apps with Functions require Shopify Plus.
  • Show the tier table on the product page so customers see the saving before the cart.

To create tiered quantity discounts on Shopify in 2026 (for example buy 3 save 10%, buy 5 save 15%, buy 10 save 20%), use a Shopify Function built on the Discount Function API, or a Functions-powered discount app from the Shopify App Store. Shopify Scripts used to do this on Shopify Plus, but they stopped running on June 30, 2026. Below is the no-code route, the limits of Shopify's built-in automatic discounts, and a working JavaScript Function you can adapt, with tiers stored in a metafield so marketing can change them without a deploy.

Three ways to do tiered discounts on Shopify

MethodPlanEffortLimits
Built-in automatic discounts (one per tier)AnyMinutesEach discount has one minimum; several tiers depend on discount combination settings and can stack or conflict
Functions-powered discount appAnyAn hourMonthly app fee, rules limited to the app's settings
Custom app with a Discount FunctionShopify Plus for custom apps1 to 5 daysDevelopment and maintenance; full control

For one or two simple tiers, try the built-in automatic discounts first. For several tiers, customer-tag rules, collection rules or anything your store relied on Scripts for, use a Function.

Reusable shopping tote bag printed with Rotterdam 010 on a shop display
Volume tiers lift average order value on products people buy in multiples. Photo: Donald Trung Quoc Don, CC BY-SA 4.0, via Wikimedia Commons

How the Discount Function API works

  • A Function is a small WebAssembly module that Shopify runs during cart and checkout. You can write it in JavaScript or Rust; Shopify recommends Rust for large carts.
  • Product and order discounts use the target cart.lines.discounts.generate.run. Shipping discounts use cart.delivery-options.discounts.generate.run.
  • The Function returns operations such as productDiscountsAdd, orderDiscountsAdd or deliveryDiscountsAdd.
  • The discount's classes (PRODUCT, ORDER, SHIPPING) arrive in the input, so one Function can check what it is allowed to apply.
  • Settings live in a metafield on the discount (namespace $app, key function-configuration), read as JSON.

Step 1: Generate the Function

shopify app init
cd your-app
shopify app generate extension --template discount --name tiered-discount

Choose JavaScript when the CLI asks for a language. The generator creates the extension folder with a TOML config, an input query and a run function.

Step 2: The input query

query CartInput {
  cart {
    lines {
      id
      quantity
    }
  }
  discount {
    discountClasses
    metafield(namespace: "$app", key: "function-configuration") {
      jsonValue
    }
  }
}

Step 3: The run function

import { DiscountClass, ProductDiscountSelectionStrategy } from '../generated/api';

const DEFAULT_TIERS = [
  { min: 3, percent: 10 },
  { min: 5, percent: 15 },
  { min: 10, percent: 20 },
];

export function cartLinesDiscountsGenerateRun(input) {
  if (!input.cart.lines.length) {
    return { operations: [] };
  }
  if (!input.discount.discountClasses.includes(DiscountClass.Product)) {
    return { operations: [] };
  }
  const config = input.discount.metafield?.jsonValue;
  const tiers = Array.isArray(config?.tiers) && config.tiers.length ? config.tiers : DEFAULT_TIERS;
  const totalQuantity = input.cart.lines.reduce((sum, line) => sum + line.quantity, 0);
  const tier = [...tiers].sort((a, b) => b.min - a.min).find((t) => totalQuantity >= t.min);
  if (!tier) {
    return { operations: [] };
  }
  return {
    operations: [
      {
        productDiscountsAdd: {
          selectionStrategy: ProductDiscountSelectionStrategy.First,
          candidates: [
            {
              message: `${tier.percent}% off ${tier.min}+ items`,
              targets: input.cart.lines.map((line) => ({ cartLine: { id: line.id } })),
              value: { percentage: { value: String(tier.percent) } },
            },
          ],
        },
      },
    ],
  };
}

Notes: percentage values are Decimals and must be sent as strings. To limit the discount to one collection, add merchandise with inAnyCollection to the input query and filter the lines before counting.

Step 4: Deploy and create the discount

  1. Run shopify app dev to test on a development store, then shopify app deploy.
  2. Create an automatic app discount that uses your Function (for example with the discountAutomaticAppCreate Admin API mutation), set its discount class to product, and save the tiers JSON in the $app / function-configuration metafield:
{"tiers":[{"min":3,"percent":10},{"min":5,"percent":15},{"min":10,"percent":20}]}
  1. Set the discount's combination rules (with product, order and shipping discounts) to match your promo policy.
  2. Test carts with 2, 3, 5 and 10 items, mixed products, a discount code on top, and different markets.

Show the tiers on the product page

Customers only buy more if they can see the deal. Add a small tier table under the price ("3+ save 10%, 5+ save 15%, 10+ save 20%") using a theme app block or a metafield in your theme, and show the saving in the cart. Keep the table text the same as the Function's tiers so the cart never disagrees with the product page.

Shopify sign on an office building directory board
Discount Functions run inside Shopify's checkout, so they work with Checkout Extensibility and Shop Pay. Photo: Raysonho @ Open Grid Scheduler / Grid Engine, CC0, via Wikimedia Commons

Common problems

  • Discount does not apply: the discount is not active, its class does not include product, or the Function returned no operations (check the Function run logs in the Partner Dashboard or in shopify app dev).
  • Stacking with codes: discount combination settings decide whether a code applies on top. Set them deliberately.
  • Wrong tier: make sure you count quantity across the right lines (all lines, one collection, or one product).
  • Large carts: very large carts can hit Function limits in JavaScript; Rust is faster if you see failures.

Need it built?

I build Shopify Functions, discount apps and Checkout UI extensions for Shopify and Shopify Plus stores. If your tiered pricing stopped working when Scripts were retired, read Shopify Scripts stopped working: how to fix it or see my Shopify development services.

Frequently asked questions

Can Shopify do tiered discounts without an app?

Partly. You can create one automatic discount per tier with a minimum quantity, but several tiers rely on discount combination settings and can behave unpredictably. A Function or Functions-powered app gives reliable tiers.

Do I need Shopify Plus for tiered discounts?

No. Public discount apps that use Shopify Functions work on any plan. Only a custom app with your own Function requires Shopify Plus.

What replaced Shopify Scripts for tiered pricing?

The Discount Function API. Product and order discounts use the cart.lines.discounts.generate.run target and return productDiscountsAdd or orderDiscountsAdd operations.

Can I change discount tiers without redeploying?

Yes. Store the tiers as JSON in the discount's function-configuration metafield and read it in the Function input.

Can tiered discounts apply to one collection only?

Yes. Query each line's merchandise with inAnyCollection and only count and discount the lines in that collection.

Should I write Shopify Functions in JavaScript or Rust?

JavaScript is quicker to write and fine for most stores. Shopify recommends Rust for performance, especially with large carts.

Sources

Related reading