Shopify 2026 in one page
What changes for apps that put code on Shopify storefronts, what the merchant has to do, what the app has to do, and the mistakes that cost the most. Platform knowledge only, from Shopify's own documentation and staff answers, checked in October 2026.
Three dates, not two
| Date | What happens |
|---|---|
| October 1, 2026 (already in effect) | scriptTagCreate and scriptTagUpdate return an error on every API version, and so do the REST equivalents. Pinning an older version does not defer it. The scriptTags query and scriptTagDelete keep working, so apps can still audit and clean up. |
| January 1, 2027 | The Admin API rejects non-expiring offline access tokens from public apps. Apps must move to expiring offline tokens with refresh tokens (90-day refresh). Otherwise merchants lose access to the app until they re-authenticate. The migration does not need a user session. |
| March 1, 2027 | Shopify stops injecting script tags on storefronts. Anything still loaded by a script tag stops running, without an error. After that date, leftover script tag records have no effect. |
Most people talk about March. January is the one that catches teams off guard, because it affects every public app, not only those with script tags. Also note that API version 2025-10 is already unsupported and becomes inaccessible on October 16, 2026.
Who does what
| The app | The merchant |
|---|---|
| Ships a theme app extension with an app embed block. It is versioned with the app, so one release reaches every store. | Switches the embed on in the theme editor. No app can do it for them: there is no API to activate an embed. |
Sends a deep link to the right theme (activateAppId={api_key}/{handle}), by theme ID. |
Switches it on again after changing themes: an embed is only active on the theme it was enabled on. |
Detects activation in two ways: shopify.app.extensions() in the admin (published theme only, no extra scopes) and config/settings_data.json read with read_themes. |
Approves cleanup of old code that was put directly into the theme. A public app cannot rewrite theme files without an exemption, so cleanup is manual, on a duplicated theme. |
| Verifies the embed actually runs, for example with a beacon from the storefront, before removing anything. | Decides what to do with legacy data, such as one-variant-per-country products, after checking orders. |
Deletes its own script tags with scriptTagDelete, one store at a time, and treats frozen (402), locked (423) and closed (404) stores as a pause, not as churn. |
|
| Migrates to expiring offline tokens before January 1, 2027. |
Prices by country with Markets
Some apps fake a local price with one variant per country. Once Shopify Markets is on, that breaks: Markets converts the "local" price again. In one test, a variant priced 15,999 for Mexico showed as 299,006 MXN.
The native replacement:
- The market's catalog. Create it if it is missing.
- A price list in the market's currency. The price list currency must match the market currency.
- Fixed prices with
priceListFixedPricesAdd, in batches of at most 250. Each call adds and replaces. - An audit with
productVariant.contextualPricing(context: {country}), which returns what Shopify will actually charge. Do not compute an international price from the base price.
Fixed prices are not converted or rounded. Charging in the buyer's local currency needs Shopify Payments or Adyen; rounding rules work only with Shopify Payments.
The mistakes that cost the most
- Treating "enabled" as "running". If a theme has
</body>inside a comment, app embeds can be switched on and silently never run. Verify on the storefront before removing anything. - Linking to
themes/current. Activation is per theme, and links to the current theme have opened the wrong theme before. Link by theme ID. - Removing the old script tag too early, or running both at once. Before March 1, a script tag and its replacement running together load the script twice; removing the tag before the embed runs leaves the store with nothing.
- Dropping
write_script_tagsfrom the app's scopes too soon. A store that re-authorizes without it can no longer be cleaned. Keep it until an audit reads zero tags everywhere. - Parsing
settings_data.jsonnaively. The file starts with a comment that breaksJSON.parse, andcurrentcan be a preset name. - Counting frozen, locked or closed stores as lost. They return 402, 423 or 404. Queue them separately and retry with backoff.
- Expecting bulk operations to solve scale. Bulk operations run per store. Across thousands of stores the real work is orchestration, one queue per store.
- Forgetting January 1. The token deadline comes before the script tag shutdown.
Official sources
- Script tag deprecation (changelog)
- Migrating storefront script tags
- Expiring offline access tokens required as of January 1, 2027
- Migrate to expiring offline access tokens
- Theme app extensions: configuration
- Theme app extensions: UX guidelines and deep links
- Migrate to theme app extensions
- App API:
shopify.app.extensions() scriptTagDelete(Admin GraphQL 2026-10)themeFilesDeleteand thewrite_themesexemption- Access scopes
- Response codes (402, 423, 404)
- Markets: catalogs
priceListCreateandpriceListFixedPricesAdd- Local currencies and payments
- Rounding
- Bulk operations: imports