Shopify 14 min read

Shopify Checkout Extensibility: What Merchants Need to Know in 2025

Shopify's new Checkout Extensibility replaced checkout.liquid in 2024. This guide covers what changed, how UI Extensions and Functions work, what you can and can't customise, and when to hire a developer.

A
Aumlytics Team
·

If you’ve been running a Shopify Plus store with a customised checkout, 2024 brought one of the biggest required migrations in Shopify’s history. The old checkout.liquid system — which let you drop custom HTML and JavaScript directly into checkout pages — is gone. All Shopify Plus stores must use the new Checkout Extensibility system.

If you’re not on Plus but you’ve wanted checkout customisation, Checkout Extensibility is also now available to standard Shopify plans with a limited feature set.

This guide explains what changed, what you can actually customise now, what you can’t, and when you need a developer to make it work.


What Was checkout.liquid?

checkout.liquid was a Liquid template file that Shopify Plus merchants could edit directly. Like any Liquid template, you could add custom HTML, include external scripts, display custom fields, restructure the layout, and integrate third-party services.

It was powerful because it treated the checkout like any other page on your Shopify theme — editable HTML with access to Liquid variables.

It was also dangerous for the same reason. Custom JavaScript in checkout caused:

  • Broken checkout experiences when Shopify updated its checkout logic
  • Security vulnerabilities (payment page scripts are a top target for card skimmers)
  • Performance degradation from poorly-optimised third-party scripts
  • Maintenance burden after every Shopify update

Shopify deprecated checkout.liquid and required migration to Checkout Extensibility for all Shopify Plus stores by August 2024.

Official reference: Checkout Extensibility overview


What Is Checkout Extensibility?

Checkout Extensibility is Shopify’s new system for customising the checkout experience. Instead of editing a template directly, you extend checkout through two mechanisms:

  1. UI Extensions — inject custom UI elements (fields, banners, content blocks) into specific slots in the checkout layout
  2. Shopify Functions — modify checkout business logic (discounts, shipping, payment, cart validation) via server-side serverless functions

The key philosophical difference: you’re extending a Shopify-controlled checkout, not editing a template. Shopify controls the layout, security, and performance of the checkout itself. Your customisations plug into designated extension points.


Part 1: Checkout UI Extensions

UI Extensions let you add custom UI elements to specific places in the checkout. They’re built as React components using Shopify’s @shopify/ui-extensions-react library.

Where You Can Add UI Elements

Shopify defines specific extension targets — slots where you can inject content. Key targets:

TargetWhat You Can Do
purchase.checkout.block.renderGeneral-purpose block anywhere in checkout
purchase.checkout.delivery-address.render-beforeContent before shipping address form
purchase.checkout.shipping-option-list.render-afterContent after shipping options
purchase.checkout.payment-method-list.render-beforeContent before payment methods
purchase.checkout.order-summary.cart-line-item.render-afterUpsell/cross-sell below cart item
purchase.checkout.footer.render-beforeFooter area content
purchase.thank-you.block.renderThank you page blocks
purchase.order-status.block.renderOrder status page blocks

Limitations of UI Extension targets:

  • You can only add content to these predefined slots — you cannot reorder existing checkout elements
  • You cannot remove Shopify’s native checkout fields
  • You cannot inject arbitrary JavaScript that affects the checkout payment flow

Building a UI Extension

You build UI extensions inside a Shopify app (public or custom). Here’s a minimal example:

# Create a new Shopify app with the CLI
npm create @shopify/app@latest
cd my-checkout-app
shopify app generate extension
# Select: Checkout UI extension

This generates:

extensions/
  my-extension/
    src/
      Checkout.tsx    ← your React component
    shopify.extension.toml

A basic extension that adds a custom field to checkout:

// extensions/gift-message/src/Checkout.tsx
import {
  reactExtension,
  BlockStack,
  Text,
  TextField,
  useApplyAttributeChange,
  useAttributes,
} from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.block.render',
  () => <GiftMessageExtension />,
);

function GiftMessageExtension() {
  const applyAttributeChange = useApplyAttributeChange();
  const attributes = useAttributes();

  const currentMessage = attributes.find(
    (attr) => attr.key === 'gift_message'
  )?.value || '';

  return (
    <BlockStack spacing="base">
      <Text size="base" emphasis="bold">
        Add a gift message
      </Text>
      <TextField
        label="Gift message (optional)"
        value={currentMessage}
        onChange={(value) => {
          applyAttributeChange({
            type: 'updateAttribute',
            key: 'gift_message',
            value,
          });
        }}
        multiline={3}
        maxLength={200}
      />
    </BlockStack>
  );
}

What the APIs give you:

  • useApplyAttributeChange — add order attributes (stored on the order in Shopify)
  • useCartLines — read cart items
  • useShippingAddress — read shipping address
  • useCustomer — read customer data
  • useApplyDiscountCodeChange — apply/remove discount codes
  • useExtensionLanguage — localisation

What you can’t do in UI Extensions:

  • Run arbitrary server-side logic
  • Access document or window (no raw DOM manipulation)
  • Load external scripts from third-party domains
  • Redirect the user away from checkout

Part 2: Shopify Functions

Shopify Functions are serverless functions that run server-side to modify checkout business logic. Unlike UI Extensions which control what users see, Functions control what happens.

What Functions Can Do

Function TypeUse Case
DiscountCustom discount logic (e.g., buy 3 pay for 2, tiered discounts based on customer tags)
Cart and Checkout ValidationBlock checkout if conditions aren’t met (e.g., minimum order, product combination restrictions)
Payment CustomisationHide or reorder payment methods based on cart contents, customer location, or order value
Shipping CustomisationHide, rename, or reorder shipping options based on cart data
Order RoutingRoute orders to different fulfilment locations based on rules
Fulfillment ConstraintsDefine which locations can fulfil which items

Writing a Shopify Function

Functions are written in Rust (for performance) or JavaScript/TypeScript. The Shopify CLI handles compilation. Here’s a JavaScript discount function example:

shopify app generate extension
# Select: Discount Function (JavaScript)

Generated structure:

extensions/
  volume-discount/
    src/
      run.js         ← your function logic
    shopify.extension.toml
    input.graphql    ← what cart data you need
    schema.graphql   ← Shopify-generated, don't edit

A volume discount function (buy 3+ get 10% off):

// extensions/volume-discount/src/run.js
export function run(input) {
  const targets = [];
  const discountLines = [];

  for (const line of input.cart.lines) {
    if (line.quantity >= 3) {
      targets.push({
        cartLine: {
          id: line.id,
        },
      });
      discountLines.push({
        value: { percentage: { value: 10 } },
        targets: [{ cartLine: { id: line.id } }],
      });
    }
  }

  if (discountLines.length === 0) {
    return { discounts: [], discountApplicationStrategy: 'FIRST' };
  }

  return {
    discounts: discountLines,
    discountApplicationStrategy: 'FIRST',
  };
}

The input.graphql file defines what cart data your function receives:

# input.graphql — request only what you need
query RunInput {
  cart {
    lines {
      id
      quantity
      merchandise {
        ... on ProductVariant {
          id
          product {
            id
            tags
          }
        }
      }
    }
  }
}

Reference: Shopify Functions API documentation


What You Can Customise With Checkout Extensibility

✅ You CAN:

Add custom fields and information:

  • Gift message input field (stored as order attribute)
  • Custom date picker (e.g., delivery date selection)
  • Custom checkbox (e.g., “I agree to special installation terms”)
  • Business tax ID or VAT number field for B2B
  • Tip/gratuity selector

Add information banners:

  • “Orders placed before 2pm ship same day”
  • Trust badges (BBB, secure checkout icons)
  • Free shipping progress indicator
  • Custom returns policy text

Add upsells and cross-sells:

  • Product upsell below cart line items
  • “Add gift wrapping for £3” toggle
  • Extended warranty selector

Modify checkout business logic:

  • Tiered discounts (Functions)
  • Minimum order validation (Functions)
  • Hide incompatible shipping methods (Functions)
  • Hide pay-later options for restricted products (Functions)
  • Custom B2B payment terms (Functions)

Customise the thank-you page:

  • Add post-purchase survey
  • Display loyalty points earned
  • Show referral program CTA
  • Video or custom confirmation content

❌ You CANNOT:

Structurally redesign the checkout:

  • Reorder the address → shipping → payment steps
  • Add a custom pre-checkout step
  • Create a multi-page custom checkout flow
  • Remove the Shopify checkout header/footer

Inject arbitrary JavaScript:

  • No <script> tags with external code
  • No direct DOM manipulation
  • No custom CSS that overrides Shopify’s checkout styles

Remove native Shopify fields:

  • Cannot hide the email field
  • Cannot remove the billing address section
  • Cannot modify Shopify’s native validation

Access full checkout performance data directly:

  • GA4 checkout events must come through Shopify’s web_pixels API, not injected scripts

GA4 and GTM in the New Checkout

This is where most merchants hit a wall. The old checkout.liquid approach of injecting gtag.js directly is no longer possible.

Web Pixels API (Shopify’s Analytics Solution)

Shopify provides the Web Pixels API as the official way to add analytics to checkout. A web pixel is a sandboxed JavaScript snippet that runs in a separate iframe with access to Shopify checkout events.

Key checkout events available via web pixels:

  • checkout_started — began checkout
  • checkout_address_info_submitted — completed address step
  • checkout_shipping_info_submitted — selected shipping
  • checkout_completed — purchase confirmed
  • payment_info_submitted — entered payment info

Setting up GA4 via Web Pixels:

  1. In Shopify Admin → SettingsCustomer eventsAdd custom pixel
  2. Pixel type: Custom
  3. Write pixel code:
// Custom Web Pixel for GA4
analytics.subscribe('checkout_completed', (event) => {
  const checkout = event.data.checkout;

  // Send purchase event to GA4
  gtag('event', 'purchase', {
    transaction_id: checkout.order.id,
    value: parseFloat(checkout.totalPrice.amount),
    currency: checkout.currencyCode,
    items: checkout.lineItems.map((item, index) => ({
      item_id: item.variant.sku || item.variant.id,
      item_name: item.title,
      price: parseFloat(item.variant.price.amount),
      quantity: item.quantity,
      index: index,
    })),
  });
});

Limitation: Web pixels run in a sandboxed iframe with restricted network access. They can make requests to declared endpoints but can’t load arbitrary external scripts in real-time. You must declare which domains your pixel communicates with.

Reference: Web Pixels API documentation

GTM in Shopify Checkout (The Current Reality)

GTM cannot be injected into Shopify’s checkout the way it used to be via checkout.liquid. Your options:

  1. Use Web Pixels for checkout events — implement GA4 purchase events directly via the Web Pixels API (shown above)
  2. Use Shopify’s native GA4 integration — Shopify’s built-in Google & YouTube channel handles basic purchase tracking automatically
  3. Use server-side tracking — the Conversions API approach where your server sends purchase events after order creation (most reliable)

For e-commerce stores where checkout conversion data is critical, server-side tracking via the Orders API or webhooks is the most reliable approach — a webhook fires on orders/paid, your server extracts the order data, and sends a purchase event to GA4 via the Measurement Protocol.


Branding the New Checkout

While structural customisation is limited, Shopify does let you brand the checkout appearance:

Available in Shopify Admin → Settings → Checkout → Branding:

  • Logo (upload a custom logo for the checkout header)
  • Background colour and image
  • Button colours
  • Font selection (from a limited set)
  • Input field styling (corner radius, border style)
  • Accent colours

Checkout Editor (Shopify Plus only): Shopify Plus merchants get access to the Checkout Editor — a drag-and-drop tool that lets you add approved app extensions to the checkout without code.

  1. Shopify Admin → Online StoreThemesCustomize → dropdown → Checkout
  2. The Checkout Editor shows you approved extension slots
  3. Add installed app extensions by clicking the + in each slot

Migration Checklist: checkout.liquid → Checkout Extensibility

If you’re migrating from checkout.liquid, audit your current customisations:

□ List all custom fields in checkout.liquid → rebuild as UI Extensions
□ List all custom scripts → review which are replaceable via Web Pixels
□ List all discount logic → rebuild as Discount Functions
□ List all shipping rule customisations → rebuild as Shipping Functions
□ Payment method customisations → rebuild as Payment Functions
□ Analytics/GTM integration → rebuild via Web Pixels or server-side
□ Third-party app scripts → check if app has a UI Extension equivalent
□ Custom CSS overrides → rebuild via Checkout Branding API where possible
□ Test each extension in a development theme before going live

Reference: checkout.liquid migration guide


When Do You Need a Developer?

You can DIY:

  • Branding changes (logo, colours, fonts) — all in Shopify Admin, no code
  • Basic trust badge or banner — using an app from the App Store with a UI Extension
  • Gift message field — several free apps provide this as a UI Extension
  • Discount codes — native Shopify discount system handles most cases

You need a developer for:

  • Custom UI Extensions with specific data — if you need to show inventory status, customer-specific pricing, or data from an external system in checkout
  • Custom Shopify Functions — tiered discounts, complex validation rules, payment method rules based on multiple conditions
  • Server-side analytics setup — Measurement Protocol purchase tracking via webhooks
  • B2B checkout customisation — net terms, PO number fields, tax exemption handling
  • Custom upsell logic — product recommendations based on cart contents with live pricing
  • Multi-language/multi-currency edge cases — customisations that need to behave differently across markets

The Bottom Line for Shopify Merchants

Checkout Extensibility is more restrictive than checkout.liquid for power users, but it’s a better system overall. The sandboxed approach means fewer checkout-breaking deployments, better security (critical for a payment page), and consistent performance.

What most merchants actually need — gift message, trust badges, shipping messaging, basic upsells — is achievable with apps that have already built UI Extensions. Check the Shopify App Store first before commissioning custom development.

What requires custom development: B2B-specific customisations, complex discount logic, custom analytics setups, and anything that requires data from your own systems inside the checkout flow.

We build Shopify UI Extensions, Functions, and checkout analytics integrations for merchants who’ve outgrown what App Store solutions provide. Book a free consultation to scope your checkout project.

#shopify#checkout#checkout-extensibility#shopify-functions#ui-extensions#shopify-plus#checkout-liquid

Want This Implemented Correctly?

Let our team apply these concepts to your specific setup — with QA validation and 30 days of support.