--- title: Metafields description: The API for interacting with metafields. api_version: 2025-10 api_name: checkout-ui-extensions source_url: html: https://shopify.dev/docs/api/checkout-ui-extensions/latest/apis/metafields md: https://shopify.dev/docs/api/checkout-ui-extensions/latest/apis/metafields.md --- # MetafieldsAPI Requires access to [protected customer data](https://shopify.dev/docs/apps/store/data-protection/protected-customer-data) for some properties. The API for interacting with metafields. ## StandardApi The base API object provided to `purchase` extension targets. * appMetafields SubscribableSignalLike\ required The metafields requested in the [`shopify.extension.toml`](https://shopify.dev/docs/api/checkout-ui-extensions/configuration) file. These metafields are updated when there's a change in the merchandise items being purchased by the customer. App owned metafields are supported and are returned using the `$app` format. The fully qualified reserved namespace format such as `app--{your-app-id}[--{optional-namespace}]` is not supported. See [app owned metafields](https://shopify.dev/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. [](https://shopify.dev/apps/store/data-protection/protected-customer-data)Requires access to [protected customer data](https://shopify.dev/docs/apps/store/data-protection/protected-customer-data). * metafields SubscribableSignalLike\ required The metafields that apply to the current checkout. Metafields are stored locally on the client and are applied to the order object after the checkout completes. These metafields are shared by all extensions running on checkout, and persist for as long as the customer is working on this checkout. Once the order is created, you can query these metafields using the [GraphQL Admin API](https://shopify.dev/docs/admin-api/graphql/reference/orders/order#metafield-2021-01) Tip \> Cart metafields are only available on carts created via the Storefront API version `2023-04` or later. ### SubscribableSignalLike Represents a read-only value managed on the main thread that an extension can subscribe to. Example: Checkout uses this to manage the state of an object and communicate state changes to extensions running in a sandboxed web worker. This interface is compatible with \[Preact's ReadonlySignal]\(https\://github.com/preactjs/signals/blob/a023a132a81bd4ba4a0bebb8cbbeffbd8c8bbafc/packages/core/src/index.ts#L700-L709). Some fields are deprecated but still supported for backwards compatibility. In version 2025-10, \[\`StatefulRemoteSubscribable\`]\(https\://github.com/Shopify/remote-dom/blob/03929aa8418a89d41d294005f219837582718df8/packages/async-subscription/src/types.ts#L17) was replaced with \`ReadonlySignalLike\`. Checkout will remove the old fields some time in the future. * current ```ts T ``` * destroy ```ts () => Promise ``` * subscribe ```ts (fn: (value: T) => void) => () => void ``` * value ```ts T ``` ```ts export interface SubscribableSignalLike extends ReadonlySignalLike { /** * @deprecated Use `.value` instead. */ readonly current: T; /** * @deprecated No longer needed. Use Preact Signal management instead. */ destroy(): Promise; } ``` ### AppMetafieldEntry A metafield associated with the shop or a resource on the checkout. * metafield The metadata information. ```ts AppMetafield ``` * target The target that is associated to the metadata. {% include /apps/checkout/privacy-icon.md %} Requires access to \[protected customer data]\(/docs/apps/store/data-protection/protected-customer-data) when the type is \`customer\`, \`company\` or \`companyLocation\`. ```ts AppMetafieldEntryTarget ``` ```ts export interface AppMetafieldEntry { /** * The target that is associated to the metadata. * * {% include /apps/checkout/privacy-icon.md %} Requires access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data) when the type is `customer`, `company` or `companyLocation`. */ target: AppMetafieldEntryTarget; /** The metadata information. */ metafield: AppMetafield; } ``` ### AppMetafield Represents a custom metadata attached to a resource. * key The key name of a metafield. ```ts string ``` * namespace The namespace for a metafield. App owned metafield namespaces are returned using the \`$app\` format. See \[app owned metafields]\(/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. ```ts string ``` * type The metafield's type name. ```ts string ``` * value The value of a metafield. ```ts string ``` * valueType The metafield’s information type. ```ts 'boolean' | 'float' | 'integer' | 'json_string' | 'string' ``` ```ts export interface AppMetafield { /** The key name of a metafield. */ key: string; /** * The namespace for a metafield. * * App owned metafield namespaces are returned using the `$app` format. See [app owned metafields](/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. */ namespace: string; /** The value of a metafield. */ value: string; /** The metafield’s information type. */ valueType: 'boolean' | 'float' | 'integer' | 'json_string' | 'string'; /** The metafield's type name. */ type: string; } ``` ### AppMetafieldEntryTarget The metafield owner. * id The numeric owner ID that is associated with the metafield. ```ts string ``` * type The type of the metafield owner. {% include /apps/checkout/privacy-icon.md %} Requires access to \[protected customer data]\(/docs/apps/store/data-protection/protected-customer-data) when the type is \`customer\`, \`company\` or \`companyLocation\`. ```ts | 'customer' | 'product' | 'shop' | 'shopUser' | 'variant' | 'company' | 'companyLocation' | 'cart' ``` ```ts export interface AppMetafieldEntryTarget { /** * The type of the metafield owner. * * {% include /apps/checkout/privacy-icon.md %} Requires access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data) when the type is `customer`, `company` or `companyLocation`. */ type: | 'customer' | 'product' | 'shop' | 'shopUser' | 'variant' | 'company' | 'companyLocation' | 'cart'; /** The numeric owner ID that is associated with the metafield. */ id: string; } ``` ### Metafield Metadata associated with the checkout. * key The name of the metafield. It must be between 3 and 30 characters in length (inclusive). ```ts string ``` * namespace A container for a set of metafields. You need to define a custom namespace for your metafields to distinguish them from the metafields used by other apps. This must be between 2 and 20 characters in length (inclusive). ```ts string ``` * value The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. ```ts string | number ``` * valueType The metafield’s information type. ```ts 'integer' | 'string' | 'json_string' ``` ```ts export interface Metafield { /** * The name of the metafield. It must be between 3 and 30 characters in * length (inclusive). */ key: string; /** * A container for a set of metafields. You need to define a custom * namespace for your metafields to distinguish them from the metafields * used by other apps. This must be between 2 and 20 characters in length (inclusive). */ namespace: string; /** * The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. */ value: string | number; /** The metafield’s information type. */ valueType: 'integer' | 'string' | 'json_string'; } ``` ## use​App​Metafields([filters](#useappmetafields-propertydetail-filters)​) Returns the metafields configured with `shopify.extension.toml`. ### Parameters * filters AppMetafieldFilters Default: {} ### Returns * AppMetafieldEntry\[] ### AppMetafieldFilters * id ```ts string ``` * key ```ts string ``` * namespace To filter for app owned metafields, use the \`$app\` format. The fully qualified reserved namespace format such as \`app--{your-app-id}\[--{optional-namespace}]\` is not supported. See \[app owned metafields]\(/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. ```ts string ``` * type ```ts 'customer' | 'product' | 'shop' | 'shopUser' | 'variant' | 'company' | 'companyLocation' | 'cart' ``` ```ts interface AppMetafieldFilters { id?: AppMetafieldEntryTarget['id']; type?: AppMetafieldEntryTarget['type']; /** * To filter for app owned metafields, use the `$app` format. The fully qualified reserved namespace format such as `app--{your-app-id}[--{optional-namespace}]` is not supported. * * See [app owned metafields](/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. */ namespace?: Metafield['namespace']; key?: Metafield['key']; } ``` ### AppMetafieldEntry A metafield associated with the shop or a resource on the checkout. * metafield The metadata information. ```ts AppMetafield ``` * target The target that is associated to the metadata. {% include /apps/checkout/privacy-icon.md %} Requires access to \[protected customer data]\(/docs/apps/store/data-protection/protected-customer-data) when the type is \`customer\`, \`company\` or \`companyLocation\`. ```ts AppMetafieldEntryTarget ``` ```ts export interface AppMetafieldEntry { /** * The target that is associated to the metadata. * * {% include /apps/checkout/privacy-icon.md %} Requires access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data) when the type is `customer`, `company` or `companyLocation`. */ target: AppMetafieldEntryTarget; /** The metadata information. */ metafield: AppMetafield; } ``` ### AppMetafield Represents a custom metadata attached to a resource. * key The key name of a metafield. ```ts string ``` * namespace The namespace for a metafield. App owned metafield namespaces are returned using the \`$app\` format. See \[app owned metafields]\(/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. ```ts string ``` * type The metafield's type name. ```ts string ``` * value The value of a metafield. ```ts string ``` * valueType The metafield’s information type. ```ts 'boolean' | 'float' | 'integer' | 'json_string' | 'string' ``` ```ts export interface AppMetafield { /** The key name of a metafield. */ key: string; /** * The namespace for a metafield. * * App owned metafield namespaces are returned using the `$app` format. See [app owned metafields](/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. */ namespace: string; /** The value of a metafield. */ value: string; /** The metafield’s information type. */ valueType: 'boolean' | 'float' | 'integer' | 'json_string' | 'string'; /** The metafield's type name. */ type: string; } ``` ### AppMetafieldEntryTarget The metafield owner. * id The numeric owner ID that is associated with the metafield. ```ts string ``` * type The type of the metafield owner. {% include /apps/checkout/privacy-icon.md %} Requires access to \[protected customer data]\(/docs/apps/store/data-protection/protected-customer-data) when the type is \`customer\`, \`company\` or \`companyLocation\`. ```ts | 'customer' | 'product' | 'shop' | 'shopUser' | 'variant' | 'company' | 'companyLocation' | 'cart' ``` ```ts export interface AppMetafieldEntryTarget { /** * The type of the metafield owner. * * {% include /apps/checkout/privacy-icon.md %} Requires access to [protected customer data](/docs/apps/store/data-protection/protected-customer-data) when the type is `customer`, `company` or `companyLocation`. */ type: | 'customer' | 'product' | 'shop' | 'shopUser' | 'variant' | 'company' | 'companyLocation' | 'cart'; /** The numeric owner ID that is associated with the metafield. */ id: string; } ``` ## use​Metafield([filters](#usemetafield-propertydetail-filters)​) Returns a single filtered `Metafield` or `undefined`. ### Parameters * filters MetafieldFilter required ### Returns * Metafield | undefined ### MetafieldFilter * key ```ts string ``` * namespace ```ts string ``` ```ts interface MetafieldFilter { namespace: string; key: string; } ``` ### Metafield Metadata associated with the checkout. * key The name of the metafield. It must be between 3 and 30 characters in length (inclusive). ```ts string ``` * namespace A container for a set of metafields. You need to define a custom namespace for your metafields to distinguish them from the metafields used by other apps. This must be between 2 and 20 characters in length (inclusive). ```ts string ``` * value The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. ```ts string | number ``` * valueType The metafield’s information type. ```ts 'integer' | 'string' | 'json_string' ``` ```ts export interface Metafield { /** * The name of the metafield. It must be between 3 and 30 characters in * length (inclusive). */ key: string; /** * A container for a set of metafields. You need to define a custom * namespace for your metafields to distinguish them from the metafields * used by other apps. This must be between 2 and 20 characters in length (inclusive). */ namespace: string; /** * The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. */ value: string | number; /** The metafield’s information type. */ valueType: 'integer' | 'string' | 'json_string'; } ``` ## use​Metafields([filters](#usemetafields-propertydetail-filters)​) Returns the current array of `metafields` applied to the checkout. You can optionally filter the list. ### Parameters * filters MetafieldsFilters ### Returns * Metafield\[] ### MetafieldsFilters * key ```ts string ``` * namespace ```ts string ``` ```ts interface MetafieldsFilters { namespace: string; key?: string; } ``` ### Metafield Metadata associated with the checkout. * key The name of the metafield. It must be between 3 and 30 characters in length (inclusive). ```ts string ``` * namespace A container for a set of metafields. You need to define a custom namespace for your metafields to distinguish them from the metafields used by other apps. This must be between 2 and 20 characters in length (inclusive). ```ts string ``` * value The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. ```ts string | number ``` * valueType The metafield’s information type. ```ts 'integer' | 'string' | 'json_string' ``` ```ts export interface Metafield { /** * The name of the metafield. It must be between 3 and 30 characters in * length (inclusive). */ key: string; /** * A container for a set of metafields. You need to define a custom * namespace for your metafields to distinguish them from the metafields * used by other apps. This must be between 2 and 20 characters in length (inclusive). */ namespace: string; /** * The information to be stored as metadata. Always stored as a string, regardless of the metafield's type. */ value: string | number; /** The metafield’s information type. */ valueType: 'integer' | 'string' | 'json_string'; } ``` ## CheckoutApi The API object provided to `purchase.checkout` extension targets. * applyMetafieldChange (change: MetafieldChange) => Promise\ required Performs an update on a piece of metadata attached to the checkout. If successful, this mutation results in an update to the value retrieved through the [`metafields`](https://shopify.dev/docs/api/checkout-ui-extensions/apis/metafields#standardapi-propertydetail-metafields) property. Note This method will return an error if the [cart instruction](https://shopify.dev/docs/api/checkout-ui-extensions/apis/cart-instructions#standardapi-propertydetail-instructions) `metafields.canSetCartMetafields` is false, or the buyer is using an accelerated checkout method, such as Apple Pay or Google Pay. ### MetafieldChange ```ts MetafieldRemoveChange | MetafieldUpdateChange | MetafieldRemoveCartChange | MetafieldUpdateCartChange ``` ### MetafieldRemoveChange Removes a metafield. * key The name of the metafield to remove. ```ts string ``` * namespace The namespace of the metafield to remove. ```ts string ``` * type The type of the \`MetafieldRemoveChange\` API. ```ts 'removeMetafield' ``` ```ts export interface MetafieldRemoveChange { /** * The type of the `MetafieldRemoveChange` API. */ type: 'removeMetafield'; /** * The name of the metafield to remove. */ key: string; /** * The namespace of the metafield to remove. */ namespace: string; } ``` ### MetafieldUpdateChange Updates a metafield. If a metafield with the provided key and namespace does not already exist, it gets created. * key The name of the metafield to update. ```ts string ``` * namespace The namespace of the metafield to add. ```ts string ``` * type The type of the \`MetafieldUpdateChange\` API. ```ts 'updateMetafield' ``` * value The new information to store in the metafield. ```ts string | number ``` * valueType The metafield’s information type. ```ts 'integer' | 'string' | 'json_string' ``` ```ts export interface MetafieldUpdateChange { /** * The type of the `MetafieldUpdateChange` API. */ type: 'updateMetafield'; /** The name of the metafield to update. */ key: string; /** The namespace of the metafield to add. */ namespace: string; /** The new information to store in the metafield. */ value: string | number; /** * The metafield’s information type. */ valueType: 'integer' | 'string' | 'json_string'; } ``` ### MetafieldRemoveCartChange Removes a cart metafield. * key The name of the metafield to remove. ```ts string ``` * namespace The namespace of the metafield to remove. ```ts string ``` * type The type of the \`MetafieldRemoveChange\` API. ```ts 'removeCartMetafield' ``` ```ts export interface MetafieldRemoveCartChange { /** * The type of the `MetafieldRemoveChange` API. */ type: 'removeCartMetafield'; /** * The name of the metafield to remove. */ key: string; /** * The namespace of the metafield to remove. */ namespace?: string; } ``` ### MetafieldUpdateCartChange Updates a cart metafield. If a metafield with the provided key and namespace does not already exist, it gets created. * metafield ```ts { key: string; namespace?: string; value: string; type: string; } ``` * type The type of the \`MetafieldUpdateChange\` API. ```ts 'updateCartMetafield' ``` ```ts export interface MetafieldUpdateCartChange { /** * The type of the `MetafieldUpdateChange` API. */ type: 'updateCartMetafield'; metafield: { /** The name of the metafield to update. */ key: string; /** The namespace of the metafield to add. */ namespace?: string; /** The new information to store in the metafield. */ value: string; /** * The metafield’s information type. * See the [`metafields documentation`](/docs/apps/custom-data/metafields/types) for a list of supported types. */ type: string; }; } ``` ### MetafieldChangeResult ```ts MetafieldChangeResultSuccess | MetafieldChangeResultError ``` ### MetafieldChangeResultSuccess * type The type of the \`MetafieldChangeResultSuccess\` API. ```ts 'success' ``` ```ts export interface MetafieldChangeResultSuccess { /** * The type of the `MetafieldChangeResultSuccess` API. */ type: 'success'; } ``` ### MetafieldChangeResultError * message A message that explains the error. This message is useful for debugging. It is \*\*not\*\* localized, and therefore should not be presented directly to the buyer. ```ts string ``` * type The type of the \`MetafieldChangeResultError\` API. ```ts 'error' ``` ```ts export interface MetafieldChangeResultError { /** * The type of the `MetafieldChangeResultError` API. */ type: 'error'; /** * A message that explains the error. This message is useful for debugging. * It is **not** localized, and therefore should not be presented directly * to the buyer. */ message: string; } ``` ## use​Apply​Metafields​Change() Returns a function to mutate the `metafields` property of the checkout. ### Returns * (change: MetafieldChange) => Promise\ ### MetafieldChange ```ts MetafieldRemoveChange | MetafieldUpdateChange | MetafieldRemoveCartChange | MetafieldUpdateCartChange ``` ### MetafieldRemoveChange Removes a metafield. * key The name of the metafield to remove. ```ts string ``` * namespace The namespace of the metafield to remove. ```ts string ``` * type The type of the \`MetafieldRemoveChange\` API. ```ts 'removeMetafield' ``` ```ts export interface MetafieldRemoveChange { /** * The type of the `MetafieldRemoveChange` API. */ type: 'removeMetafield'; /** * The name of the metafield to remove. */ key: string; /** * The namespace of the metafield to remove. */ namespace: string; } ``` ### MetafieldUpdateChange Updates a metafield. If a metafield with the provided key and namespace does not already exist, it gets created. * key The name of the metafield to update. ```ts string ``` * namespace The namespace of the metafield to add. ```ts string ``` * type The type of the \`MetafieldUpdateChange\` API. ```ts 'updateMetafield' ``` * value The new information to store in the metafield. ```ts string | number ``` * valueType The metafield’s information type. ```ts 'integer' | 'string' | 'json_string' ``` ```ts export interface MetafieldUpdateChange { /** * The type of the `MetafieldUpdateChange` API. */ type: 'updateMetafield'; /** The name of the metafield to update. */ key: string; /** The namespace of the metafield to add. */ namespace: string; /** The new information to store in the metafield. */ value: string | number; /** * The metafield’s information type. */ valueType: 'integer' | 'string' | 'json_string'; } ``` ### MetafieldRemoveCartChange Removes a cart metafield. * key The name of the metafield to remove. ```ts string ``` * namespace The namespace of the metafield to remove. ```ts string ``` * type The type of the \`MetafieldRemoveChange\` API. ```ts 'removeCartMetafield' ``` ```ts export interface MetafieldRemoveCartChange { /** * The type of the `MetafieldRemoveChange` API. */ type: 'removeCartMetafield'; /** * The name of the metafield to remove. */ key: string; /** * The namespace of the metafield to remove. */ namespace?: string; } ``` ### MetafieldUpdateCartChange Updates a cart metafield. If a metafield with the provided key and namespace does not already exist, it gets created. * metafield ```ts { key: string; namespace?: string; value: string; type: string; } ``` * type The type of the \`MetafieldUpdateChange\` API. ```ts 'updateCartMetafield' ``` ```ts export interface MetafieldUpdateCartChange { /** * The type of the `MetafieldUpdateChange` API. */ type: 'updateCartMetafield'; metafield: { /** The name of the metafield to update. */ key: string; /** The namespace of the metafield to add. */ namespace?: string; /** The new information to store in the metafield. */ value: string; /** * The metafield’s information type. * See the [`metafields documentation`](/docs/apps/custom-data/metafields/types) for a list of supported types. */ type: string; }; } ``` ### MetafieldChangeResult ```ts MetafieldChangeResultSuccess | MetafieldChangeResultError ``` ### MetafieldChangeResultSuccess * type The type of the \`MetafieldChangeResultSuccess\` API. ```ts 'success' ``` ```ts export interface MetafieldChangeResultSuccess { /** * The type of the `MetafieldChangeResultSuccess` API. */ type: 'success'; } ``` ### MetafieldChangeResultError * message A message that explains the error. This message is useful for debugging. It is \*\*not\*\* localized, and therefore should not be presented directly to the buyer. ```ts string ``` * type The type of the \`MetafieldChangeResultError\` API. ```ts 'error' ``` ```ts export interface MetafieldChangeResultError { /** * The type of the `MetafieldChangeResultError` API. */ type: 'error'; /** * A message that explains the error. This message is useful for debugging. * It is **not** localized, and therefore should not be presented directly * to the buyer. */ message: string; } ``` ### Examples * #### Use app owned metafields ##### Description Use the \`$app\` format to request metafields that are owned by your app in your extension configuration file. Your app exclusively controls structure, data, permissions and optional features for this type of metafield. See \[app owned metafields]\(/docs/apps/build/custom-data/ownership#reserved-prefixes) for more information. ##### Preact ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useAppMetafields} from '@shopify/ui-extensions/checkout/preact'; export default function extension() { render(, document.body); } function Extension() { const [energyRating] = useAppMetafields({ namespace: '$app', key: 'energy-rating', type: 'product', }).filter( (entry) => entry.target.id === shopify.target.value.merchandise.id, ); return ( energyRating && ( Energy rating:{' '} {energyRating.metafield.value} ) ); } ``` ##### TOML ```toml # other configs omitted [[extensions.metafields]] # tip: you can use $app:some-namespace to further segment your data namespace = "$app" key = "energy-rating" ``` ## Related [![](https://shopify.dev/images/icons/32/blocks.png)![](https://shopify.dev/images/icons/32/blocks-dark.png)](https://shopify.dev/docs/api/checkout-ui-extensions/targets) [ReferenceTargets](https://shopify.dev/docs/api/checkout-ui-extensions/targets) [![](https://shopify.dev/images/icons/32/apps.png)![](https://shopify.dev/images/icons/32/apps-dark.png)](https://shopify.dev/docs/api/checkout-ui-extensions/components) [ReferenceComponents](https://shopify.dev/docs/api/checkout-ui-extensions/components) [![](https://shopify.dev/images/icons/32/gear.png)![](https://shopify.dev/images/icons/32/gear-dark.png)](https://shopify.dev/docs/api/checkout-ui-extensions/configuration) [ReferenceConfiguration](https://shopify.dev/docs/api/checkout-ui-extensions/configuration) [![](https://shopify.dev/images/icons/32/tutorial.png)![](https://shopify.dev/images/icons/32/tutorial-dark.png)](https://shopify.dev/apps/checkout) [LearnTutorials](https://shopify.dev/apps/checkout)