Checkout Extensibility Migration Plan: Replace Legacy Checkout Customizations Safely

By Milan Dhameliya · · 4 min read

Migrate from checkout.liquid and scripts to Checkout UI Extensions, Functions, and Customer Events without revenue or tracking regressions.

Stores still carrying legacy checkout customizations are exposed to conversion, compliance, and measurement regression risk. You need a deterministic replacement map, not a one-shot rewrite.

Dates that matter for migration planning

  1. August 13, 2024: checkout.liquid stopped working on in-checkout pages.
  2. August 28, 2025: checkout.liquid, additional scripts, and script tags on Thank you/Order status reached end-of-support.
  3. January 6, 2026: Shopify started automatic upgrades for stores still using deprecated checkout pages.
  4. June 30, 2026: Shopify Scripts stop working. Shopify Functions remains.

Migration matrix by capability

  1. UI customization in checkout -> Checkout UI Extensions.
  2. Business rules/validation -> Shopify Functions.
  3. Tracking events -> Customer Events + Web Pixels API.
  4. Post-purchase UI/logic -> Extension targets and app blocks.

Inventory current customizations first

UI path: Settings > Checkout > View personalized report.

Capture each existing customization with:

  1. source location,
  2. business owner,
  3. expected behavior,
  4. replacement surface,
  5. rollback plan.

Checkout UI Extensions implementation

Add controlled attribute capture in checkout

import {
  reactExtension,
  Checkbox,
  useApplyAttributeChange
} from "@shopify/ui-extensions-react/checkout";

export default reactExtension("purchase.checkout.contact.render-after", () => (
  <GiftWrapExtension />
));

function GiftWrapExtension() {
  const applyAttributeChange = useApplyAttributeChange();

  async function onToggle(value) {
    await applyAttributeChange({
      type: "updateAttribute",
      key: "gift_wrap_requested",
      value: value ? "yes" : "no"
    });
  }

  return <Checkbox onChange={onToggle}>Add gift wrap</Checkbox>;
}

Replace Script-based validation with Functions

Validate shipping address constraints

src/cart_validations_generate_run.graphql

query Input {
  cart {
    deliveryGroups {
      deliveryAddress {
        address1
        address2
      }
    }
  }
}

src/index.js

const PO_BOX = /p\.?\s*o\.?\s*box/i;

export function cartValidationsGenerateRun(input) {
  const blocked = (input.cart?.deliveryGroups || []).some((group) => {
    const a1 = group.deliveryAddress?.address1 || "";
    const a2 = group.deliveryAddress?.address2 || "";
    return PO_BOX.test(`${a1} ${a2}`);
  });

  if (!blocked) return { operations: [] };

  return {
    operations: [
      {
        validationAdd: {
          errors: [
            {
              message: "PO boxes are not supported for this shipping method.",
              target: "$.cart.deliveryGroups"
            }
          ]
        }
      }
    ]
  };
}

Rebuild analytics in Customer Events

UI path: Settings > Customer events.

analytics.subscribe("checkout_started", (event) => {
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    event: "checkout_started",
    checkout_token: event.data?.checkout?.token,
    currency: event.data?.checkout?.currencyCode
  });
});

analytics.subscribe("checkout_completed", (event) => {
  window.dataLayer.push({
    event: "purchase",
    order_id: event.data?.checkout?.order?.id,
    value: event.data?.checkout?.totalPrice?.amount,
    currency: event.data?.checkout?.currencyCode
  });
});

Release with configuration gates

UI path: Settings > Checkout > Configurations.

Use phased traffic rollout

  1. Create staging configuration.
  2. Assign low-risk market or segment.
  3. Validate event parity and conversion parity.
  4. Increase rollout in controlled increments.

Technical Checklist

SEO Checklist