---
title: Navigation API
description: >-
  The Navigation API provides web-standard navigation functionality for POS UI
  extensions, allowing you to navigate between URLs, manage navigation history,
  and handle navigation events within modal interfaces. The API is available
  globally as the `navigation` object and follows web platform standards.
api_version: 2026-07-rc
source_url:
  html: >-
    https://shopify.dev/docs/api/pos-ui-extensions/2026-07-rc/target-apis/platform-apis/navigation-api
  md: >-
    https://shopify.dev/docs/api/pos-ui-extensions/2026-07-rc/target-apis/platform-apis/navigation-api.md
---

# Navigation API

The Navigation API provides web-standard navigation functionality for POS UI extensions, allowing you to navigate between URLs, manage navigation history, and handle navigation events within modal interfaces. The API is available globally as the `navigation` object and follows web platform standards.

Each screen runs in its own isolated sandbox, so module-level variables and closures aren't shared across navigations. To pass data between screens, use the `state` option in `navigation.navigate()` or the [Storage API](https://shopify.dev/docs/api/pos-ui-extensions/2026-07-rc/target-apis/platform-apis/storage-api).

### Use cases

* **Multi-screen workflows:** Implement workflows with URL-based navigation and browser history support.
* **Wizard interfaces:** Build wizard-style interfaces allowing forward and backward navigation.
* **Deep linking:** Create deep-linkable modal states that can be bookmarked or shared.
* **Navigation events:** Handle navigation events to save progress or trigger cleanup.

### Properties

The `navigation` object provides navigation controls for extension modals. Access the following properties on `navigation` to navigate between screens, manage navigation history, and handle navigation events.

* **addEventListener**

  **(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void**

  **required**

  Registers an event listener for navigation events. The `currententrychange` event fires when the `currentEntry` property changes, such as when the user navigates to a different screen within the extension modal. Use to track navigation changes, update UI state based on the current location, or implement analytics for navigation patterns.

* **back**

  **() => void**

  **required**

  Navigates to the previous entry in the history list. Use for implementing back buttons, breadcrumb navigation, or allowing users to return to previous screens in multi-step workflows.

* **currentEntry**

  **NavigationHistoryEntry**

  **required**

  Returns a `NavigationHistoryEntry` object representing the location the user is currently navigated to. Use to access current URL, navigation state, or implement navigation-aware functionality based on the current location.

* **navigate**

  **(url: string, options?: NavigationNavigateOptions) => Promise\<void>**

  **required**

  Navigates to a specific URL, updating any provided state in the history entries list. Returns a promise that resolves when navigation is complete. Use for programmatic navigation between screens, implementing custom navigation controls, or deep-linking to specific modal states.

* **removeEventListener**

  **(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void**

  **required**

  Removes a previously registered event listener. The callback reference must match the one passed to `addEventListener`. Use to clean up event listeners when they are no longer needed, such as when a component unmounts or navigation tracking should be disabled.

### NavigationCurrentEntryChangeEvent

The event object for the \`currententrychange\` event, which fires when \`Navigation.currentEntry\` has changed due to navigation within the extension modal. Use to access information about the previous navigation entry when responding to navigation changes.

* from

  The \`NavigationHistoryEntry\` that was navigated away from. Use to access the previous URL, key, or state when tracking navigation transitions or implementing breadcrumb-style navigation.

  ```ts
  NavigationHistoryEntry
  ```

### NavigationHistoryEntry

Represents a single entry in the navigation history stack. Contains the URL and unique identifier for tracking navigation state and implementing history-based navigation.

* getState

  Returns a clone of the available state associated with this history entry. Use to retrieve navigation state data that was passed during navigation or to implement state-based navigation logic.

  ```ts
  () => unknown
  ```

* key

  A unique, UA-generated value that represents the history entry's slot in the entries list rather than the entry itself. Use for tracking navigation history or implementing navigation-based logic.

  ```ts
  string
  ```

* url

  The URL of this history entry. Returns \`null\` if no URL is associated with the entry. Use for URL-based navigation logic, deep-linking, or displaying current location information.

  ```ts
  string | null
  ```

### NavigationNavigateOptions

Specifies configuration options for navigation operations. Allows passing state data that persists across navigation transitions.

* state

  Developer-defined information to be stored in the associated \`NavigationHistoryEntry\` once the navigation is complete, retrievable using \`getState()\`. Use to pass data between navigation states or implement stateful navigation workflows.

  ```ts
  unknown
  ```

### Window

The global `window` object provides control over the extension modal lifecycle. Access these properties and methods directly through the global `window` object to manage the modal interface programmatically.

* **close**

  **{ (): void; (): void; }**

  **required**

  Closes the extension screen and dismisses the modal interface. Use to programmatically close the modal after completing a workflow, canceling an operation, or when user action is no longer required. This provides the same behavior as the user dismissing the modal through the UI.

Examples

### Examples

* ####

  ##### Description

  Create multi-screen workflows within your extension using web-standard navigation. This example demonstrates using \`navigation.navigate()\` to move between different screens in your modal interface. This enables complex multi-step processes with proper navigation history management.

  ##### jsx

  ```tsx
  import { render } from "preact";

  export default async () => {
    render(<Extension />, document.body);
  };

  const Extension = () => {
    const url = navigation.currentEntry.url;

    if (url?.includes("ScreenTwo")) {
      return (
        <s-page heading="Screen Two Title">
          <s-scroll-box>
            <s-button onClick={() => navigation.navigate("ScreenOne")}>
              Navigate to Screen One
            </s-button>
            <s-button onClick={() => navigation.back()}>Go back</s-button>
          </s-scroll-box>
        </s-page>
      );
    }

    return (
      <s-page heading="Screen One Title">
        <s-scroll-box>
          <s-button onClick={() => navigation.navigate("ScreenTwo")}>
            Navigate to Screen Two
          </s-button>
          <s-button onClick={() => navigation.back()}>Go back</s-button>
        </s-scroll-box>
      </s-page>
    );
  };
  ```

* ####

  ##### Description

  Navigate to native POS screens from your extension using deep link URIs. This example shows how to use \`navigation.navigate()\` with POS screen URIs to transition to core POS functionality like cart, product details, or order screens. This enables direct transitions between your extension and native POS features.

  ##### jsx

  ```tsx
  import {render} from 'preact';

  export default async () => {
    render(<Extension />, document.body);
  };

  function Extension() {
    /**
     * Available POS native screen uris:
     * - `shopify:point-of-sale/products/123` to present product details.
     * - `shopify:point-of-sale/products/123/variants/456` to present product variant details.
     * - `shopify:point-of-sale/customers/123` to present customer details.
     * - `shopify:point-of-sale/orders/123` to present order details.
     * - `shopify:point-of-sale/draft_orders/123` to present draft order details.
     * - `shopify:point-of-sale/staff/123` to present staff details.
     */
    return (
      <s-page heading="POS native screen navigation">
        <s-scroll-box>
          <s-button
            onClick={() => {
              // Use the navigate API to open a POS native resource details screen.
              // A permissions dialog will block navigation if they do not have the staff permissions to view the screen.
              navigation.navigate('shopify:point-of-sale/orders/123');
            }}
          >
            View order
          </s-button>
        </s-scroll-box>
      </s-page>
    );
  }
  ```

* ####

  ##### Description

  Share data between screens using navigation state parameters. This example demonstrates using the \`state\` option in \`navigation.navigate()\` to pass data when navigating. This enables screens to receive context and maintain workflow continuity across navigation transitions.

  ##### jsx

  ```tsx
  import { render } from "preact";

  export default async () => {
    render(<Extension />, document.body);
  };

  const Extension = () => {
    const url = navigation.currentEntry.url;
    
    /** @type {{ firstParam?: string; secondParam?: string }} */
    const state = navigation.currentEntry.getState();

    if (url?.includes("ScreenTwo")) {
      return (
        <s-page heading="Screen Two Title">
          <s-scroll-box>
            <s-text>First Param: {state.firstParam}</s-text>
            <s-text>Second Param: {state.secondParam}</s-text>
          </s-scroll-box>
        </s-page>
      );
    }

    return (
      <s-page heading="Screen One Title">
        <s-scroll-box>
          <s-button onClick={() => navigation.navigate("ScreenTwo", { state: { firstParam: "test", secondParam: "test2" } })}>
            Navigate to Screen Two
          </s-button>
          <s-button onClick={() => navigation.back()}>Go back</s-button>
        </s-scroll-box>
      </s-page>
    );
  };
  ```

***

## Best practices

* **Use URL-based navigation:** Implement URL-based navigation patterns that allow for deep-linking, bookmarking, and intuitive browser-like navigation within your modal workflows.
* **Manage navigation state effectively:** Use the `state` parameter in navigation options to pass data between screens, maintaining workflow context and user progress across navigation changes.

***

## Limitations

* The Navigation API is only available in action (modal) targets and can't be used in action (menu item), block, or tile targets that don't support multi-screen navigation.
* Navigation state is limited to serializable data and can't contain functions, complex objects, or circular references.

***
