Loading tutorials…
Loading tutorials…
On standard Shopify, checkout extensibility is mostly settings. On Plus, it's UI extensions, branding APIs, and Functions — code-deployed, version-controlled, infinitely flexible. The wrong setup is also infinitely expensive.
Who this is forShopify Plus brands who previously customized checkout.liquid heavily and need to migrate to the new model. Or Plus brands launching B2B / wholesale who need checkout flows that differ from DTC.
What you'll need
Step 1
Before touching the new model, list every thing the old checkout did: custom fields, scripts, trust badges, upsells, gift options. You cannot migrate what you haven't inventoried.
If you still have access to checkout.liquid (Plus had grace period through August 2025), pull the latest version from Git or admin → Themes → Edit code → checkout.liquid.
Inventory: (1) custom form fields (gift message, PO number, delivery instructions), (2) custom scripts (analytics pixels, A/B test snippets), (3) UI customizations (trust badges, testimonials, value props), (4) order-note logic, (5) post-purchase upsells.
Tag each by destination in the new model: 'Customer Events' (analytics), 'Checkout UI extension' (custom UI/fields), 'Functions' (discount/shipping/payment logic), 'Branding API' (colors/fonts/copy), 'Post-Purchase extension' (upsells).
Estimate dev hours per migration: simple field move = 1-2 hours, custom React extension = 4-8 hours, complex Function = 8-16 hours.
Step 2
Shopify CLI is required to build, test, and deploy Checkout UI extensions and Functions. Install it before writing any code.
Install Node.js 18+ and npm. Then: `npm install -g @shopify/cli @shopify/theme`.
Authenticate: `shopify login --store=your-store.myshopify.com`. Opens browser for OAuth.
Create a new extension app: `shopify app init`. Choose 'Build a Shopify app' → name it (e.g., 'checkout-extensions'). This creates a local project with the right structure.
Inside the app project: `shopify app generate extension`. Choose 'Checkout UI extension' or 'Function' depending on what you're building.
The CLI scaffolds a TypeScript/React (UI extension) or JavaScript/Rust (Function) starter. Open in your editor (VSCode, etc.).
Run `shopify app dev` to start the local dev server. The CLI deploys a draft extension to your dev store and gives you a preview URL.
Step 3
Branding API handles colors, fonts, button shapes, sizing — no code, just GraphQL or the UI. Get visual customization done before you touch UI extensions.
Shopify Admin → Settings → Checkout → Customize. The visual editor handles 60-70% of branding work without code.
For deeper control: use the Checkout Branding API via GraphQL. Endpoint: `admin/api/2025-01/graphql.json`. Mutation: `checkoutBrandingUpsert`.
You can configure: typography (font family, sizes, weights), colors (background, primary, secondary, success, error), corner radius, button styles, control styles (checkboxes, radios), header layout, order summary position.
Use the GraphQL playground in Plus admin → Apps → Develop apps to test branding mutations before scripting.
Save the branding config in version control (a JSON or GraphQL file in your repo). When you ship the same brand to expansion stores or sandbox, you can re-apply quickly.
Step 4
UI extensions are React components rendered in defined 'extension points' (e.g., below the email field, above the payment step). Build them once, deploy via CLI.
Choose your extension point. Common ones: `purchase.checkout.delivery-address.render-before`, `purchase.checkout.shipping-option-list.render-after`, `purchase.checkout.actions.render-before`. Full list in Shopify dev docs.
Write the React component. Use Shopify's UI components: `<TextField>`, `<Banner>`, `<BlockStack>`, `<Checkbox>`. Don't import generic React/HTML — UI extensions run in a sandboxed iframe with restricted DOM.
Read checkout state via hooks: `useApi()` for the full API, `useCustomer()` for customer data, `useShippingAddress()` for address. Don't try to access window.localStorage or document.cookie — sandbox blocks both.
Persist custom data via `useApplyAttributeChange()` (order attributes) or `useApplyNoteChange()` (order note). These survive to the order in admin and integrations.
Deploy: `shopify app deploy`. Confirms the extension version, uploads to Shopify, marks as ready for production.
Activate in admin: Settings → Checkout → Customize → drag your extension into the relevant slot. It's live.
Step 5
Functions replace Shopify Scripts. They run server-side at checkout, written in JavaScript or Rust, deployed via CLI. This is where discount stacking, shipping rate customization, and payment-method filtering live.
Scaffold a Function: `shopify app generate extension` → choose 'Function' → pick the type (Product Discount, Order Discount, Shipping Discount, Delivery Customization, Payment Customization).
Write the logic. Functions receive a GraphQL input (cart, customer, shipping rates) and return a GraphQL response (apply discount, hide payment method, etc.).
JavaScript Functions are simpler to start; Rust Functions are faster (matters at high checkout volume).
Test in the sandbox store: `shopify app dev` deploys the Function to a draft, you can run test checkouts that exercise the logic.
Configure rate limits: Functions have input-size and execution-time limits (e.g., cart up to 200 lines, execution under 5ms). Stay under or the Function falls back gracefully.
Deploy and activate: `shopify app deploy` + admin → Settings → [Discounts | Shipping | Payments] → Add → select your Function.
Step 6
Analytics and ad pixels move to Settings → Customer events. Use the Web Pixels API for custom JavaScript, or the channel apps for official pixels (Meta, Google, TikTok).
Settings → Customer events. Two types: App pixels (Meta, Google, TikTok via their channel apps) and Custom pixels (your own JS).
For official pixels, install/upgrade the latest channel apps. Each registers an App pixel automatically and handles browser + server-side (CAPI) events.
For custom pixels (Reddit, Snap, homegrown analytics): Add custom pixel → write JavaScript that subscribes to standard events ('checkout_started', 'checkout_completed', 'product_viewed').
Custom pixels run in a sandboxed iframe. You CANNOT access document.querySelector or read parent-page cookies. Use the event payload Shopify provides.
Set the privacy permission level: 'Required' if you have a real consent banner enforced; 'Not required' if you don't (most US-only stores).
Test in admin → Customer events → run a test event → confirm your pixel logs the event in the test console.
Step 7
Before declaring done: run real test purchases through every checkout flow (DTC, B2B if relevant, gift cards, subscriptions). Verify every UI extension, Function, pixel, and post-purchase flow fires correctly.
Run a DTC test purchase: add product, hit checkout, complete with a real card (refund yourself). Verify: custom UI extension renders, Function applies correct discount/shipping, branding looks right, custom pixel fires.
If B2B is enabled: log in as a B2B customer, run a B2B checkout. Different price list, different payment terms, often a different checkout layout. Verify.
If you have post-purchase upsells: hit the Thank You page and verify the upsell renders. Click through and confirm the upsell processes.
Check ad platforms within 24h: Meta Events Manager → Test events shows Purchase with browser + server columns. Google Ads → Conversions shows 'Recording'. TikTok → Events Manager shows CompletePayment.
Document the version of each extension and Function. When you debug a production issue 6 months later, you'll thank past-you.
Common mistakes
Treating UI extensions like normal React components
What goes wrong: Developers import generic React libraries, use document.querySelector, or call fetch() on external APIs. UI extensions run in a sandboxed iframe with restricted networking and a custom component library. Code fails silently in production. Bug discovered weeks later.
How to avoid: Read the Shopify Checkout UI extensions API reference before coding. Use only `@shopify/ui-extensions-react` components. Networking is restricted to a fetch-via-extension-target pattern, not direct.
Customizing checkout via CSS injected from theme app extensions
What goes wrong: Agencies inject CSS via theme app extensions to override checkout styles beyond what the Branding API allows. Every Shopify checkout update breaks these injections — typically once a quarter. The store ends up with broken checkout styling for 1-7 days per incident.
How to avoid: Use only the official Checkout Branding API. If you need styling beyond its limits, file a Shopify dev request. Do NOT inject CSS via theme code.
Skipping the Functions rate-limit check
What goes wrong: Functions have strict input-size and execution-time limits (5ms typical). High-cart-line orders or complex logic exceed the limit and the Function silently falls back to 'no effect.' Discount doesn't apply, shipping rate is wrong, payment method shows up that shouldn't. Hard to debug because there's no error.
How to avoid: Test Functions with worst-case carts (200 line items, complex pricing). Optimize logic to stay under limits. If you need more, switch from JavaScript to Rust Functions.
Building custom pixels without CAPI server-side
What goes wrong: Browser pixels are blocked by ITP, ad blockers, and Apple Mail Privacy. Without CAPI server-side events, ad platforms lose 30-50% of conversion data. Bid strategies optimize toward bad signals. CPA climbs 30-60% in 30-60 days.
How to avoid: For Meta/Google/TikTok, install the official channel apps and enable Maximum data sharing (CAPI). For custom pixels, post events server-side from your own backend in parallel with the browser pixel.
Not version-controlling the branding config and extensions
What goes wrong: Branding changes and extension code live only in Shopify Admin / one developer's machine. When you provision an expansion store or rebuild the dev sandbox, you re-do the work from scratch. Plus when the dev leaves, knowledge walks out the door.
How to avoid: Keep branding GraphQL mutations and extension source code in your team git repo. Use the Shopify CLI to deploy from CI/CD. Document the deploy process.
Forgetting to test B2B checkout separately
What goes wrong: B2B has its own checkout flow with company-level pricing, payment terms (net 30), and PO numbers. Brands that test only DTC after migration discover B2B checkout has broken fields or missing logic when their first B2B customer tries to order. Embarrassing and revenue-impacting.
How to avoid: After every checkout change, run a test B2B order. Different price list, different payment terms, different UI. Validate the same way you validate DTC.
Recap
Done — what's next
How to set up Shopify Functions (the Scripts replacement)
Read the next tutorial
Hand it off
Plus checkout extensibility is where DIY usually breaks. The Shopify CLI, UI extensions, Functions, and Branding API are 4 separate technical surfaces — most owners don't have the developer to navigate them. A Plus checkout specialist at $14-16/hr can ship the full migration in 2-3 weeks, typically $1,500-3,000 total, with ongoing pixel + extension monitoring at $400-600/mo.
See specialist rates
For visual branding only (colors, fonts, button styles), no — the Checkout Customizer UI handles it. For UI extensions, Functions, and custom pixels: yes, you need a developer. Shopify CLI is the deploy tool, and the extension code is React/JavaScript/Rust.
Shopify Functions. Scripts were deprecated August 2024. Functions are code-deployed (Shopify CLI), written in JavaScript or Rust, and run server-side at checkout. Each Script needs a separate Function rewrite. Plan 30-60 days for the full migration.
Yes — Plus supports Post-Purchase UI extensions and Order Status UI extensions. Same model as checkout UI extensions: React components, deployed via CLI, configured via admin. Common use cases: thank-you upsells, custom branding on order confirmation, embedded surveys.
Two patterns: (1) ship UI extensions or Function variants behind a feature flag in your own code and split traffic at the extension level; (2) use Shopify Markets to run different checkout configs per region. Plus does NOT have native A/B testing for checkout — most agencies use Optimizely or Convert at the extension level.
Same UI extension and Function model applies. B2B checkout has slightly different extension points (company selector, PO number field built-in). Test B2B separately — payment terms, price lists, and PO flow differ from DTC.
Shopify Plus
Shopify Functions are the official Scripts replacement. They run server-side at checkout, written in JavaScript or Rust, deployed via CLI. Most Plus brands need 3-7 Functions to replicate their old Scripts. Here's how to build the first one.
Shopify Plus
Shopify B2B (formerly the Wholesale Channel) is now native on Plus. Companies, price lists, net-30 terms, and customer-specific catalogs all work — but most brands set up Companies wrong and end up rebuilding 3 months later.
Shopify Plus
Most Plus brands migrated Scripts to Functions in a rush before the deprecation deadline. Now subtle bugs are surfacing: discounts not stacking, shipping rates wrong on edge cases, Functions silently failing. Here's the diagnostic sequence.
Shopify
Shopify killed checkout.liquid in August 2025. If you haven't migrated, your old pixels and order-confirmation customizations are silently broken. Here's the full checkout extensibility migration — pixels, CAPI, and post-purchase logic.