--- title: Storage API description: >- The Storage API lets you persist key-value data scoped to the customer across sessions. Use this API to store customer preferences, dismissed states, or other lightweight data that should survive navigation and return visits. api_version: 2026-04 api_name: customer-account-ui-extensions source_url: html: >- https://shopify.dev/docs/api/customer-account-ui-extensions/latest/target-apis/platform-apis/storage-api md: >- https://shopify.dev/docs/api/customer-account-ui-extensions/latest/target-apis/platform-apis/storage-api.md --- # Storage API The Storage API lets you persist key-value data scoped to the customer across sessions. Use this API to store customer preferences, dismissed states, or other lightweight data that should survive navigation and return visits. ### Use cases * **Remember customer preferences**: Save choices like preferred language, display options, or notification settings so they persist across visits. * **Track dismissed content**: Store whether a customer has dismissed a promotional banner or onboarding message so it doesn't reappear. * **Cache lightweight data**: Store small pieces of data to reduce redundant API calls, such as a customer's loyalty tier or last-viewed order. ### Support Targets (24) ### Supported targets * [customer-account.​footer.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/footer#footer-render-after-) * [customer-account.​order-index.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-index-announcement-) * [customer-account.​order-index.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-index-block-) * [customer-account.​order-status.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#order-status-announcement-) * [customer-account.​order-status.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#order-status-block-) * [customer-account.​order-status.​cart-line-item.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#cart-line-item-render-after-) * [customer-account.​order-status.​cart-line-list.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#cart-line-list-render-after-) * [customer-account.​order-status.​customer-information.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#customer-information-render-after-) * [customer-account.​order-status.​fulfillment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/fulfillment-status#fulfillment-status-targets) * [customer-account.​order-status.​payment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/payments-and-returns#payments-and-returns-targets) * [customer-account.​order-status.​return-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/payments-and-returns#return-details-render-after-) * [customer-account.​order-status.​unfulfilled-items.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/fulfillment-status#unfulfilled-items-render-after-) * [customer-account.​order.​action.​menu-item.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-action-menu-item-) * [customer-account.​order.​action.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-action-) * [customer-account.​order.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/full-page#order-specific-full-page-) * [customer-account.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/full-page#customer-account-full-page-) * [customer-account.​profile.​addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-page-default-targets-) * [customer-account.​profile.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-announcement-) * [customer-account.​profile.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-block-) * [customer-account.​profile.​company-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#profile-page-b2b-targets-) * [customer-account.​profile.​company-location-addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-addresses-render-after-) * [customer-account.​profile.​company-location-payment.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-payment-render-after-) * [customer-account.​profile.​company-location-staff.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-staff-render-after-) * customer-account.​profile.​payment.​render-after ### Properties The [`shopify` global object](https://shopify.dev/docs/api/customer-account-ui-extensions/latest#target-apis-define-what-your-extension-does) provides key-value storage scoped to the customer. Access the following properties on `shopify` to read, write, and delete persistent data across sessions. * **storage** **Storage** **required** Key-value storage that persists across customer sessions for this extension target. Use this to store preferences, dismiss states, or cached data without requiring a backend call. ### Storage Key-value storage for a specific extension. Use storage to save preferences or cached data that should survive page reloads without requiring a backend call. Stored data is only available to this specific extension. The storage backend is implemented with \`localStorage\` and data persistence isn't guaranteed. * delete Deletes a previously stored value by key. ```ts (key: string) => Promise ``` * read Read and return a stored value by key. The stored data is deserialized from JSON and returned as its original type. Returns the stored value for the given key, or \`null\` when no value exists. Doesn't throw on a missing key. ```ts (key: string) => Promise ``` * write Write stored data for this key. The data must be serializable to JSON. ```ts (key: string, data: any) => Promise ``` Examples ### Examples * #### ##### Description Write a value to storage and read it back when the extension loads again. This example saves a locale preference using \`shopify.storage.write()\` and reads it when the extension loads with \`shopify.storage.read()\`. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useEffect, useState} from 'preact/hooks'; export default async () => { render(, document.body); }; function Extension() { const [preference, setPreference] = useState(null); useEffect(() => { async function loadPreference() { const stored = await shopify.storage.read('locale_pref'); if (stored) { setPreference(stored); } } loadPreference(); }, []); async function handleSave(value) { await shopify.storage.write( 'locale_pref', value, ); setPreference(value); } return ( {preference ? `Saved preference: ${preference}` : 'No preference saved'} handleSave('en-US')}> Set preference to en-US ); } ``` * #### ##### Description Remove a stored value when the customer resets a preference or state. This example tracks whether a promotion was dismissed and uses \`shopify.storage.delete()\` to clear the value when the customer wants to see it again. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useEffect, useState} from 'preact/hooks'; export default async () => { render(, document.body); }; function Extension() { const [dismissed, setDismissed] = useState(false); useEffect(() => { async function checkDismissed() { const value = await shopify.storage.read('promo_dismissed'); if (value === 'true') { setDismissed(true); } } checkDismissed(); }, []); async function handleDismiss() { await shopify.storage.write( 'promo_dismissed', 'true', ); setDismissed(true); } async function handleReset() { await shopify.storage.delete( 'promo_dismissed', ); setDismissed(false); } if (dismissed) { return ( Show promotion again ); } return ( Get 20% off your next order. Dismiss ); } ``` * #### ##### Description Check storage on load to decide whether to show a promotional banner. When the customer dismisses it, write to storage so it stays hidden on future visits. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useEffect, useState} from 'preact/hooks'; export default async () => { render(, document.body); }; function Extension() { const [dismissed, setDismissed] = useState(true); useEffect(() => { async function checkDismissed() { const value = await shopify.storage.read('promo_dismissed'); setDismissed(value === 'true'); } checkDismissed(); }, []); async function handleDismiss() { await shopify.storage.write( 'promo_dismissed', 'true', ); setDismissed(true); } if (dismissed) { return null; } return ( Use code FREESHIP at checkout. ); } ``` *** ## Best practices * **Store only small values**: Keep stored data lightweight. Storage is intended for simple key-value pairs like preferences and flags, not large datasets. * **Use descriptive keys**: Name your storage keys clearly (for example, `promo_dismissed` or `locale_pref`) so their purpose is obvious and conflicts with other extensions are unlikely. * **Handle missing values gracefully**: Always check for `null` or `undefined` when reading from storage, since the value may not exist on the customer's first visit. * **Don't store sensitive data**: Storage isn't encrypted. Don't store personal information, tokens, or anything that could compromise customer privacy. *** ## Limitations * Storage is scoped per customer and per extension. You can't share data between different extensions or access another customer's stored values. * On the pre-authenticated Order status page, storage is scoped to the customer associated with the order, not the browsing session. * All values are stored as strings. You must serialize and deserialize complex types (like JSON objects). ***