--- title: Upgrading to 2026-04 description: > This guide covers what's changed in `2026-04`, including the removal of the checkout metafield API, and how to adopt web components if you're upgrading from a version earlier than `2025-10`. api_version: 2026-04 api_name: checkout-ui-extensions source_url: html: >- https://shopify.dev/docs/api/checkout-ui-extensions/latest/upgrading-to-2026-04 md: >- https://shopify.dev/docs/api/checkout-ui-extensions/latest/upgrading-to-2026-04.md --- # Upgrading to 2026-04 This guide covers what's changed in `2026-04`, including the removal of checkout metafield write types, and how to adopt web components if you're upgrading from a version earlier than `2025-10`. *** ## Update API version Set the API version to `2026-04` in `shopify.extension.toml`. ## shopify.extension.toml ```toml api_version = "2026-04" [[extensions]] name = "your-extension" handle = "your-extension" type = "ui_extension" # Contents of your existing file... ``` *** ## File size limit **Note:** Your compiled UI extension bundle can't exceed 64 KB. Shopify enforces this limit at deployment to ensure fast loading times and optimal performance. Learn how to [analyze your bundle size](https://shopify.dev/docs/apps/build/app-extensions#analyzing-bundle-size). *** ## Migrate to cart metafields In `2026-04`, the checkout metafield API is removed and the corresponding change types `updateMetafield` and `removeMetafield` for `applyMetafieldChange` are no longer supported. Use `MetafieldUpdateCartChange` and `MetafieldRemoveCartChange` change types instead to write metafields on the cart, and `useAppMetafields` to read them. See [metafields API](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/apis/metafields) for more details. **Info:** To persist cart metafields to orders, ensure your app has the `write_orders` [scope](https://shopify.dev/docs/api/usage/access-scopes) and create a matching order metafield definition with the [`cart_to_order_copyable`](https://shopify.dev/docs/apps/build/metafields/use-metafield-capabilities#cart-to-order-copyable) capability. For a step-by-step walkthrough, see the [add a field to checkout](https://shopify.dev/docs/apps/build/checkout/fields-banners/add-field) tutorial. ### Request metafields in your extension TOML Request metafields that your extension needs access to in your extension configuration using `[[extensions.metafields]]`. See [configurations](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/configuration#metafields) for more details. ## shopify.extension.toml ```toml [[extensions.metafields]] namespace = "my-namespace" key = "gift-requested" ``` ### Update API calls Instead of reading checkout metafields using `useMetafield`, use `useAppMetafields` to read cart metafields. Use cart metafield change types `updateCartMetafield` and `removeCartMetafield` to write data. ##### After: using app metafields and cart metafield change types ##### Before: using checkout metafields (removed) ## Using app metafields and cart metafield change types ```tsx import "@shopify/ui-extensions/preact"; import { render } from "preact"; export default async () => { render(, document.body); }; function Extension() { const giftRequested = shopify.appMetafields.value.find( (appMetafield) => appMetafield.target.type === "cart" && appMetafield.metafield.namespace === "my-namespace" && appMetafield.metafield.key === "gift-requested", ); return ( ); async function onCheckboxChange(event) { const isChecked = event.target.checked; if (isChecked) { await shopify.applyMetafieldChange({ type: "updateCartMetafield", metafield: { namespace: "my-namespace", key: "gift-requested", value: "true", type: "boolean", }, }); } else { await shopify.applyMetafieldChange({ type: "removeCartMetafield", namespace: "my-namespace", key: "gift-requested", }); } } } ``` ## Using checkout metafields (removed) ```tsx import "@shopify/ui-extensions/preact"; import { render } from "preact"; import { useMetafield } from "@shopify/ui-extensions/checkout/preact"; export default function extension() { render(, document.body); } function Extension() { const giftRequested = useMetafield({ namespace: "my-namespace", key: "gift-requested", }); return ( ); async function onCheckboxChange(event) { const isChecked = event.target.checked; if (isChecked) { await shopify.applyMetafieldChange({ type: "updateMetafield", namespace: "my-namespace", key: "gift-requested", valueType: "string", value: "true", }); } else { await shopify.applyMetafieldChange({ type: "removeMetafield", namespace: "my-namespace", key: "gift-requested", }); } } } ``` *** ## Adopting web components The following sections apply if you're upgrading from a version earlier than `2025-10`. If you're already using web components, you can skip ahead. ### Adjust package dependencies As of `2025-10`, Shopify recommends Preact for UI extensions. Update the dependencies in your `package.json` file and re-install. ##### New dependencies with Preact ##### Previous dependencies with React ##### Previous dependencies with JavaScript ## New dependencies with Preact ## package.json ```json { "dependencies": { "preact": "^10.10.x", "@preact/signals": "^2.3.x", "@shopify/ui-extensions": "2026.4.x" } } ``` ## Previous dependencies with React ## package.json ```json { "dependencies": { "react": "^18.0.0", "@shopify/ui-extensions": "2025.4.x", "@shopify/ui-extensions-react": "2025.4.x", "react-reconciler": "0.29.0" }, "devDependencies": { "@types/react": "^18.0.0" } } ``` ## Previous dependencies with JavaScript ## package.json ```json { "dependencies": { "@shopify/ui-extensions": "2025.4.x" } } ``` ### Type​Script Configuration Get full IntelliSense and auto-complete support by adding a config file for your extension at `extensions/{extension-name}/tsconfig.json`. You do **not** need to change your app's root `tsconfig.json` file. ##### New tsconfig.json ##### Old tsconfig.json ## New tsconfig.json ## tsconfig.json ```json { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact", "target": "ES2020", "checkJs": true, "allowJs": true, "moduleResolution": "node", "esModuleInterop": true }, "include": ["./src", "./shopify.d.ts"] } ``` ## Old tsconfig.json ## tsconfig.json ```json { "compilerOptions": { "jsx": "react-jsx" }, "include": ["./src"] } ``` ### Upgrade the Shopify CLI The new CLI adds supoort for building with web components. The `shopify app dev` command runs your app and also generates a `shopify.d.ts` file in your extension directory, adding support for the new global `shopify` object. ## Support new global shopify object ## CLI ```bash # Upgrade to latest version of the CLI npm install -g @shopify/cli # Run the app to generate the type definition file shopify app dev ``` ### Optional ESLint configuration If your app is using ESLint, update your configuration to include the new global `shopify` object. ## .eslintrc.cjs ```js module.exports = { globals: { shopify: 'readonly', }, }; ``` ### Migrate API calls Instead of accessing APIs from a callback parameter, access them from the global `shopify` object. Here's an example of migrating the `applyAttributeChange` API call. ##### New API calls in Preact ##### Previous API calls in React ##### Previous API calls in JavaScript ## New API calls in Preact ## Preact ```tsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( ); } async function onCheckboxChange(event) { const isChecked = event.target.checked; const result = await shopify.applyAttributeChange({ type: 'updateAttribute', key: 'includeGift', value: isChecked ? 'yes' : 'no', }); console.log( 'applyAttributeChange result', result, ); } ``` ## Previous API calls in React ## React ```tsx import { reactExtension, Checkbox, useApi, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { const api = useApi(); async function onCheckboxChange(isChecked) { const result = await api.applyAttributeChange( { type: 'updateAttribute', key: 'includeGift', value: isChecked ? 'yes' : 'no', }, ); console.log( 'applyAttributeChange result', result, ); } return ( Include a complimentary gift ); } ``` ## Previous API calls in JavaScript ## JavaScript ```ts import { extension, Checkbox, } from '@shopify/ui-extensions/checkout'; export default extension( 'purchase.checkout.block.render', (root, api) => { async function onCheckboxChange(isChecked) { const result = await api.applyAttributeChange({ type: 'updateAttribute', key: 'includeGift', value: isChecked ? 'yes' : 'no', }); console.log( 'applyAttributeChange result', result, ); } root.replaceChildren( root.createComponent( Checkbox, { onChange: onCheckboxChange, }, 'Include a complimentary gift', ), ); }, ); ``` ### Migrate hooks If you had previously been using React hooks, import those same hooks from a new Preact-specific package. Here's an example of migrating the `useAttributeValues` hook. ##### New hooks in Preact ##### Previous hooks in React ## New hooks in Preact ## Preact ```tsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useAttributeValues} from '@shopify/ui-extensions/checkout/preact'; export default function extension() { render(, document.body); } function Extension() { const [includeGift] = useAttributeValues([ 'includeGift', ]); return ( ); } async function onCheckboxChange(event) { const isChecked = event.target.checked; const result = await shopify.applyAttributeChange({ type: 'updateAttribute', key: 'includeGift', value: isChecked ? 'yes' : 'no', }); console.log( 'applyAttributeChange result', result, ); } ``` ## Previous hooks in React ## React ```tsx import { reactExtension, Checkbox, useAttributeValues, useApplyAttributeChange, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { const [includeGift] = useAttributeValues([ 'includeGift', ]); const applyAttributeChange = useApplyAttributeChange(); async function onCheckboxChange(isChecked) { const result = await applyAttributeChange({ type: 'updateAttribute', key: 'includeGift', value: isChecked ? 'yes' : 'no', }); console.log( 'applyAttributeChange result', result, ); } return ( Include a complimentary gift ); } ``` ### Migrate to web components Web components are exposed as custom HTML elements. Update your React or JavaScript components to custom elements. ##### New components in Preact ##### Previous components in React ##### Previous components in JavaScript ## New components in Preact ## Preact ```tsx /* eslint-disable react/self-closing-comp */ import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { return ( Save ); } ``` ## Previous components in React ## React ```tsx import { reactExtension, InlineStack, TextField, Button, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { return ( ); } ``` ## Previous components in JavaScript ## JavaScript ```ts import { extension, InlineStack, TextField, Button, } from '@shopify/ui-extensions/checkout'; export default extension( 'purchase.checkout.block.render', (root, _api) => { root.replaceChildren( root.createComponent(InlineStack, {}, [ root.createComponent(TextField, { label: 'Gift message', }), root.createComponent(Button, {}, 'Save'), ]), ); }, ); ``` ### Mapping legacy components to web components | **Legacy Component** | **Web Component** | **Migration Notes** | | - | - | - | | | [Abbreviation](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/abbreviation) | Available | | `Badge` | [Badge](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/badge) | Available | | `Banner` | [Banner](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/feedback/banner) | Available | | `BlockLayout` | | Removed. Use `Grid` | | `BlockSpacer` | | Removed. Use [Stack](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/stack) with `gap` property | | `BlockStack` | | Removed. Use [Stack](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/stack) with `direction=block` | | `Button` | [Button](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/button) | Available | | `Chat` | `Chat` | Coming soon | | `Checkbox` | [Checkbox](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/checkbox) | Available | | `Choice` | [Choice](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/choicelist#choice) | Available | | `ChoiceList` | [ChoiceList](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/choicelist) | Available | | `ClipboardItem` | [ClipboardItem](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/utilities/clipboarditem) | Available | | `ConsentCheckbox` | [ConsentCheckbox](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/consentcheckbox) | Available | | `ConsentPhoneField` | [ConsentPhoneField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/consentphonefield) | Available | | `DateField` | [DateField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/datefield) | Available | | `DatePicker` | [DatePicker](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/datepicker) | Available | | `Disclosure` | [Details](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/interactive/details) and [Summary](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/interactive/details#summary) | Available | | `Divider` | [Divider](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/divider) | Available | | `DropZone` | [DropZone](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/dropzone) | Available | | | [EmailField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/email-field) | Available | | `Form` | [Form](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/form) | Available | | `Grid` | [Grid](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/grid) | Available | | `GridItem` | [GridItem](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/grid#griditem) | Available | | `Heading` | [Heading](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/heading) | Available | | `HeadingGroup` | [Section](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/section) | Available | | `Icon` | [Icon](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/media/icon) | Available | | `Image` | [Image](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/media/image) | Available | | `InlineLayout` | | Removed. Use `Grid` | | `InlineSpacer` | | Removed. Use [Stack](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/stack) | | `InlineStack` | [Stack](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/stack) | Removed. Use [Stack](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/stack) with `direction=inline` | | `Link` | [Link](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/link) | Available | | `List` | [UnorderedList](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/layout-and-structure/unordered-list) or [OrderedList](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/layout-and-structure/ordered-list) | Available | | `ListItem` | [ListItem](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/other/listitem) | Available | | `Map` | [Map](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/interactive/map) | Available | | `MapMarker` | [MapMarker](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/interactive/map#mapmarker) | Available | | `MapPopover` | [Popover](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/overlays/popover) | Available | | `Modal` | [Modal](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/overlay/modal) | Available | | | [MoneyField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/money-field) | Available | | `PaymentIcon` | [PaymentIcon](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/media/paymenticon) | Available | | `PhoneField` | [PhoneField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/phonefield) | Available | | `Popover` | [Popover](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/overlays/popover) | Available | | `Pressable` | [Clickable](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/clickable) | Available | | `ProductThumbnail` | [ProductThumbnail](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/media/productthumbnail) | Available | | `Progress` | [Progress](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/feedback/progress) | Available | | `QRCode` | [QRCode](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/other/qrcode) | Available | | `ScrollView` | [ScrollBox](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/layout-and-structure/scroll-box) | Available | | `Select` | [Select](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/select) | Available | | `Sheet` | [Sheet](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/overlays/sheet) | Available | | `SkeletonImage` | | Removed | | `SkeletonText` | [SkeletonParagraph](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/feedback-and-status-indicators/skeleton-paragraph) | Available | | `SkeletonTextBlock` | [SkeletonParagraph](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/feedback-and-status-indicators/skeleton-paragraph) | Available | | `Spinner` | [Spinner](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/feedback/spinner) | Available | | `Stepper` | [NumberField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/number-field) | Available | | `Switch` | [Switch](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/switch) | Available | | `Tag` | [Chip](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/chip) and [ClickableChip](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/clickable-chip) | Available | | `Text` | [Text](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/text) | Available | | `TextField` with `multiline` | [TextArea](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/text-area) | Available | | `TextBlock` | [Paragraph](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/paragraph) | Available | | `TextField` | [TextField](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/textfield) | Available | | | [Time](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/titles-and-text/time) | Available | | `ToggleButton` | [PressButton](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/press-button) | Available | | `ToggleButtonGroup` | [ChoiceList](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/forms/choicelist) or [PressButton](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/actions/press-button) | Available | | `Tooltip` | [Tooltip](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/overlays/tooltip) | Available | | `View` | [Box](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/web-components/structure/box) | Available | ***