Shopify has officially deprecated legacy checkout.liquid in favor of Checkout Extensibility. For years, Shopify Plus merchants customized checkout by directly modifying Ruby Liquid files, injecting arbitrary script tags, and styling forms with unconstrained CSS. While flexible, this approach frequently caused checkout breakages during major platform updates, introduced security vulnerabilities, and degraded mobile performance. This migration guide breaks down the new Checkout Extensibility architecture, Checkout UI Extensions, Shopify Functions, and Web Pixels API.
📅 Deprecation Timeline & Enforcement Milestones
Shopify's migration timeline establishes strict deprecation dates:
- Information, Shipping, and Payment steps:
checkout.liquiddeprecated since August 2024. - Thank You and Order Status Pages: Full deprecation finalized in 2025/2026. Customizations must use Checkout UI Extensions and Web Pixels.
- Shop Pay Parity: Checkout Extensibility customizations natively execute inside Shop Pay one-click checkouts—a capability never possible under legacy
checkout.liquid.
1. The 3 Architectural Pillars of Checkout Extensibility
Modern checkout customization is divided into three purpose-built, secure components:
Built with Preact / React and rendered in an isolated sandbox. Allows injecting bespoke UI elements (such as dynamic gift wrapping options, custom banners, and post-purchase upsells) into designated extension target slots without accessing sensitive customer payment details.
Compiled to WebAssembly and executed on Shopify's global edge infrastructure within strict edge latency budgets (typically low millisecond range) without blocking client-side checkout rendering. Replaces legacy Shopify Scripts for custom discount logic, payment method filtering, and dynamic delivery option customization.
A sandboxed behavioral event tracking pipeline replacing legacy additional_scripts. Executes in an isolated Web Worker sandbox, reducing the risk of third-party tracking scripts delaying checkout rendering while respecting Customer Privacy API consent signals.
2. Building a Custom Upsell Banner with Checkout UI Extensions
Using the official Shopify CLI, developers generate extensions targeting specific checkout slots like purchase.checkout.block.render:
// Checkout UI Extension Component (Shopify UI Extensions React)
import {
reactExtension,
Banner,
BlockStack,
Button,
useApplyCartLinesChange,
useInstructions
} from '@shopify/ui-extensions-react/checkout';
export default reactExtension('purchase.checkout.block.render', () => );
function Extension() {
const applyCartLinesChange = useApplyCartLinesChange();
const instructions = useInstructions();
// Guard against checkout states where cart mutations are disallowed
if (!instructions.lines.canAddCartLine) {
return null;
}
async function addPriorityHandling() {
await applyCartLinesChange({
type: 'addCartLine',
merchandiseId: 'gid://shopify/ProductVariant/42109876543210',
quantity: 1
});
}
return (
);
}
3. Step-by-Step Migration Protocol for Shopify Plus Merchants
Migrating a live store with complex checkout requirements demands a structured transition plan:
- Audit
checkout.liquid: Document all custom CSS overrides, injected tracking snippets, and script tags currently active in the legacy template. - Audit Shopify Scripts: Categorize all active Ruby Scripts (Line Item Discounts, Payment Method Gateways, Shipping Rate calculators) and identify corresponding Shopify Function APIs.
- Migrate Tracking Tags to Web Pixels: Move Meta Pixel, Google Ads, and analytics tags to Settings → Customer Events using Shopify's official Web Pixel integrations.
- Build and Test Extensions in Checkout Editor: Use Shopify Admin's visual Checkout Editor to position extension blocks across desktop and mobile preview viewports.
- Verify Payment Gateway Parity: Execute end-to-end test orders using Shop Pay, PayPal Express, and standard credit cards to verify discount calculations and shipping rules execute identically across all paths.
4. Custom Discounts and Delivery Customization with Shopify Functions
Shopify Functions replace legacy Ruby-based Shopify Scripts. Because Functions compile to WebAssembly (Wasm), they execute on Shopify's global edge infrastructure with minimal server execution latency, scaling effortlessly during Black Friday peak traffic without timing out.
// Example Shopify Function Input Query (Cart Delivery Customization API)
query RunInput {
cart {
deliveryGroups {
deliveryOptions {
handle
title
}
}
buyerIdentity {
purchasingCompany {
company { id }
}
}
}
}
5. Migrating Analytics Tags to the Sandboxed Web Pixels API
Historically, tracking pixels were injected via additional_scripts on the Order Status page. In Checkout Extensibility, tracking scripts execute inside an isolated Web Worker sandbox via the Web Pixels API. By executing analytics in isolated Web Worker sandboxes, this architecture significantly reduces the risk of third-party tracking scripts blocking checkout completion while strictly limiting access to sensitive customer and payment data.
// Sandboxed Web Pixel Subscription in Shopify Admin > Customer Events
analytics.subscribe('checkout_completed', (event) => {
const checkout = event.data.checkout;
fetch('https://tracking.yourstore.com/events', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
eventName: 'Purchase',
orderId: checkout.order.id,
totalValue: checkout.totalPrice.amount,
currency: checkout.totalPrice.currencyCode,
items: checkout.lineItems.map(item => ({
sku: item.variant.sku,
quantity: item.quantity,
price: item.finalPrice.amount
}))
}),
keepalive: true
});
});
6. Architecture Comparison: Legacy checkout.liquid vs. Checkout Extensibility
| Feature | Legacy checkout.liquid | Modern Checkout Extensibility |
|---|---|---|
| Execution Environment | Unsandboxed browser DOM | Secure Web Worker sandbox |
| Shop Pay Compatibility | Incompatible (reverted to default UI) | Native Shop Pay compatibility |
| Upgrade Safety | Frequently broke on platform updates | API-versioned platform stability without direct DOM dependency |
| Logic Customization | Ruby Shopify Scripts | Shopify Functions (WebAssembly) |
7. Building a Custom Discount Function with WebAssembly
Shopify Functions allow developers to write custom business logic that runs directly within Shopify's checkout engine. Here is the structure of a volume discount function:
// Shopify Function Logic (JavaScript / WebAssembly)
export function run(input) {
const targets = input.cart.lines
.filter(line => line.quantity >= 3)
.map(line => ({
cartLine: { id: line.id }
}));
if (!targets.length) return { discounts: [] };
return {
discounts: [{
targets,
value: { percentage: { value: 15.0 } },
message: '15% Volume Discount Unlocked'
}]
};
}
📚 Verified Documentation & References:
Need Support Migrating to Checkout Extensibility?
Transitioning from legacy checkout.liquid to custom UI Extensions and Shopify Functions? Explore our Shopify Plus Engineering services or review our Shopify Checkout Abandonment Solutions guide.