---
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
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<void>
  ```

* 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
  <T = unknown>(key: string) => Promise<T>
  ```

* write

  Write stored data for this key. The data must be serializable to JSON.

  ```ts
  (key: string, data: any) => Promise<void>
  ```

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(<Extension />, 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 (
      <s-stack direction="block" gap="base">
        <s-text>
          {preference
            ? `Saved preference: ${preference}`
            : 'No preference saved'}
        </s-text>
        <s-button onClick={() => handleSave('en-US')}>
          Set preference to en-US
        </s-button>
      </s-stack>
    );
  }
  ```

* ####

  ##### 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(<Extension />, 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 (
        <s-button onClick={handleReset}>
          Show promotion again
        </s-button>
      );
    }

    return (
      <s-stack direction="block" gap="base">
        <s-banner heading="Special offer!">
          Get 20% off your next order.
        </s-banner>
        <s-button onClick={handleDismiss}>
          Dismiss
        </s-button>
      </s-stack>
    );
  }
  ```

* ####

  ##### 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(<Extension />, 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 (
      <s-banner
        heading="Free shipping on your next order"
        onDismiss={handleDismiss}
      >
        <s-text>
          Use code FREESHIP at checkout.
        </s-text>
      </s-banner>
    );
  }
  ```

***

## 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).

***
