Developer reference

Shopify Checkout UI Extensions for Personalization

Checkout UI Extensions replaced Checkout.liquid on August 13, 2024 (mandatory for all merchants). For personalization stores, they're where you display the full personalization spec at checkout, show a preview thumbnail, capture last-mile print instructions, and cross-sell related items. Here is the complete developer reference: extension targets, GraphQL access, personalization data flow, and the mandatory migration off Checkout.liquid.

Last updated: August 23, 2026~12 min readBy the Print It My Way team

Checkout.liquid is gone

Checkout.liquid — the old template-based way to customize Shopify checkout — was fully deprecated on August 13, 2024, and can no longer be edited. Every merchant with a custom checkout has migrated to Checkout UI Extensions, which are React-based components that render inside Shopify's checkout UI. If you have code that still references Checkout.liquid, it's either not running or running on legacy Shopify Plus stores that were grandfathered temporarily.

Extension targets — where your extension can appear

TargetWhat renders hereBest for personalization
purchase.checkout.block.renderAnywhere merchant places the block via checkout editorShow personalization preview thumbnail beside cart line
purchase.checkout.cart-line-item.render-afterBelow each cart lineDisplay "Custom text: Sarah" line-item property details
purchase.checkout.header.render-afterTop of checkoutTrust badges, "Personalized items — no refunds" notice
purchase.checkout.actions.render-beforeAbove the Buy Now buttonConfirmation checkbox for personalization spec
purchase.thank-you.block.renderOrder confirmation pageShow final print preview, upsell related items
customer-account.order-status.block.renderOrder status page (post-checkout)Show print progress, tracking, reprint request

Bootstrapping an extension

cd my-personalization-app
npm run shopify app generate extension
# Select: Checkout UI (via App CLI wizard)

The CLI creates extensions/checkout-personalization/ with a Preact-based entry point. Extensions use a subset of React (Preact under the hood) and render to Shopify's UI primitives (no arbitrary HTML/CSS — components like <BlockStack>, <Text>, <Banner>, <Button>).

Displaying personalization data

import { reactExtension, useCartLines, Text, BlockStack, InlineLayout, Image } from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.cart-line-item.render-after',
  () => <PersonalizationDetails />
);

function PersonalizationDetails() {
  const [line] = useCartLines(); // current cart line
  const attrs = line.attributes ?? [];
  const customText = attrs.find(a => a.key === 'Custom text')?.value;
  const photoUrl = attrs.find(a => a.key === '_photo_url')?.value;

  if (!customText && !photoUrl) return null;

  return (
    <BlockStack spacing="tight">
      {customText && <Text size="small">Text: {customText}</Text>}
      {photoUrl && (
        <InlineLayout>
          <Image source={photoUrl} accessibilityDescription="Your uploaded photo" />
          <Text size="small">Your uploaded photo</Text>
        </InlineLayout>
      )}
    </BlockStack>
  );
}

Confirmation checkbox before checkout

Personalized items typically can't be refunded (they're made-to-order to a specific spec). Add a mandatory checkbox before checkout that captures the customer's acknowledgment:

import { reactExtension, useCartLines, useBuyerJourneyIntercept, Checkbox, Text, useState } from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.actions.render-before',
  () => <PersonalizationAcknowledgment />
);

function PersonalizationAcknowledgment() {
  const [acked, setAcked] = useState(false);
  const lines = useCartLines();
  const hasPersonalization = lines.some(l => l.attributes.length > 0);

  useBuyerJourneyIntercept(() => {
    if (hasPersonalization && !acked) {
      return { behavior: 'block', reason: 'Please acknowledge the personalization spec' };
    }
    return { behavior: 'allow' };
  });

  if (!hasPersonalization) return null;

  return (
    <Checkbox checked={acked} onChange={setAcked}>
      I confirm the personalization details are correct. Personalized items cannot be refunded.
    </Checkbox>
  );
}

Post-purchase upsell on thank-you page

The thank-you page target lets you show a personalization preview + upsell related SKUs (matching-color accessories, gift box, rush shipping for a next order):

import { reactExtension, useOrder, useTranslate } from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.thank-you.block.render',
  () => <ThankYouUpsell />
);

function ThankYouUpsell() {
  const order = useOrder();
  const hasPersonalized = order.lineItems.some(li =>
    li.customAttributes.some(a => a.key === 'Custom text' || a.key === '_photo_url')
  );
  if (!hasPersonalized) return null;

  return <PersonalizationPreviewAndUpsell orderId={order.id} />;
}

GraphQL access from within extensions

Extensions have restricted GraphQL access to Shopify's Checkout GraphQL API — you can query the cart, buyer identity, and shop data, but not arbitrary Admin data. For extra data (product recommendations, custom personalization spec lookup), your extension can call your own app's backend, but must go through fetch to a domain whitelisted in your extension's shopify.extension.toml.

Deploying + previewing

npm run shopify app deploy

Extensions deploy as an app version. Merchants enable via Checkout & Accounts editor → App blocks. Test on a dev store before promoting to production.

Frequently asked questions

What are Shopify Checkout UI Extensions?

React-based components that render inside Shopify's checkout UI. Replaced the deprecated Checkout.liquid on August 13, 2024. Extensions render at specific "targets" (cart line, header, order status, thank-you) using Shopify's UI primitives.

Can I still edit Checkout.liquid?

No — fully deprecated as of August 13, 2024. All checkout customization must use Checkout UI Extensions.

Which extension target should I use for personalization data?

purchase.checkout.cart-line-item.render-after — renders below each cart line, ideal for showing the personalization spec (custom text, uploaded photo thumbnail) inline with the item it applies to.

How do I block checkout if the customer hasn't acknowledged personalization?

Use useBuyerJourneyIntercept with a mandatory checkbox in the purchase.checkout.actions.render-before target. Return behavior: 'block' when the checkbox is unchecked.

Can Checkout UI Extensions call external APIs?

Yes via fetch, but only to domains whitelisted in your extension's shopify.extension.toml under network_access. Use this to hit your app's backend for personalized spec lookups or upsell recommendations.

Do I need Shopify Plus for Checkout UI Extensions?

No — Checkout UI Extensions are available on all Shopify plans. Some advanced targets (Buy Now button customization, custom shipping methods) are Plus-only, but personalization display targets work on Basic and up.

How do I show a personalization preview thumbnail at checkout?

Store the preview image URL as a line-item property (e.g., _preview_url). In your Checkout UI Extension, read the property from useCartLines() and render an <Image> component.

Best extension target for post-purchase personalization display?

purchase.thank-you.block.render for immediate confirmation with preview + upsell. customer-account.order-status.block.render for the ongoing order status page where customers check print progress.

Related reading

Try it free on Shopify

Print It My Way ships Checkout UI Extensions that display personalization specs, capture acknowledgment, and cross-sell on the thank-you page — no custom app development needed.

Install Print It My Way