Admin, installation, and OAuth performance
These guidelines apply to apps in the Shopify admin only.
Improve your app's loading performanceAnchor link to section titled "Improve your app's loading performance"
Loading performance is an important part of the user experience when using apps in the Shopify admin. When your app is slow to load, it dissuades users from adopting it, increases bounce rates, and decreases overall usage.
You can also improve your app's loading experience by minimizing visual noise, such as layout shifts, and clearly indicating loading progress. As a result, users will perceive your app as faster and more responsive, even if the loading time doesn't change. Refer to the Polaris best practices for loading for a complete guide on designing a high-quality experience.
Measure your app's loading performanceAnchor link to section titled "Measure your app's loading performance"
Shopify uses Web Vitals to measure your app's performance in the Shopify admin. Each time a user loads your app, we gather and save the Web Vitals metrics in order to better understand the user experience. To learn more about Web Vitals, you can refer to the introduction on web.dev
To measure your app's performance, we recommend adding Web Vitals to your app, capturing the performance with an analytics tool, and analyzing the aggregated data from user visits to your app. Though measuring Web Vitals on your device can be a useful tool for debugging issues, the data can differ significantly from what users experience when they use your app. To ensure that you provide users with an outstanding app experience, you should measure and monitor user loading experiences with your app as well.
The web-vitals package used by Shopify measures your app's performance each time a merchant launches your app through any route. If you use another tool to measure your page's performance, then it might take measurements more frequently. For example, some tools might measure the performance of each navigation between pages of your app. This can cause discrepancies between the values displayed in the Partner Dashboard and the metrics gathered by these tools.
To add Web Vitals to your app, install it from npm or load the package from a CDN.
Then, you can import the core Web Vitals metrics and call each function to log the resulting metrics to your own analytics service. Detailed usage information and additional diagnostic tools can be found on the web-vitals GitHub page.
Largest Contentful PaintAnchor link to section titled "Largest Contentful Paint"
Largest Contentful Paint (LCP) measures the time from when a user begins loading your page to when the largest image or block of text is displayed. It tracks how quickly your app can display its main content to users.
First Input DelayAnchor link to section titled "First Input Delay"
First Input Delay (FID) measures your app responsiveness to users' input. It measures the time from when a user interacts with your page to when your app begins processing the response to that interaction.
Cumulative Layout ShiftAnchor link to section titled "Cumulative Layout Shift"
Cumulative Layout Shift (CLS) measures your app's visual stability. Unstable user interfaces can be frustrating for users, especially when an element, such as a button, that they're trying to interact with moves suddenly. Cumulative Layout Shift quantifies these kinds of disruptive experiences so you can identify and remove them.
Enable optimized loading on mobile devicesAnchor link to section titled "Enable optimized loading on mobile devices"
By default, the Shopify Mobile app opens apps in an iFrame that's hosted from the Shopify admin. Each time an app is launched, the Shopify admin site must be re-loaded, which adds a significant amount of time to the app's load. With optimized loading enabled, the Shopify Mobile app loads the app directly inside of a native WebView, which significantly reduces the load time.
Load Shopify App Bridge from your app bundle for redirectsAnchor link to section titled "Load Shopify App Bridge from your app bundle for redirects"
Shopify offers an option to load Shopify App Bridge from Shopify CDN. However, for optimal performance, you should load App Bridge from your app bundle instead. Loading Shopify App Bridge from your app bundle increases the chance that the user's browser can access this code from the cache rather than downloading it. This can make your app more performant.
For an example of loading Shopify App Bridge from the app bundle, refer to this page in the Node app template.
Optimize your OAuth flowAnchor link to section titled "Optimize your OAuth flow"
Because OAuth is the first interaction that users have with your app UI, you should make sure that it's a positive experience. Follow these best practices for optimizing your OAuth performance to make your app authorization process smoother, faster, and more polished.
If you have an existing OAuth flow, then you can update your embedded app OAuth flow to follow these best practices.
Shopify offers app templates that already have OAuth implemented, and API libraries that include methods that simplify the implementation process. Using these templates or libraries helps to ensure that your implementation is complete, and that your app follows our OAuth best practices that are outlined here. You can build an app using a Shopify app template by initializing an app using Shopify CLI. For more information, refer to Create an app.
If you don't want to use an app template, then you can use the same API libraries that the templates use to implement OAuth in your own app. To learn more, refer to Getting started with OAuth.
Perform a server-side redirect to your embedded appAnchor link to section titled "Perform a server-side redirect to your embedded app"
If your embedded app doesn't need to get a new OAuth token, and the app isn't being displayed in an iframe, then you should redirect the user to the embedded app URL so that they can view your app.
You should perform a server-side 3xx redirect to the embedded app URL, rather than a client-side redirect that uses Shopify App Bridge. A server-side redirect is faster, and avoids the multiple page loads that occur during an App Bridge redirect. These page loads appear as screen flicker to the user.
To learn when to perform this redirect, and how to build and redirect to the embedded app URL, refer to Getting started with OAuth.
Conditionally escape your embedded app iframeAnchor link to section titled "Conditionally escape your embedded app iframe"
For users to grant permission for your app to access sensitive data, your app needs to redirect to the OAuth grant screen:
If your app is rendered inside of an iframe, then the grant screen won't render due to
X-Frame-Options: DENY restriction on the page, so you need to escape the iframe before redirecting.
You should only attempt to escape the iframe if the iframe exists. This avoids unnecessary HTTP redirects and requests, which increase load time and can cause screen flicker. To detect the presence of an iframe, check the request query parameters for an
embedded parameter with a value of
For more information about detecting and escaping an iframe, refer to Getting started with OAuth.
Request new tokens before rendering the UI, and only when neededAnchor link to section titled "Request new tokens before rendering the UI, and only when needed"
Your app might need to request a new token for a store for the following reasons:
- Your app doesn't have a token for the shop.
- Your app uses online tokens and the token for that shop has expired.
- Your app has a token for that shop, but it was created before you rotated the app's secret.
- Your app has a token for that shop, but your app now requires scopes that differ from the scopes granted with that token.
If any of these conditions are true, then your app should request a new token by redirecting to the grant screen instead of your app UI. This avoids users having to load the app UI before being redirected to the OAuth grant screen.
If none of these conditions are true, then the app should avoid requesting new tokens. These requests increase the time the app takes to load.
For more information about this logic, and how to implement it using Shopify API libraries, refer to Getting started with OAuth.