Skip to main content

Migrate your app to Shopify App Bridge

If you have an app that uses a previous version of Shopify App Bridge (3.x.x or earlier), this guide explains how to upgrade to the latest Shopify App Bridge. The most significant change in Shopify App Bridge is how you access APIs.

Using React?

If you're using React components and hooks from @shopify/app-bridge-react, refer to the React migration guide for framework-specific instructions.



Anchor to Benefits of migrationBenefits of migration

When you migrate your app to use Shopify App Bridge, you can take advantage of the following improvements to the developer experience:

Anchor to Simplified configurationSimplified configuration

Shopify App Bridge simplifies the configuration process. Apps no longer need complex initialization or the host config. Instead, they only need to provide their API key to the app-bridge.js script.

The app-bridge.js script automatically keeps itself up to date, so you can access new Shopify App Bridge APIs as soon as they're released.

The latest version of Shopify App Bridge embraces the web platform and web standards, so you can use web APIs you're already familiar with. For more information about the motivation behind App Bridge, refer to Shopify's platform is the Web platform.

Take advantage of the new Direct API access feature. You can make requests to the Admin API directly from your app using the standard web fetch API. For more information about Direct API access, refer to the documentation.

Anchor to Modals with custom contentModals with custom content

Add modals to your app with custom content using web components or React components from Shopify App Bridge. This enables you to create rich modal experiences that render directly in the Shopify admin. These modals are fast too, because they're preloaded.


Anchor to Step 1: Add the ,[object Object], script tagStep 1: Add the app-bridge.js script tag

Include the app-bridge.js script tag in your app. Replace %SHOPIFY_API_KEY% with your app's client ID. This configures your app to use Shopify App Bridge.

The app-bridge.js script is CDN-hosted, so your app always gets the latest version of it.

index.html

<head>
<meta name="shopify-api-key" content="%SHOPIFY_API_KEY%" />
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
</head>

Anchor to Step 2: Upgrade your Shopify App Bridge dependencyStep 2: Upgrade your Shopify App Bridge dependency

Install or upgrade the Shopify App Bridge dependency for your framework with your package manager.

Terminal

npm install @shopify/app-bridge@latest
yarn add @shopify/app-bridge@latest
pnpm add @shopify/app-bridge@latest
Framework-specific packages

If you're using a framework-specific package like @shopify/app-bridge-react, upgrade that package to the latest version as well.


Anchor to Step 3: Remove the initialization setupStep 3: Remove the initialization setup

In previous versions of App Bridge, you needed to manually initialize and configure App Bridge. This is no longer needed, as all the setup for Shopify App Bridge is done through the app-bridge.js script tag that you added in step 1.

Remove all manual App Bridge initialization code from your app:

Initialization setup

3.x.x

import createApp from '@shopify/app-bridge';

const config = {
apiKey: 'YOUR_API_KEY',
host: 'YOUR_HOST',
forceRedirect: true
};

const app = createApp(config);

Current

// No initialization needed - handled by app-bridge.js script
// Access App Bridge APIs through the shopify global variable

Anchor to Step 4: Update App Bridge APIsStep 4: Update App Bridge APIs

The following App Bridge APIs have been refactored or replaced. Review and update your code as described:

The Modal API allows you to display an overlay that prevents interaction with the rest of the app until dismissed. Shopify App Bridge now uses Polaris web components: <s-modal> for inline content and <s-app-window> for modals with separate routes.

The modal implementation has been simplified. Here are the key changes:

  • Web component based: Modals now use <s-modal> for inline content or <s-app-window> for src-based modals instead of imperative APIs.
  • Size configuration: Use the size attribute with values like 'small', 'large', or 'full-width'.
  • Title and content: Use the heading attribute for the modal title and add content as children.
  • Actions: Modal actions are handled through standard HTML buttons with slot attributes.
  • Auto-sizing: Modal auto-sizing is now automatic - no manual setup required.

Modal configuration

3.x.x

import {Modal} from '@shopify/app-bridge/actions';

const modalOptions = {
title: 'My modal',
message: 'Hello world!',
size: Modal.Size.Large,
primaryAction: {
content: 'Add Instagram',
onAction: handleChange
},
secondaryActions: [{
content: 'Learn more',
onAction: handleChange
}]
};

const myModal = Modal.create(app, modalOptions);
myModal.dispatch(Modal.Action.OPEN);

Current

<!-- For inline content -->
<s-modal id="my-modal" heading="My modal" size="large">
<s-text>Hello world!</s-text>
<s-button variant="primary" slot="primary-action" onclick="handleChange()">
Add Instagram
</s-button>
<s-button slot="secondary-actions" onclick="handleChange()">
Learn more
</s-button>
</s-modal>

<s-button command="--show" commandFor="my-modal">Open Modal</s-button>

Current (with src)

<!-- For external content (separate route) -->
<s-app-window id="my-modal" src="/modal-content">
</s-app-window>

<s-button command="--show" commandFor="my-modal">Open Modal</s-button>

Anchor to Communication with the parent pageCommunication with the parent page

In previous versions, you needed to use the Modal.Action.DATA action to communicate between the parent page and the modal.

For inline content modals: Since these render within your app's iframe, no special communication mechanism is needed - you can directly access your app's JavaScript context.

For src modals: Use the postMessage API to communicate with the parent page. Access postMessage through window.opener in the modal and through the modal's contentWindow in the parent page.

Communication with src modals

3.x.x

import {Modal} from '@shopify/app-bridge/actions';

// In modal page (loaded via src)
function sendMessageFromModal() {
app.dispatch(Modal.data({message: 'Hi, this is the modal!'}));
}

// In parent page
app.subscribe(Modal.Action.DATA, (data) => {
console.log('Received message from modal: ', data.message);
});

Current

<!-- In parent page -->
<s-app-window id="my-app-window" src="/modal-page">
</s-app-window>

<s-button command="--show" commandFor="my-app-window">Open Modal</s-button>

<script>
// Listen for messages from modal
window.addEventListener('message', (ev) => {
console.log('Message received from modal:', ev.data);
});

// Send message to modal
function sendMessageToModal() {
const modal = document.getElementById('my-app-window');
modal.contentWindow.postMessage('Hi, this is the main app!', location.origin);
}
</script>

Current (modal page)

<!-- In modal page (loaded via src) -->
<script>
function sendMessageFromModal() {
window.opener.postMessage('Hi, this is the modal!', location.origin);
}

// Listen for messages from parent
window.addEventListener('message', (ev) => {
console.log('Message received in modal:', ev.data);
});
</script>

The TitleBar API allows you to populate a standardized title bar with button actions and navigation breadcrumbs. Title bars are now configured using the <s-page> component's title and action slots.

TitleBar configuration

3.x.x

import {TitleBar} from '@shopify/app-bridge/actions';

const titleBar = TitleBar.create(app, {
title: 'Hello world!',
primaryAction: {
content: 'Foo',
onAction: handleFooClick
},
secondaryActions: [{
content: 'Bar',
onAction: handleBarClick
}],
actionGroups: [{
title: 'More actions',
actions: [{
content: 'First grouped button',
onAction: handleFirstGroupedButtonClick
}]
}]
});

Current

<s-page title="Hello world!">
<s-button variant="primary" slot="primary-action" onclick="handleFooClick()">
Foo
</s-button>
<s-button slot="secondary-actions" onclick="handleBarClick()">
Bar
</s-button>
</s-page>

Breadcrumbs configuration

3.x.x

import {TitleBar} from '@shopify/app-bridge/actions';

const titleBar = TitleBar.create(app, {
title: 'Hello world!',
breadcrumbs: [{
content: 'Breadcrumb',
url: '/breadcrumb'
}]
});

Current

<s-page title="Hello world!">
<s-link slot="breadcrumb-actions" href="/breadcrumb">Breadcrumb</s-link>
</s-page>

The Navigation creates a navigation menu for your app. The navigation now uses the <s-app-nav> Polaris web component.

Navigation configuration

3.x.x

import {NavigationMenu} from '@shopify/app-bridge/actions';

const navigationMenu = NavigationMenu.create(app, {
items: [
{
label: 'Home',
destination: '/'
},
{
label: 'Templates',
destination: '/templates'
},
{
label: 'Settings',
destination: '/settings'
}
],
active: navigationMenu.items[0]
});

Current

<s-app-nav>
<s-link href="/">Home</s-link>
<s-link href="/templates">Templates</s-link>
<s-link href="/settings">Settings</s-link>
</s-app-nav>

The active link is automatically matched based on the current URL.

Anchor to Other APIs that we've replacedOther APIs that we've replaced

All other App Bridge actions from previous versions have been replaced by new APIs provided through the shopify global variable. Refer to the following table to learn about the API replacement:

Previous ActionNew API
ContextualSaveBarContextual Save Bar API
LoadingLoading API
PickerPicker API
ResourcePickerResourcePicker API
ToastToast API
FeaturesFeatures API
CartCart API
ClientUse the shopify global variable directly

Anchor to Step 5: Update API usageStep 5: Update API usage

After migrating your imports and configuration, you'll need to update how you interact with App Bridge APIs. Most App Bridge functionality now uses the shopify global variable for imperative APIs (like Toast, ResourcePicker) and web components for UI elements (like Modal, TitleBar).

Anchor to Accessing App Bridge APIsAccessing App Bridge APIs

The most significant change in Shopify App Bridge is how you access APIs. Instead of creating an app instance and dispatching actions, you now use web components for UI elements and the shopify global variable for imperative APIs:

Accessing APIs

3.x.x

import createApp from '@shopify/app-bridge';
import {Toast} from '@shopify/app-bridge/actions';

const app = createApp(config);

const toastOptions = {
message: 'Product saved',
duration: 5000
};
const toastNotice = Toast.create(app, toastOptions);
toastNotice.dispatch(Toast.Action.SHOW);

Current

// The shopify global variable is automatically available
// after including the app-bridge.js script

await shopify.toast.show('Product saved', {
duration: 5000
});

The following table shows how to replace previous App Bridge actions with new APIs:

Previous useNew API
app.getState()Various APIs , for example shopify.user() for user info
app.dispatch()Direct method calls on shopify object
app.subscribe()Event listeners on specific APIs
Authenticated fetchGlobal fetch automatically includes auth headers
History.Action.PUSHshopify.navigation.navigate()
Redirect.Action.APPshopify.navigation.navigate()
Redirect.Action.REMOTEwindow.open() or window.location.href

Anchor to Framework-specific considerationsFramework-specific considerations

If you're using a framework-specific package like @shopify/app-bridge-react, refer to that package's migration guide for framework-specific updates. The core concepts remain the same:

  1. Remove manual initialization
  2. Access APIs through the shopify global variable
  3. Use web standards where possible
  4. Let App Bridge handle authentication automatically

Was this page helpful?