Free Shopify store auditSpeed, SEO and conversion leaks β€” no cost, no obligation.
Claim it
Thriftizer Solutions LLPShopify Select Partner
Book a Growth Audit
PPC Aug 22, 2026 9 min read

Migrating checkout.liquid to Checkout Extensibility on Shopify Plus

Nothing ports over. Every checkout.liquid override, Additional Script and Shopify Script has to be rebuilt as a UI extension, a Function, a custom pixel or a Branding API setting β€” and some can't be rebuilt at all.

If you still have code in checkout.liquid, Additional Scripts or the Script Editor, the honest answer to "how do I do a checkout extensibility migration" is this: you are not porting code, you are rebuilding behaviour. Nothing transfers. Every override gets re-created as one of four things β€” a checkout UI extension, a Shopify Function, a custom pixel, or a setting in the Branding API. And a handful of things you built simply cannot exist any more, so the migration includes deciding what to drop.

Shopify pulled checkout.liquid support from the Information, Shipping and Payment steps in August 2024, and from the Thank You and Order Status pages a year later, taking the Script Editor with it. Stores that did nothing got moved onto the default checkout automatically, which usually means the customisation is already gone and someone noticed when GST fields stopped appearing on invoices. Either way, the work below is the same.

First, find everything. There are more places than you think

Before mapping anything, get the full inventory. In our experience four of these five turn up on any Plus store that has been live more than three years:

  • checkout.liquid in the published theme β€” usually a mix of CSS overrides, a trust-badge row, and one or two functional fields.
  • Additional Scripts under Settings β†’ Checkout β€” the graveyard. Pixels layered over five years, half of them duplicating native integrations, some pointing at endpoints that no longer resolve.
  • Script Editor β€” discount logic, free gifts, shipping rate renaming, payment method hiding.
  • Apps that injected into checkout via script tags. These stopped working silently. Check your app list against which ones now ship a checkout UI extension.
  • Order Status page scripts, which are separate from checkout scripts and where most conversion tracking actually lived.

Print all of it. Then mark each item: still needed, cosmetic, or dead. We regularly delete a third of Additional Scripts outright because Shopify's native GA4, Meta and Google Ads connections already cover them, and keeping both double-counts revenue.

Customisations that map cleanly to UI extensions

These are the easy ones. A checkout UI extension is a small React or JavaScript app that renders inside Shopify's own components, placed at a named target.

  • Custom input fields β€” GST number, delivery instructions, gift message, PAN for high-value orders. Build a block, save the value with useApplyAttributeChange as a cart attribute, or useApplyMetafieldChange if you need it on the order as structured data. Attributes show on the order in admin; metafields are what your ERP or invoicing app should read.
  • Consent checkboxes β€” age verification, prescription confirmation, terms acceptance. Pair the checkbox with useBuyerJourneyIntercept so checkout blocks until it's ticked. This is one of the few cases where the new API is genuinely better than the old hack, because the block is enforced server-side rather than by hiding a button.
  • Trust badges, payment logos, delivery promise copy β€” a static block at purchase.checkout.block.render or a targeted one like purchase.checkout.shipping-option-list.render-after.
  • Free-shipping threshold nudges β€” read useCartLines and the cart cost, render a banner. Trivial, and the only place in checkout where you can still talk to the buyer mid-flow.
  • Thank You and Order Status content β€” tracking widgets, app download prompts, referral blocks. These extension targets work on every Shopify plan, not just Plus, which surprises people.

One constraint that trips up developers coming from Liquid: placement is the merchant's decision, not the developer's. Blocks get positioned in the checkout editor, and a merchant dragging things around can move or remove your GST field without touching a line of code. Document which blocks are load-bearing and tell whoever owns the editor.

Discount, shipping and payment logic becomes a Function

Anything that used to live in the Script Editor is now a Shopify Function β€” WebAssembly, written in Rust or JavaScript, deployed as part of an app. Same outcomes, different mental model: a Function receives an input query and returns operations, and it cannot call your server mid-run.

  • Tiered and volume discounts, BOGO, cart-level promotions β†’ product, order or shipping discount functions. Available on all plans.
  • Renaming, reordering or hiding shipping rates β†’ a delivery customisation function. Plus only.
  • Hiding payment methods β†’ a payment customisation function. Plus only, and for Indian stores this is the single most valuable one.
  • Free gift with purchase β†’ either a discount function that zeroes a line, or a cart transform if you need a genuine bundle. The discount route is simpler and easier to report on.
  • Field and cart validation β†’ a cart and checkout validation function, which can hard-block checkout with an error tied to a specific field.

The COD case deserves its own paragraph because everyone in India asks for it. A payment customisation function can hide Cash on Delivery above an order value, for specific product tags, for specific customer metafield values, or based on the delivery address in the cart. What it cannot do is call an external RTO-risk API in real time β€” Functions have no network access. If your COD gating depends on a third-party pincode risk score, you either pre-compute that score into a customer or product metafield on a schedule, or you use an app that maintains its own logic. We usually go with metafields refreshed nightly; it's less clever and it works.

Additional Scripts to custom pixels: the part that quietly breaks reporting

Marketing tags that sat in Additional Scripts now go in Settings β†’ Customer events as custom pixels. They run in a sandbox β€” a separate frame with no access to the checkout DOM and no access to window from the parent page. Subscribe to events like checkout_completed and payment_info_submitted, read the payload, fire your call.

Two things go wrong. First, anything that needed to read the page β€” session recording, heatmaps, some fraud tools, a chat widget that pinned itself to the corner of the payment step β€” will not work, full stop. Second, migrating a pixel changes its event timing and its deduplication key, so your GA4 or Meta revenue for checkout week will not reconcile with Shopify's. Take a screenshot of last month's numbers in every platform before you publish, or you will spend a fortnight arguing about a discrepancy you caused yourself.

The customisations with no path forward

Say this to stakeholders early, in writing:

  • Arbitrary CSS. Styling is controlled by the Branding API and the checkout editor β€” colours, corner radius, fonts, button styles, background images, some spacing. You cannot target an element and move it 12 pixels left. If your old checkout was a pixel-perfect rebuild of your brand guidelines, you will get close, not identical.
  • Removing, renaming or reordering Shopify's native fields. Email stays. The address block order stays. A store selling only digital goods still gets the address step unless every line item is digital.
  • Injecting third-party JavaScript that needs the DOM. Covered above. This kills a specific class of CRO tooling inside checkout.
  • Custom HTML in the head, custom meta tags, custom fonts loaded from your own CDN.
  • A one-off, one-page layout of your own design. You get Shopify's one-page or three-page checkout, and blocks in the slots Shopify defines.

The trade is real: you lose control of the frame and you get a checkout that Shopify keeps making faster, more accessible and better at passing PCI review, plus extensions that survive theme updates. For most brands that's a good deal. For a couple of stores we've worked with, whose checkout carried a genuinely custom multi-step flow, it wasn't, and the right answer was to simplify the flow rather than pretend an extension could recreate it.

What the rebuild actually takes

Illustrative, but close to what a mid-sized Plus store looks like when we audit it. Say the inventory comes back as: 320 lines of checkout.liquid (180 of them pure CSS), 14 Additional Scripts, and 3 Scripts in the editor.

Rebuild plan and hours:

  • One private app with three checkout UI extension blocks β€” GST field, trust badges, COD notice: 18h
  • Validation function for phone number format: 6h
  • Payment customisation function, hide COD above β‚Ή5,000 and on three product tags: 8h
  • Discount function for the tiered promotion plus the free gift over β‚Ή2,499: 14h
  • Four custom pixels, after deleting six duplicates and two dead scripts: 5h
  • Branding API styling to approximate the old CSS: 6h
  • QA β€” 3 payment methods Γ— 2 devices Γ— 2 currencies = 12 combinations at 20 minutes each is 4h, run twice: 8h

That totals 65 hours. Price it against whatever your team or agency charges; our own breakdown sits on the Shopify development cost page. It is materially less than a replatform and materially more than the "couple of days" most founders assume when they hear the word migration.

The phone validation line is the one we most often get wrong on the first pass. Indian numbers arrive as +91 98xxx, 098xxx, 98xxx and with spaces or hyphens, and a regex that looks right in the editor rejects perfectly good buyers in production. Test with real numbers from three carriers before you publish.

Testing checkout when you can't just refresh the page

Use checkout profiles. Create a draft profile, build everything there, and keep the live checkout untouched until you publish. This is the single most useful thing in the whole extensibility toolkit and plenty of teams never touch it.

For local development, the extension dev server gives you a preview link that renders your blocks against a real cart. It's good for layout and logic. It is not good for payment flows, because the Bogus Gateway does not behave like Razorpay or a UPI intent flow. Before go-live, run at least one real β‚Ή1 order through each live payment method on a mobile browser, then refund it. On stores with more than one fulfilment location, run one order per location too β€” delivery groups behave differently once a cart splits, and that's where hidden shipping rate logic tends to fall over.

Publish the profile on a weekday morning, not a Friday evening, and watch orders for the first hour. If a validation function is too strict, you will see it as checkouts that reach the payment step and stop.

When to build your own app and when to buy

A checkout UI extension has to be delivered inside an app, even if that app is private to your store. If your requirements are a GST field and a trust badge, there are public apps that do it with a settings screen and no code. Use them. If your requirements touch your ERP, your invoicing rules, or COD logic specific to your category, build the app β€” you'll own the logic, avoid a monthly fee that scales with orders, and skip the app's own performance overhead. We cover the build path in more detail under Shopify app development.

The middle case is the awkward one: an app that does 80% of what you need. Extensions from different apps can sit in the same checkout, so a hybrid is possible, but two apps both writing cart attributes to the same key will overwrite each other, and debugging that in a live checkout is unpleasant. Decide on one owner per field.

If you're on Plus and still don't know what's left of your old checkout, start with the inventory β€” the theme file, the two script boxes, and your app list. It takes an afternoon and it tells you whether this is a two-week job or a two-day one. Our Shopify Plus team does that audit as a fixed piece of work; you can also just ask for a free audit and we'll tell you what we find, including the parts you no longer need to rebuild.

Previous postNext post

Ready to scale your D2C brand profitably?

Let's build a growth engine that drives more traffic, more conversions and more profit.

Book a Growth Audit
πŸ“… Free AuditπŸ’¬ WhatsApp