User to Cart

Shopify Scripts to Functions migration: mapping every script pattern

Shopify Scripts, the Ruby scripts Plus merchants wrote in Script Editor to change line item prices, shipping rates and payment methods, stopped executing on June 30, 2026. Editing and publishing them had already ended on April 15, 2026. That is according to Shopify's developer changelog. The replacement is Shopify Functions. This guide maps each common script pattern to its Function API, shows what the code looks like on the other side, and gives a migration plan, whether you are finishing a migration or recovering from scripts that already stopped.

The three kinds of script, and where they went

Script typeWhat it didReplacement
Line item scriptsChanged line prices, discounts, tiered pricing, BOGO, bundlesDiscount Function (product and order discounts); Cart Transform for bundles
Shipping scriptsHid, renamed, reordered or discounted shipping ratesDelivery Customization Function; Discount Function (shipping discounts)
Payment scriptsHid, renamed or reordered payment gatewaysPayment Customization Function
(not possible with Scripts)Blocking checkout for invalid cartsCart and Checkout Validation Function

Pattern-by-pattern mapping

Common script patternFunction approach
Tiered pricing by quantity (buy 10+, get 10% off)Discount Function, product discount on qualifying lines; or B2B volume pricing for wholesale
Tiered discount by cart subtotalDiscount Function, order discount (see example below)
Buy X get Y / BOGONative BXGY discount if it fits; otherwise Discount Function, product discount on the Y line
Discount for customers with a tag (VIP, wholesale)Discount Function reading buyer identity (customer tags); or B2B catalogs
Bundle pricing (A + B for a set price)Cart Transform to merge lines into a bundle, or Discount Function on the combination
Free gift over a thresholdDiscount Function making the gift line free, with a cart extension or theme adding the gift
Disallow discount codes with certain itemsDiscount Function logic, discount combination settings, and rejecting entered codes where supported
Hide express shipping for certain products or PO boxesDelivery Customization: deliveryOptionHide
Rename or reorder shipping ratesDelivery Customization: rename and move operations
Discount shipping for VIPs or over a thresholdDiscount Function with the shipping (delivery) discount class
Hide a payment gateway for some countries, carts or customersPayment Customization: paymentMethodHide
Rename or reorder payment gatewaysPayment Customization: rename and move operations (wallets can't be renamed)
Different logic per market or currencyRead localization or market data in the Function input

What changed conceptually

Scripts and Functions are both "code that runs in checkout", but the model is different, and that affects how you port logic:

  • Scripts mutated the cart. Functions return operations. A script set line_item.change_line_price. A Function returns "add this discount candidate to these lines", and Shopify applies it. Discounts show up as discounts, with a message, in reports and on the order.
  • Functions are deterministic and data-driven. They get only what their input query asks for and have no network access by default. Rules and lists that were hard-coded in Ruby move into metafields, editable from an app UI.
  • One script per type, many Functions per API. Shopify allows up to 25 active functions per Function API for payment customizations, delivery customizations, validations and fulfillment constraints. Split unrelated rules into separate functions.
  • Discount combinations are explicit. Function discounts follow Shopify's discount combination settings, so decide deliberately which discounts may stack with which.
  • Different plan rules. Scripts were Plus-only. Functions in public apps work on any plan, while Functions in custom apps need Plus.

Before and after: a customer-tag discount

The old line item script (the "before" state, shown for comparison only):

# Script Editor (Ruby), no longer runs
customer = Input.cart.customer
if customer && customer.tags.include?("vip")
  Input.cart.line_items.each do |line_item|
    line_item.change_line_price(line_item.line_price * 0.9, message: "VIP 10% off")
  end
end
Output.cart = Input.cart

The Function equivalent. The input query asks only for what it needs:

query CartInput {
  cart {
    buyerIdentity {
      customer {
        hasAnyTag(tags: ["vip"])
      }
    }
    lines {
      id
    }
  }
  discount {
    discountClasses
  }
}

The run function returns a product discount for every line when the customer has the tag:

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

export function cartLinesDiscountsGenerateRun(input) {
  const isVip = input.cart.buyerIdentity?.customer?.hasAnyTag ?? false;
  if (!isVip || !input.discount.discountClasses.includes(DiscountClass.Product)) {
    return {operations: []};
  }

  return {
    operations: [
      {
        productDiscountsAdd: {
          candidates: [
            {
              message: 'VIP 10% off',
              targets: input.cart.lines.map((line) => ({cartLine: {id: line.id}})),
              value: {percentage: {value: 10}},
            },
          ],
          selectionStrategy: ProductDiscountSelectionStrategy.First,
        },
      },
    ],
  };
}

In production, the tag and percentage would come from a metafield rather than being hard-coded, so the merchant can change them.

Migration plan

  1. Collect every script: its Ruby source, whether it was published, and what it did in plain language. Shopify recommends its Scripts customizations report to see which customizations can move to Functions or public apps.
  2. Check what's happening now. If the scripts have stopped, test real carts: which prices, shipping options and payment methods do customers see today? Rank the gaps by revenue and support impact.
  3. Try native features first: automatic discounts, BXGY, discount combinations, B2B catalogs and volume pricing, shipping profiles.
  4. Try public apps for standard patterns such as tiered discounts, hiding payment methods and bundles.
  5. Build Functions for the rest in one custom app (on Plus), grouped by API, with configuration in metafields and an admin screen to edit it.
  6. Test with fixtures taken from real carts that the scripts used to handle, including edge cases: mixed carts, discount codes, B2B buyers, multiple markets.
  7. Roll out gradually: activate for a customer segment or market first, then everywhere, and compare order values and support tickets with the old behaviour.

Common porting mistakes

  • Porting line by line. A 300-line script usually becomes three small Functions plus some native settings.
  • Hard-coding lists of SKUs, tags and thresholds in Function code. Use metafields.
  • Forgetting discount combinations, so a Function discount stacks with codes it never stacked with before, or doesn't stack when it should.
  • Using a discount where a Cart Transform is right, or the reverse, for bundles.
  • Not testing accelerated checkouts and B2B, which take different paths through checkout.

Frequently asked questions

When were Shopify Scripts deprecated?

According to Shopify's developer changelog, editing and publishing Shopify Scripts stopped on April 15, 2026, and all Shopify Scripts stopped executing on June 30, 2026. Any logic that still lived in Script Editor no longer runs.

What replaces the Shopify Script Editor?

Shopify Functions. Discount Functions replace line item scripts, delivery customization and discount Functions replace shipping scripts, and payment customization Functions replace payment scripts. Cart and checkout validation Functions add something Scripts couldn't do: blocking an invalid checkout.

Are Shopify Plus scripts and Shopify Functions the same thing?

No. Scripts were Ruby code run in Script Editor, available only on Plus, which rewrote the cart as it was. Functions are WebAssembly modules inside apps, usually written in Rust or JavaScript, which receive a defined input and return operations. The logic ports over; the code doesn't.

Do I need a developer to migrate from Scripts to Functions?

Not always. Shopify recommends its Scripts customizations report to see which scripts can be replaced by native features or public apps. For logic that's specific to your store, you need a Function in a custom app, which on Plus is the usual route, and that is development work.

What do I do if my Scripts already stopped working?

Work out what they did from the Ruby source or your records, check what customers are seeing now (prices, shipping options, payment methods), and prioritise by revenue impact. Native discounts or an app can often restore the most important behaviour quickly while custom Functions are built for the rest.

  • Shopify Functions

    What Shopify Functions are and what they can do: discount functions, cart transform, delivery and payment customization, cart and checkout validation. How they're built, plan requirements, limits, and example code.

  • Shopify Plus development

    What Shopify Plus merchants actually need developers for (checkout extensibility, Functions, B2B, Launchpad and Flow automations, expansion stores, ERP integration) and how to choose between an agency and a specialist developer.

  • Shopify B2B

    What Shopify B2B includes on each plan since April 2026, how companies, catalogs, volume pricing, payment terms and purchase orders work, and which B2B requirements need a custom Shopify B2B app or ERP integration.

  • Hire a Shopify app developer

    Freelance Shopify app developer for custom app development, ERP and accounting integrations, Checkout UI extensions and Shopify Functions. How an engagement works and what to prepare.