Skip to content
Ecom

Shopify Checkout Extensibility Migration: What Changes for Conversion

A veteran walkthrough of the checkout.liquid to Checkout Extensibility migration, what actually breaks, and the three patterns WitsCode rebuilds on every store.

By WitsCode12 min read

If you run a Shopify Plus store and you have not yet fully migrated your Thank You and Order Status pages, you are living on borrowed time. Shopify began auto-upgrading Plus stores in January 2026 with thirty days of notice, and when that upgrade runs it silently removes every additional script, every app that injected via script tag, and every checkout.liquid customization still attached to those pages. If you are on a non-Plus plan, August 26, 2026 is the hard cutoff. And if you still have any Ruby Script running discount, shipping, or payment logic, April 15, 2026 is the date you can no longer edit them and June 30, 2026 is the date they stop executing entirely.

This is not an IT migration. It is a checkout-conversion event, and the gap between handling it well and handling it badly shows up in revenue inside forty-eight hours of cutover. The merchants who treat it as a compliance checkbox lose one to three percent of conversion rate and spend the next quarter hunting down why. The merchants who treat it as a rebuild keep their numbers and usually pick up a point or two because the new surface is genuinely faster.

Why this migration is different from a theme upgrade

A theme upgrade swaps presentation. Checkout Extensibility swaps the runtime. The old checkout.liquid world let you paste arbitrary HTML, CSS, and JavaScript into a single Liquid file and run it inline with the rest of the checkout. That freedom is exactly why Shopify could not make checkout faster, safer, or PCI-predictable at scale, and it is why the replacement looks nothing like it.

Checkout Extensibility replaces three things with three different mechanisms. Presentation customizations such as trust badges, cart-line messaging, and gift notes move into Checkout UI Extensions, which are sandboxed React components that render in merchant-chosen slots. Business logic for discounts, shipping rules, and payment gating moves into Shopify Functions, which are WebAssembly modules that execute server-side inside Shopify's infrastructure in under five milliseconds. Branding such as logos, typography, and colors moves into the Checkout Editor, which is a no-code settings surface.

The merchant-facing consequence is that the old model of "our developer can do anything in checkout" becomes "there are named extension points, and you work within them." The conversion consequence is that every customization you relied on needs to be classified into one of the three buckets, rebuilt, and tested, because a customization that does not cleanly map into any of them will not survive the migration.

The deadlines in plain English

For Plus stores, the Information, Shipping, and Payment steps of checkout were required to be migrated by August 13, 2024. That deadline has already passed and Plus stores operating past it had their checkouts forcibly upgraded. The Thank You and Order Status pages had a separate deadline of August 28, 2025, and starting in January 2026 Shopify began issuing thirty-day auto-upgrade notices to Plus stores still on checkout.liquid for those pages. When the auto-upgrade fires, the additional scripts box is emptied, any app using script tag injection on Thank You or Order Status stops rendering, and the custom Liquid is wiped. No rollback.

For non-Plus stores, the full deadline for Thank You and Order Status migration is August 26, 2026. Non-Plus stores never had access to checkout.liquid for the three checkout steps themselves, so the scope is narrower, but the post-purchase surfaces still need UI extensions.

Separately from the checkout.liquid timeline, Shopify Scripts, the Ruby-based tool that has powered custom discounts, shipping rules, and payment visibility since 2016, is being fully retired. April 15, 2026 is the edit freeze, meaning you cannot publish new Scripts or modify existing ones after that date. June 30, 2026 is the kill date when all active Scripts stop running. If your "above five thousand rupees, hide cash on delivery" rule is a Ruby Script and you do nothing, on July 1, 2026 every order will offer cash on delivery regardless of cart size.

Where Shopify Functions live now

The Ruby Scripts surface had three buckets: line-item Scripts for discounts, shipping Scripts for rate logic, and payment Scripts for gating methods. Shopify Functions map onto those and extend further. The Discount Function API covers product, order, and shipping discounts and replaces both line-item and shipping-discount Scripts. The Delivery Customization Function API hides, reorders, or renames shipping methods in real time during checkout, which is the direct successor to shipping Scripts. The Payment Customization Function API does the same for payment methods and is where the cash-on-delivery conditional logic now lives. Then there are new surfaces that did not exist in Scripts at all: Cart and Checkout Validation Functions that can block checkout on a condition such as minimum order value or age gate, Cart Transform Functions for bundles and line merging, Fulfillment Constraints, and Order Routing Location Rules.

Functions are compiled to WebAssembly and run inside Shopify's platform with sub-five-millisecond execution and no cold starts. You write them in JavaScript, TypeScript, or Rust using the Shopify CLI, deploy them as app extensions, and activate them per market through the Checkout Editor. The limit is twenty-five active Functions per type per store, which sounds generous until you realize a mature store often has fifteen discount rules, eight payment rules, and another dozen shipping customizations and is genuinely hitting the ceiling. Consolidation during migration is not optional.

What actually breaks during the migration

The obvious breakages are the ones every migration guide lists. Custom HTML and CSS pasted into checkout.liquid disappears. Apps that injected trust widgets, cart upsells, or post-purchase surveys via the additional scripts box go silent. JavaScript that read or wrote DOM classes unique to the old checkout stops finding its targets. Custom Liquid for translations, currency symbols, or country-specific messaging is wiped. These are annoying but obvious, and because they are visible they get fixed.

The breakages that quietly cost you revenue are the ones the top-ranking articles do not cover.

The first is cash-on-delivery conditional logic. Most Indian and Southeast Asian stores, and a surprising number of European ones with B2B segments, run a Ruby Script that hides COD above a cart threshold or for repeat fraud signals. When Scripts stop running and the replacement Payment Customization Function has not been deployed or activated on the correct market, COD appears on every order. Fraudulent and undelivered COD orders surge within days, and the cost shows up not on the conversion dashboard but in the returns and reverse-logistics line of the P&L four weeks later.

The second is Google Consent Mode v2 event-firing order. Inside checkout.liquid you had precise control over when the consent update fired relative to the purchase event. The new Web Pixel API runs in a sandboxed worker with a fixed event timeline, and if you naively port the pixel code without understanding the sandbox, you will fire purchase events before consent is granted, meaning the event is dropped downstream, or you will fire them with denied consent flags, meaning attribution disappears from Google Ads. The store still converts. Your reporting shows a ten-to-thirty-percent drop in tracked conversions that nobody can explain.

The third is pixels that only ever fired on checkout.liquid. Facebook CAPI implementations written by agencies in 2021 commonly live in the additional scripts box and fire a purchase event with the order payload. The Web Pixel sandbox does not allow that code to run as-is, and App Pixels require a registered Shopify app. If your CAPI is broken, Facebook's algorithm degrades silently and your ROAS drops inside a week. TikTok pixel, Klaviyo purchase tracking, and Pinterest enhanced match commonly have the same failure mode.

The fourth is discount logic that relied on cart line properties not exposed in the Discount Function input query. Functions operate on a defined GraphQL input schema, and if your old Script read a custom line property such as a personalization field or a hidden tag set by a product-options app, that field may not be accessible to the Function without also installing a metafield pipeline. The Function runs, returns a discount, but the amount is wrong by a few rupees, and the customer either sees a lower discount than promised or overpays on checkout. Nobody notices until the support queue fills with complaints.

The fifth is the post-purchase extension slot. The old world let you stack multiple apps on order status. The new post-purchase extension is single-slot, meaning only one app can own the step between payment and the Thank You page. If your upsell app and your review-request app both need that slot, you pick one.

The three patterns WitsCode rebuilds every time

Past a certain number of migrations, the work stops being bespoke. Roughly ninety percent of what any store needs collapses into three patterns, and we build them first because every other customization can wait.

The first pattern is a Delivery Customization Function that hides, reorders, or renames shipping methods in checkout. This is where cash-on-delivery threshold logic lives, where "hide express shipping for PO boxes" lives, and where "rename standard to free two-to-four-day delivery when cart exceeds threshold" lives. The Function receives the cart and delivery groups as input and returns an operations array of hide, move, and rename actions. It is deployed as part of a Shopify app, activated in the Checkout Editor per market, and runs on every cart change with no perceptible latency.

The second pattern is a Checkout UI Extension that renders inside the checkout flow itself. This is the successor to the cart upsell widget, the gift-note textarea, the trust-badge row, and the "enter your GST number" field. The extension targets one of the named extension points, such as the cart-line item render-after target or a checkout block target, and uses React hooks provided by Shopify's extension API to read cart state and apply changes. The merchant drags the block into place in the Checkout Editor. The critical constraint is that the extension runs in a sandboxed React runtime. You cannot ship arbitrary JavaScript, you cannot touch the DOM, and you cannot load third-party scripts. Whatever logic you need to run server-side goes through your app backend via authenticated fetch.

The third pattern is a Thank You UI Extension that renders on the order confirmation page. This is the successor to order-status surveys, referral widgets, account-creation prompts, and iframe upsells. The extension targets the Thank You block render point, uses hooks to read order and customer data, and calls out to your app backend for anything that needs state. It cannot mutate the order. If you need to modify what the customer is buying, that is a post-purchase extension, which is a different surface with a single-slot constraint. For everything after the order is confirmed, including delayed upsells that create a follow-up cart, the Thank You extension is the right home.

These three patterns cover the work for most stores. Once they are in place, the remaining specialized Functions (validation, cart transform, order routing) and extensions (customer account, post-purchase) are layered on for stores that need them.

The parallel-testing protocol that keeps your revenue intact

Most migration failures are not from bad code. They are from cutting over without validating that the new stack produces the same order shapes, fires the same pixels, and handles the same edge cases as the old one. The protocol we run on every engagement takes a week of calendar time and catches the failures before they hit customers.

Step one is to stand up a development store or a password-protected Plus store that mirrors the production theme, product catalog, app stack, and checkout configuration. This is not optional. Testing Functions against a toy cart on a blank store misses the real failure cases, which are always about specific product metafields, specific delivery profiles, and specific discount combinations that only exist in production.

Step two is to build the Functions and UI Extensions as a single app, deployed first to the staging store. The Shopify CLI provides a development tunnel, but production-shaped testing requires a real deploy because Functions only run when registered against a real store and activated through the Checkout Editor.

Step three is to validate the input queries against real cart shapes. Export twenty recent production orders covering the full distribution of cart sizes, discount types, delivery methods, payment methods, customer segments, and markets. Reconstruct those carts in staging and confirm each Function produces the expected output. This catches the missing-metafield problem before customers do.

Step four is to use Checkout Profiles, which is Shopify's native support for running a draft checkout configuration alongside the active one on the same store. Create a new profile containing the new Functions and extensions, keep the old profile active, and route internal test orders through the draft profile using its preview URL.

Step five is to place real orders through the draft profile with live payment methods at the smallest possible cart values. Cover the full matrix: cash on delivery, prepaid card, UPI or local wallet, high cart, low cart, percentage discount, fixed discount, gift card, B2B customer, guest checkout, logged-in checkout, domestic shipping, international shipping, and store pickup. At least twenty orders, ideally covering your top ten customer scenarios.

Step six is to verify the downstream pipes on every single test order. Facebook Events Manager should show a purchase event with the right value, currency, and matching event ID for CAPI deduplication. GA4 DebugView should show a purchase event with consent granted. Klaviyo should show a Placed Order metric. Your ERP or accounting integration should have received the order. Your warehouse management system should have received the fulfillment. If any of these is missing or wrong, you fix before cutover, not after.

Step seven is the cutover itself. Flip the draft profile to active during your lowest-traffic window with a rollback profile preserved for at least seventy-two hours. Hold monitoring dashboards open: conversion rate, checkout abandonment, payment method mix, average order value, and the pixel health checks. If anything drifts by more than one standard deviation from the prior week, flip back to the old profile and diagnose before re-cutting.

This protocol takes a week of calendar time and saves you a quarter of lost revenue. Every migration we have handled that skipped a step on this list surfaced a failure in the first week of production traffic. Every migration that followed it did not.

Where this lands you

The stores that complete the migration properly come out of it with a faster checkout, a cleaner app stack, and a maintainable configuration. Checkout Extensibility is genuinely better technology: the Function runtime is faster than any Liquid-based logic you could write, the UI extensions are more stable than random script-tag injections, and the Checkout Editor lets merchants make changes without developer intervention for the cases that used to require code. The migration cost is real, but so is the upside once you are on the other side.

The stores that coast into it, however, will find out in Q3 of 2026 what their actual dependency graph looked like, and they will find out while customers are abandoning carts. Checkout Extensibility is not a feature release. It is a platform change with a hard deadline, and the merchants who treat it that way will outperform the ones who do not for the next several quarters.

How WitsCode approaches your migration

We run this migration as a fixed-scope engagement with four phases. First we audit every customization currently in checkout.liquid, additional scripts, Shopify Scripts, and script-tag apps, and classify each into Function, UI Extension, Checkout Editor setting, or drop. Second we build the three core patterns and any store-specific Functions in a new Shopify app, deployed to a staging Checkout Profile. Third we run the parallel-testing protocol end-to-end, validating every pixel, every discount scenario, and every payment and shipping combination. Fourth we cut over in a controlled window with rollback preserved.

If you are a Plus store approaching your auto-upgrade notice, a non-Plus store staring at the August 2026 deadline, or any store still on Ruby Scripts, this is the work you need done now, not in the last month before cutoff. Get in touch and we will give you a scoped timeline against your specific checkout configuration.

Get weekly field notes.

Practical writing on shipping products, straight to your inbox. No spam.

Need help with this?

Shopify Development

We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.

Talk to us

Want to discuss ecom for your business?

Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.