Pulse
7 7IT Solutions
eCommerce

Shopify Functions: Custom Discounts and Cart Logic Without an App

Lior Aharonov Lior Aharonov 6 min read Updated 2026-06-22

Sooner or later every Shopify store wants a promotion the platform does not offer out of the box: buy three get the cheapest free, tiered pricing for wholesale customers, a cart that blocks an invalid combination, an automatic discount that only applies under specific conditions. For years the answer was Shopify Scripts (Plus only) or installing yet another discount app with its own monthly fee. Now there is a better way that most merchants still do not know about: Shopify Functions.

Functions let you run your own logic directly inside Shopify's checkout and cart, custom discounts, delivery and payment customizations, cart validation, written as small pieces of code that Shopify executes natively. No app subscription, no third party in your checkout, and far more flexibility than the discount editor. This guide explains how they work and how to write one. It assumes you are comfortable with the command line and a little JavaScript.

What Shopify Functions actually are

A Function is a small program you write and deploy that Shopify runs at specific moments, when it calculates discounts, when it decides delivery options, when the cart updates. Each Function has two parts: an input, which is a GraphQL query describing exactly the data your logic needs (the cart lines, quantities, customer, attributes), and a run function, which receives that input and returns a set of operations for Shopify to apply. Shopify executes it server-side as part of checkout, so it is fast, secure, and runs for every customer without a third-party service in the path.

Writing a product discount Function

Here is the shape of a discount Function that gives ten percent off any line where the customer is buying three or more of an item. First you declare the input you need.

# input.graphql: ask only for the data the logic uses
query Input {
  cart {
    lines {
      id
      quantity
    }
  }
}

Then the run function receives that data and returns the discount operations.

// run.js: apply 10% off lines with quantity >= 3
export function run(input) {
  const targets = input.cart.lines
    .filter((line) => line.quantity >= 3)
    .map((line) => ({ cartLine: { id: line.id } }));

  if (targets.length === 0) return { discounts: [], discountApplicationStrategy: "FIRST" };

  return {
    discounts: [{ targets, value: { percentage: { value: "10.0" } } }],
    discountApplicationStrategy: "FIRST",
  };
}

That is the whole pattern. Your real logic, wholesale tiers, bundle pricing, conditional promotions, lives in that run function, with the full cart available to reason over.

Deploying with the Shopify CLI

Functions are built and shipped with the Shopify CLI, not pasted into the admin. You scaffold a Function inside a Shopify app, build it, and deploy.

shopify app generate extension --type=product_discount
shopify app deploy

Once deployed, you create a discount in the admin (or via the API) that points at your Function, and from then on Shopify runs your code whenever that discount is active. The Function is versioned with your app, so changes are deliberate and reviewable rather than edits to a live setting.

When a Function beats another app

The instinct is to install a discount or cart app, and for simple needs that is fine. Reach for a Function when the off-the-shelf app cannot express your rule, when you are stacking several apps to approximate one promotion, or when you want the logic to be yours, fast, and free of monthly fees. A single Function often replaces a recurring subscription and does exactly what your business needs instead of eighty percent of it. The cost of stacking apps is real, and Functions are one of the cleanest ways to cut it.

What Functions can and cannot do

Functions are powerful but bounded by design, which is what keeps checkout fast and safe. They run within strict time and size limits, they are pure logic over the input you request rather than a place to call external APIs mid-checkout, and they cover specific extension points: discounts, delivery customizations, payment customizations, and cart and checkout validation. If your need fits one of those, a Function is almost always the right tool. If you need to call out to another system or build a full interface, that is a job for an app or a Checkout UI extension, which pairs naturally with Functions.

A Shopify Functions checklist

  • Identify whether your need is a discount, delivery, payment, or validation rule, those are what Functions cover.
  • Request only the data your logic uses in the input query, to stay fast and within limits.
  • Put your business rule in the run function and return operations, not side effects.
  • Build and deploy with the Shopify CLI, and version the Function with your app.
  • Create the discount or customization in the admin pointing at the Function.
  • Reach for a Function instead of another app when the rule is custom or you want to cut subscriptions.

FAQ

What are Shopify Functions used for?

They let you run custom logic inside Shopify's cart and checkout for things the platform does not do natively: custom and conditional discounts, wholesale and tiered pricing, hiding or reordering delivery and payment options, and validating the cart. You write a small program that Shopify executes server-side, so the logic is fast, secure, and applies to every customer without a third-party app sitting in your checkout.

Do Shopify Functions replace Shopify Scripts?

Yes. Functions are the modern replacement for Scripts, and unlike Scripts they are not limited to Shopify Plus for many use cases and are built and deployed properly through the CLI and an app. If you have existing Scripts, migrating the logic to a Function is the path forward, and it gives you versioning, broader availability, and a wider set of extension points than Scripts offered.

Can a Function replace a paid discount app?

Often, yes. If a discount or cart app exists mainly to apply a pricing rule you could express in code, a single Function can do the same thing natively, without the monthly fee or a third party in your checkout. The cases where you still want an app are when you need an interface, external API calls, or features beyond the Function extension points. For pure pricing and cart logic, a Function is usually cheaper and more precise.

Do I need Shopify Plus to use Functions?

Many Function types, including product discounts, are available beyond Plus, which is a key difference from the old Scripts that were Plus-only. Some advanced checkout customizations are still tied to Plus, so the exact availability depends on the Function type, but a great deal of custom discount and cart logic is now open to regular Shopify plans. Check the specific extension point, but do not assume you need Plus.

Can a Function call an external API during checkout?

No, and that is intentional. Functions are pure logic over the input you request, run under tight time and size limits to keep checkout fast and reliable, so they cannot make external network calls mid-checkout. If your logic needs data from another system, fetch and store it ahead of time (for example on cart attributes or metafields) so the Function can read it from its input, or use an app for the parts that genuinely need to call out.

If you want a promotion or cart rule Shopify will not do on its own, tell me what you are trying to offer and I will map out the Function that does it without another app.

Want a hand applying this?

Tell me where your business is stuck and I will give you a straight, useful read, no pitch.

Go deeper

Shopify

Shopify B2B and Wholesale: Why the Apps Still Fall Short (and What to Build Instead)

Customer-specific pricing, net terms, quote-to-order, and approval flows are where most Shopify B2B setups quietly break down. Here is why the apps struggle with real wholesale, what a custom B2B layer looks like, and how we build it so it earns trust at every step.

Read →
Shopify

Subscriptions Your Way: When Off-the-Shelf Shopify Billing Doesn't Fit

Subscription apps are powerful, but their revenue-share fees and rigid logic stop short of build-a-box, prepaid plus metered, and custom dunning. Here is when it pays to own your subscription logic on Shopify, and how we build it without risking your recurring revenue.

Read →
Shopify

The Hidden Cost of Shopify App Stacking: When 15 Apps Should Become One You Own

Every Shopify gap gets patched with another app, until the monthly bill, the slowdown, and the conflicts become a problem of their own. Here is how to tell when a stack of apps should become one custom app you own, and how we build it without putting the store at risk.

Read →
Shopify

Made-to-Order on Shopify: Building a Product Configurator the Apps Can't Handle

Custom dimensions, conditional options, live pricing, and a clean handoff to production are where Shopify's variants and configurator apps run out of road. Here is what a real made-to-order configurator looks like, and how we build it in phases you can trust.

Read →
Shopify

Advanced Shipping and Fulfillment Logic Shopify Rules Can't Express

SKU and weight tiers, freight and LTL, hazmat, multi-origin routing, and delivery scheduling are where Shopify's native shipping rules and most apps run out. Here is what custom shipping logic on the Carrier Service API looks like, and how we build it without breaking checkout.

Read →
eCommerce

When You Need a Custom WooCommerce Plugin (and When You Don't)

How to tell whether your WooCommerce store needs a custom plugin or whether an existing one will do, and how custom code can cut plugin bloat.

Read →