---
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"
}
}
```
### TypeScript 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 |
***