All entries

June 5, 2026

c35914771ace11ebc861c8071cf7643a517651ba9348e4c493867fce12dd0924
Previous: ef8b61d3 Bundle: 90.2 KB

Navigation handler sets navigationVersion 2 on the shopify global and adds a history.pushState fallback for unresolved link navigations.

Highlights

  • The navigation system now sets Symbol.for('navigationVersion') to 2 on the global shopify object at initialization, advertising the active navigation protocol version.
  • When home-link click simulation cannot process a URL, a new fallback uses history.pushState and dispatches a popstate event to complete the navigation instead of calling the App Bridge navigate API.
  • When navigating via a home link, the target URL is now derived from the home link element's href attribute rather than the original destination URL.
2 files changed +29 -13

Infrastructure Changes

REPORT.md
+3 -3
@@ -1,6 +1,6 @@
# Shopify App Bridge — Unminification Report

Generated: 2026-05-30T08:46:14.787Z
Generated: 2026-06-05T09:03:20.567Z

## Files

@@ -8,7 +8,7 @@ Generated: 2026-05-30T08:46:14.787Z
|------|------|-------|------|
| _bootstrap.js | 29.2KB | 1013 | Infrastructure |
| _remote-ui.js | 6.0KB | 255 | Infrastructure |
| _utilities.js | 72.4KB | 2705 | Infrastructure |
| _utilities.js | 72.9KB | 2721 | Infrastructure |
| _web-vitals.js | 11.6KB | 527 | Infrastructure |
| analytics.js | 211B | 11 | Module |
| app.js | 346B | 15 | Module |
@@ -46,7 +46,7 @@ Generated: 2026-05-30T08:46:14.787Z
| user.js | 940B | 37 | Module |
| visibility.js | 973B | 34 | Module |
| web-vitals.js | 1.8KB | 64 | Module |
| **Total** | **171.4KB** | **6510** | |
| **Total** | **171.9KB** | **6526** | |

## Pipeline Stages


modules/_utilities.js Truncated
+26 -10
@@ -913,22 +913,26 @@ function Vt(t, n) {
  return a.length === s.length && a.every(([t, n], e) => t === s[e][0] && n === s[e][1]);
}
const zt = ({ internalApiPromise, saveBarManager, rpcEventTarget }) => {
  if (self.shopify != null) {
    self.shopify[Symbol.for('navigationVersion')] = 2;
  }
  const abortController = new AbortController();
  async function o(e) {
  let o = false;
  async function r(e) {
    const { navigation: i } = await internalApiPromise;
    const url = new URL(e.detail.destination.url, location.href);
    const r = `${url.pathname}${url.search}`;
    if (saveBarManager.isSaveBarVisible) return;
    const a = Dt(r);
    const r = Dt(new URL(e.detail.destination.url, location.href));
      (e.detail.destination.topFramePath === '/' &&
        qt().find((t) => ((t.rel ?? t.getAttribute('rel') ?? '') + '').includes('home')));
    const { pathname: c, search: u } = a;
    if (a) {
    if (s) {
      const { pathname: t, search: n } = Dt(a.getAttribute('href') ?? r);
      s[SIMULATING_CLICK] = true;
      let e = false;
      parseUrl(s, (t) => {
      a[SIMULATING_CLICK] = true;
      parseUrl(a, (o) => {
        e = true;
        if (
          (function (t) {
            const n = t.getAttribute('href');
@@ -936,22 +940,34 @@ const zt = ({ internalApiPromise, saveBarManager, rpcEventTarget }) => {
            const e = Dt(n);
            const i = t.getAttribute('target') ?? '_self';
            return e.origin === location.origin && i === '_self';
        ) {
          SHOPIFY_PROTOCOLS(() => i?.navigate?.(`app:${c}${u}`));
          SHOPIFY_PROTOCOLS(() => i?.navigate?.(`app:${t}${n}`));
        }
      });
      if (!e) {
        o = true;
      }
    } else {
      await i?.navigate?.(`app:${c}${u}`);
      const { pathname: t, search: n } = r;
      if (o) {
        const url = new URL(`${t}${n}`, location.href);
        history.pushState(null, '', `${url.pathname}${url.search}`);
        window.dispatchEvent(
          new PopStateEvent('popstate', {
            state: null,
          }),
        );
      } else await i?.navigate?.(`app:${t}${n}`);
    }
  }
  abortController.signal.addEventListener('abort', () => {
  });
  addEventListener('beforeunload', () => abortController.abort());
  addEventListener(

Diff truncated at 200 lines