Shopify Functions Tutorial (Your First Discount in 30 Minutes)
Scripts is dead. Functions is what every Plus merchant now uses for cart, discount, shipping, and payment logic. The first time a developer opens the Functions tooling, the learning curve looks steep. It is not. In 30 minutes you can ship a working product discount Function to a development store and see the discount apply at checkout. This is the exact tutorial we run with new hires on our team. No prior Shopify Functions experience required.
What you will build
A Product Discount Function that applies a 10% discount to any cart line item where the product title contains the word "sale". The discount applies automatically when the item enters the cart. The customer sees the discount at checkout. The merchant configures the activation through the Shopify admin.
By the end of this tutorial you will understand the Function input, the Function output, the deployment process, and the merchant configuration. Every other Function you build follows this same pattern.
Prerequisites before you start
Three things you need ready before the timer starts.
1. Shopify CLI installed. Run shopify version in your terminal. If it does not return a version number, install it with npm install -g @shopify/cli @shopify/theme. The CLI is how you scaffold, build, and deploy Functions.
2. A Shopify Partner account. Sign up at partners.shopify.com if you do not have one. Partner accounts give you free development stores for testing Functions before pushing to a live merchant.
3. Rust toolchain or JavaScript familiarity. Functions compile to WebAssembly. The two officially supported languages are Rust and JavaScript. Rust produces smaller and faster Functions but JavaScript is easier if your team is web-native. This tutorial uses JavaScript because the install footprint is smaller.
Step 1 - Scaffold the Function app (5 minutes)
Create a new Shopify app that will house your Function. Run this in your terminal:
shopify app init
The CLI will ask you to log in to your Partner account, then prompt for the app name. Pick something like my-first-function. The CLI scaffolds a Shopify app with the basic structure ready for Function development.
Once the app is scaffolded, navigate into the app folder and add a Function extension:
cd my-first-functionshopify app generate extension
From the list of extension types, pick Product discount. Pick JavaScript as the language. Give the extension a name like sale-product-discount.
The CLI creates a new folder under extensions/sale-product-discount with the boilerplate code already in place.
Step 2 - Understand the Function structure
Open the extension folder. The files that matter:
- src/run.js - the main Function code. This is where the discount logic lives.
- src/run.graphql - the GraphQL query that defines what cart data the Function receives as input.
- shopify.extension.toml - the manifest that tells Shopify what kind of Function this is.
- schema.graphql - the schema definition for the Function input and output.
The mental model is simple. Shopify calls your Function with cart data as input. Your Function returns a list of discount operations as output. Shopify applies the operations to the cart.
Step 3 - Write the discount logic (10 minutes)
Open src/run.graphql. This query defines what cart data your Function will receive. Update it to fetch line items and product titles:
query RunInput { cart { lines { id quantity merchandise { __typename ... on ProductVariant { product { title } } } } } }
Now open src/run.js. This is where the discount logic runs. Replace the boilerplate with this code:
export function run(input) {
const targets = [];
for (const line of input.cart.lines) {
if (line.merchandise.__typename !== "ProductVariant") continue;
const title = line.merchandise.product.title.toLowerCase();
if (title.includes("sale")) {
targets.push({ cartLine: { id: line.id } });
}
}
if (targets.length === 0) return { discounts: [] };
return { discounts: [{ targets, value: { percentage: { value: 10 } } }] };
}
The Function receives the cart input, loops through line items, checks each product title, and adds matching items to a target list. If any items match, it returns a 10% discount applied to those targets.
Build the Function to confirm it compiles:
shopify app build
If the build succeeds, you have a working Function compiled to WebAssembly.
Step 4 - Deploy the Function (5 minutes)
Deploy the app to your Partner account:
shopify app deploy
The CLI walks you through the deployment. It will create an app version, upload the Function, and confirm the deployment.
Once the deployment succeeds, your Function is live in the Partner dashboard and ready to install on a store.
Step 5 - Install on a development store
From the Partner dashboard, open your app and click Select store. Pick or create a development store. The install flow uses the standard Shopify app installation pattern. Approve the requested scopes.
Once installed, the Function is registered with the store but not yet active. You need to activate it through the discount creation flow.
Step 6 - Activate the discount in the Shopify admin (5 minutes)
Open the development store admin. Go to Discounts in the left navigation. Click Create discount.
You will see your Function listed under the discount types. The label is the name you gave the Function in shopify.extension.toml. Pick it.
Give the discount a code (or set it to automatic), set the active dates, and save. The Function is now active.
Step 7 - Test the discount at checkout
From the development store admin, create a test product with the word "sale" in the title. Add it to a cart and go to checkout. The discount should appear automatically with a 10% line item discount.
Add another product without "sale" in the title. That product should not be discounted. The Function correctly identifies and discounts only matching products.
What to do next
You just shipped a working Shopify Function. The pattern you learned generalizes to every other Function type:
- Order Discount Function: the same structure but the discount applies to the order, not specific line items.
- Shipping Discount Function: targets shipping rates instead of products.
- Delivery Customization Function: hides, renames, or re-sorts shipping methods based on cart state.
- Payment Customization Function: hides, renames, or re-sorts payment methods.
- Cart Transform Function: bundles, splits, or modifies line items before checkout.
The mental model never changes. Cart input goes in. Operations come out. Shopify applies the operations. For the full picture of how Functions fit alongside Checkout UI Extensions, Checkout Components, and Shop Pay, read our checkout extensibility stack guide.
What is a Shopify Function and how does it work?
A Shopify Function is a small WebAssembly module that runs on Shopify's servers during checkout and order processing. The Function receives a structured input from Shopify (typically cart data, customer data, or order data), executes its logic, and returns a structured output that Shopify uses to modify the checkout experience. Functions are deployed as part of a Shopify app and configured by merchants through the standard Shopify admin. They run synchronously during the checkout flow, scale with Shopify infrastructure, and replaced Shopify Scripts as the official way to customize checkout business logic in 2026.
How long does it take to learn Shopify Functions for a new developer?
A developer comfortable with JavaScript or Rust can ship a basic Function in under an hour by following the standard tutorial. Reaching production-grade competency where the developer can debug edge cases, write efficient code, and integrate with the broader Shopify app ecosystem typically takes 2 to 4 weeks of focused work. The Shopify CLI handles most of the scaffolding and deployment work, so the learning curve is shorter than typical platform extensibility frameworks. The hardest part for most developers is internalizing the input and output schemas, which differ by Function type.
Can I write Shopify Functions in JavaScript or do I need Rust?
Both languages are officially supported. JavaScript Functions are easier to write if your team is web-native and the install footprint is smaller. Rust Functions produce smaller WebAssembly binaries and run faster, which matters at high cart volumes or when Function execution time is a concern. For most merchants the performance difference is negligible. For Plus merchants running 10+ Functions on high-volume checkouts during BFCM, Rust is the safer choice. Start with JavaScript while learning and migrate hot Functions to Rust later if performance becomes an issue.
How do I debug a Shopify Function when something goes wrong?
The Shopify CLI ships with a Function preview command that lets you test Functions locally with synthetic inputs before deployment. After deployment, Shopify provides a Function execution log in the Partner dashboard showing the input, output, and any execution errors. For Functions deployed to live merchants, the merchant admin shows a Function activity log under the Functions section. The most common debugging pattern is: write a unit test for the run logic, use the CLI preview to test the full Function pipeline, then deploy to a development store for end-to-end testing before promoting to live.
Do Shopify Functions work on all Shopify plans or only Plus?
Functions are available on all Shopify plans. The Function types that require Shopify Plus are typically the more advanced ones like Cart Transform and certain Payment Customizations. Product Discount, Order Discount, and Shipping Discount Functions work on Basic, Standard, Advanced, and Plus. The number of active Functions per store may be capped on lower plans. For most merchants, the available Function types on their plan cover the discount and shipping logic they need. The full Function catalog is available in the Shopify documentation.
How are Shopify Functions different from Shopify Scripts?
Scripts ran inline Ruby on Shopify servers and modified the cart object directly. Functions are compiled WebAssembly modules that receive structured input and return structured output. The differences in practice: Functions are faster, scale better, support multiple programming languages, integrate with the Shopify app ecosystem, and work on all Shopify plans (not just Plus). Scripts were deprecated and removed entirely on June 30, 2026. Any merchant still relying on Scripts must migrate to Functions. Our Scripts migration playbook covers the migration paths.
What we recommend for teams just starting with Functions
If your team is new to Functions, here is the path we run with our own developers and recommend to client teams.
Week 1: Build a working Product Discount Function on a development store. Get comfortable with the CLI, the deployment flow, and the admin configuration.
Week 2: Build an Order Discount Function and a Shipping Discount Function. The schemas differ slightly. Build muscle for reading the input and output types.
Week 3: Build a Delivery Customization Function and a Payment Customization Function. These hide and reorder methods rather than apply discounts. Different output shape, same mental model.
Week 4: Build a Cart Transform Function. This is the most advanced type. It can split, bundle, or modify cart lines before checkout.
By the end of 4 weeks, a competent developer should be production-ready for any Function type a Plus merchant needs.
If you need help migrating Scripts to Functions or building a custom Function for your store, we run Functions development engagements for Indian and global Shopify Plus merchants. Email us at hello@exactwhy.com.