--- title: Attributes description: The API for interacting with cart and checkout attributes. api_version: 2025-04 api_name: checkout-ui-extensions source_url: html: https://shopify.dev/docs/api/checkout-ui-extensions/2025-04/apis/attributes md: https://shopify.dev/docs/api/checkout-ui-extensions/2025-04/apis/attributes.md --- # AttributesAPI The API for interacting with cart and checkout attributes. ## StandardApi The base API object provided to `purchase` extension targets. * attributes StatefulRemoteSubscribable\ required The custom attributes left by the customer to the merchant, either in their cart or during checkout. ### Attribute * key The key for the attribute. ```ts string ``` * value The value for the attribute. ```ts string ``` ```ts export interface Attribute { /** * The key for the attribute. */ key: string; /** * The value for the attribute. */ value: string; } ``` ## CheckoutApi The API object provided to `purchase.checkout` extension targets. * applyAttributeChange (change: AttributeChange) => Promise\ required Performs an update on an attribute attached to the cart and checkout. If successful, this mutation results in an update to the value retrieved through the [`attributes`](https://shopify.dev/docs/api/checkout-ui-extensions/apis/attributes#standardapi-propertydetail-attributes) 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) `attributes.canUpdateAttributes` is false, or the buyer is using an accelerated checkout method, such as Apple Pay, Google Pay, or Meta Pay. ### AttributeChange ```ts AttributeUpdateChange | AttributeRemoveChange ``` ### AttributeUpdateChange Updates an attribute on the order. If an attribute with the provided key does not already exist, it gets created. * key Key of the attribute to add or update ```ts string ``` * type The type of the \`AttributeUpdateChange\` API. ```ts "updateAttribute" ``` * value Value for the attribute to add or update ```ts string ``` ```ts export interface AttributeUpdateChange { /** * The type of the `AttributeUpdateChange` API. */ type: 'updateAttribute'; /** * Key of the attribute to add or update */ key: string; /** * Value for the attribute to add or update */ value: string; } ``` ### AttributeRemoveChange Removes an attribute on the order if an attribute with the provided key already exists. * key Key of the attribute to remove ```ts string ``` * type The type of the \`AttributeRemoveChange\` API. ```ts "removeAttribute" ``` ```ts export interface AttributeRemoveChange { /** * The type of the `AttributeRemoveChange` API. */ type: 'removeAttribute'; /** * Key of the attribute to remove */ key: string; } ``` ### AttributeChangeResult ```ts AttributeChangeResultSuccess | AttributeChangeResultError ``` ### AttributeChangeResultSuccess The returned result of a successful update to an attribute. * type The type of the \`AttributeChangeResultSuccess\` API. ```ts "success" ``` ```ts export interface AttributeChangeResultSuccess { /** * The type of the `AttributeChangeResultSuccess` API. */ type: 'success'; } ``` ### AttributeChangeResultError The returned result of an unsuccessful update to an attribute with a message detailing the type of error that occurred. * 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 \`AttributeChangeResultError\` API. ```ts "error" ``` ```ts export interface AttributeChangeResultError { /** * The type of the `AttributeChangeResultError` 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​Attribute​Change() Returns a function to mutate the `attributes` property of the checkout. ### Returns * (change: AttributeChange) => Promise\ ### AttributeChange ```ts AttributeUpdateChange | AttributeRemoveChange ``` ### AttributeUpdateChange Updates an attribute on the order. If an attribute with the provided key does not already exist, it gets created. * key Key of the attribute to add or update ```ts string ``` * type The type of the \`AttributeUpdateChange\` API. ```ts "updateAttribute" ``` * value Value for the attribute to add or update ```ts string ``` ```ts export interface AttributeUpdateChange { /** * The type of the `AttributeUpdateChange` API. */ type: 'updateAttribute'; /** * Key of the attribute to add or update */ key: string; /** * Value for the attribute to add or update */ value: string; } ``` ### AttributeRemoveChange Removes an attribute on the order if an attribute with the provided key already exists. * key Key of the attribute to remove ```ts string ``` * type The type of the \`AttributeRemoveChange\` API. ```ts "removeAttribute" ``` ```ts export interface AttributeRemoveChange { /** * The type of the `AttributeRemoveChange` API. */ type: 'removeAttribute'; /** * Key of the attribute to remove */ key: string; } ``` ### AttributeChangeResult ```ts AttributeChangeResultSuccess | AttributeChangeResultError ``` ### AttributeChangeResultSuccess The returned result of a successful update to an attribute. * type The type of the \`AttributeChangeResultSuccess\` API. ```ts "success" ``` ```ts export interface AttributeChangeResultSuccess { /** * The type of the `AttributeChangeResultSuccess` API. */ type: 'success'; } ``` ### AttributeChangeResultError The returned result of an unsuccessful update to an attribute with a message detailing the type of error that occurred. * 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 \`AttributeChangeResultError\` API. ```ts "error" ``` ```ts export interface AttributeChangeResultError { /** * The type of the `AttributeChangeResultError` 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​Attributes() Returns the proposed `attributes` applied to the checkout. ### Returns * Attribute\[] | undefined ### Attribute * key The key for the attribute. ```ts string ``` * value The value for the attribute. ```ts string ``` ```ts export interface Attribute { /** * The key for the attribute. */ key: string; /** * The value for the attribute. */ value: string; } ``` ## use​Attribute​Values([keys](#useattributevalues-propertydetail-keys)​) Returns the values for the specified `attributes` applied to the checkout. ### Parameters * keys string\[] required An array of attribute keys. ### Returns * (string | undefined)\[] ### Examples * #### Attribute values ##### React ```jsx import { Text, reactExtension, useAttributeValues, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { const [buyerSelectedFreeTShirt, tshirtSize] = useAttributeValues([ 'buyerSelectedFreeTShirt', 'tshirtSize', ]); if (Boolean(buyerSelectedFreeTShirt) === true) { return ( You selected a free t-shirt, size:{' '} {tshirtSize} ); } return null; } ``` ##### JavaScript ```js import { extension, Text, } from '@shopify/ui-extensions/checkout'; export default extension( 'purchase.checkout.block.render', (root, {attributes}) => { attributes.subscribe(() => { renderUI(); }); function renderUI() { const buyerSelectedFreeTShirt = attributes.current?.find( (attr) => attr.key === 'buyerSelectedFreeTShirt', )?.value; const tshirtSize = attributes.current?.find( (attr) => attr.key === 'tshirtSize', )?.value; if ( Boolean(buyerSelectedFreeTShirt) === true ) { root.replaceChildren( root.createComponent( Text, undefined, `You selected a free t-shirt, size: ${tshirtSize}`, ), ); } else { root.replaceChildren(); } } renderUI(); }, ); ``` ## Examples Applying changes to attributes You can add or remove cart and checkout attributes by using the `applyAttributeChange` API. ### Examples * #### Applying changes to attributes ##### Description You can add or remove cart and checkout attributes by using the \`applyAttributeChange\` API. ##### React ```jsx import { reactExtension, BlockStack, Button, Text, useAttributeValues, useApplyAttributeChange, useInstructions, } from '@shopify/ui-extensions-react/checkout'; export default reactExtension( 'purchase.checkout.block.render', () => , ); function Extension() { const [giftWrapValue] = useAttributeValues([ 'giftWrap', ]); const giftWrap = Boolean(giftWrapValue); const applyAttributeChange = useApplyAttributeChange(); const instructions = useInstructions(); async function toggleGiftWrap() { const result = giftWrap ? await applyAttributeChange({ type: 'removeAttribute', key: 'giftWrap', }) : await applyAttributeChange({ type: 'updateAttribute', key: 'giftWrap', value: 'true', }); if (result.type === 'error') { console.error(result.message); } } return ( Gift wrapping:{' '} {giftWrap ? 'Added' : 'Not set'} ); } ``` ##### JavaScript ```js import { extension, BlockStack, Button, Text, } from '@shopify/ui-extensions/checkout'; export default extension( 'purchase.checkout.block.render', ( root, { attributes, instructions, applyAttributeChange, }, ) => { let giftWrap = false; const text = root.createComponent(Text); const button = root.createComponent(Button, { onPress: async () => { const result = giftWrap ? await applyAttributeChange({ type: 'removeAttribute', key: 'giftWrap', }) : await applyAttributeChange({ type: 'updateAttribute', key: 'giftWrap', value: 'true', }); if (result.type === 'error') { console.error(result.message); } }, }); const blockStack = root.createComponent( BlockStack, { spacing: 'tight', }, [text, button], ); attributes.subscribe(updateUI); instructions.subscribe(updateUI); function updateUI() { giftWrap = Boolean( attributes.current?.find( (attr) => attr.key === 'giftWrap', )?.value, ); text.replaceChildren( `Gift wrapping: ${giftWrap ? 'Added' : 'Not set'}`, ); button.updateProps({ disabled: !instructions.current?.attributes ?.canUpdateAttributes, }); button.replaceChildren( giftWrap ? 'Remove gift wrap' : 'Add gift wrap', ); } updateUI(); root.append(blockstack); }, ); ``` ## 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)