Apps can now subscribe to events for Metaobject , MetafieldDefinition , MetaobjectDefinition , and InventoryTransfer . Apps can also subscribe to targeted metafield changes on InventoryTransfer . By subscribing to these topics, your app can react directly to changes in custom content, custom data definitions, and inventory transfer workflows. Apps can target the fields that matter in triggers, query the resource that changed, and avoid subscribing to broader updates just to diff payloads in their event handler. For example, the following subscription delivers when the value of the title field changes. The query uses the trigger's metaobjectId to fetch that Metaobject and field. [events] api_version = "unstable" [[events.subscription]] handle = "metaobject-event" topic = "Metaobject" actions = ["update"] triggers = [ "metaobject(type: 'books').field(key: 'title').value" ] uri = "/api/events" query = """ query MetaobjectTitleValue($metaobjectId: ID!, $fieldKey: String!) { metaobject(id: $metaobjectId) { id type handle field(key: $fieldKey) { key value } } } """ The complete payload body when the title field changes is as follows: { "topic": "Metaobject", "action": "update", "handle": "metaobject-title-value", "data": { "metaobject": { "id": "gid://shopify/Metaobject/123123", "type": "books", "handle": "metaobject-event", "field": { "key": "title", "value": "My Book Title" } } }, "fields_changed": [ "metaobject[id: 'gid://shopify/Metaobject/123123', type: 'books'].field[key: 'title'].value" ], "query_variables": { "metaobjectId": "gid://shopify/Metaobject/123123", "metaobjectType": "books", "fieldKey": "title" } } Events remain available in the unstable API version during developer preview. For topics that are not supported yet, continue using webhooks alongside Events. Learn more about: Events: https://shopify.dev/docs/apps/build/events Metaobject: https://shopify.dev/docs/api/events/latest/metaobject MetafieldDefinition: https://shopify.dev/docs/api/events/latest/metafield-definition MetaobjectDefinition: https://shopify.dev/docs/api/events/latest/metaobject-definition InventoryTransfer: https://shopify.dev/docs/api/events/latest/inventory-transfer
Read more →When you edit a theme in the Shopify admin, the commit Shopify pushes to your connected branch now includes the editor's name in the body: Update from Shopify for theme Dawn Committed from shop: Snowdevil Theme last edited by: Bob Bobsen The name is plain text in the commit body. The commit author is still the shopify bot, so git blame and the commit avatar don't change. Edits saved within about 10 seconds of each other are batched into one commit, and the body names whoever saved last. If the theme has no recorded editor, the body lists only the shop name, as before. Learn more about the Shopify GitHub app in our developer documentation .
Read more →Starting October 1, 2026, the scriptTagCreate and scriptTagUpdate mutations will return an user error, and the ScriptTag REST Admin API resource will reject POST and PUT . The deprecation applies to all API versions, including older ones, so pinning won't defer it. On March 1, 2027, Shopify will stop injecting script tags into storefronts. Storefronts are the last place script tags still run, since they already stopped working on the Order status page . If your app uses a script tag to load JavaScript onto a store, then you need to replace it before then. What's changing A script tag loads JavaScript on a storefront without any changes to theme code. After March 1, 2027, Shopify won't inject those scripts, so script tags will stop loading JavaScript on storefronts. The scriptTags query and the scriptTagDelete mutation keep working, so you can audit and clean up your existing script tags. What you need to do Replace each script tag with an app embed block , which you ship in a theme app extension. App users activate app embed blocks in the theme editor. If a script only collects analytics or conversion data, then use a web pixel instead, which needs no action from the app user. Who's affected Apps that create script tags with a display_scope of online_store . Script tags with a display_scope of order_status are covered by an earlier deprecation. Refer to Order status script tags . Deprecation timeline October 1, 2026 : scriptTagCreate and scriptTagUpdate will return an user error. Existing script tags will keep running. March 1, 2027 : Shopify will stop injecting script tags into storefronts. Migration path App embed blocks replace script tags, and you ship them in a theme app extension. Refer to Storefront script tags to learn more. Related docs Storefront script tags Migrate to theme app extensions
Read more →When Sidekick invokes an app intent declared on the admin.app.intent.link extension target, the Shopify admin now navigates the merchant to your extension's url as a full page, matching how Shopify's own admin intents behave. Previously, the same intent always opened in an overlay on top of the page the merchant was already on. This is live for all shops, isn't gated by API version, and doesn't require any changes to your extension's configuration, intent schema, or tools. Extensions that use the admin.app.intent.render target aren't affected. What changed App intents support different presentations. Until now, every app intent appeared as an intent modal, an overlay on top of the merchant's current page that kept them in the Sidekick flow. admin.app.intent.link intents now use a full-page navigation instead, which brings app intents in line with how admin intents, the intents that launch Shopify-native editors, are already presented. It also matches the documented behavior of the target, which navigates the merchant to a URL in your app for actions that work best on a page you already render. For implementation details, see Use extensions to surface app actions . There's one case where the overlay is still used: if the merchant has unsaved changes on their current page, the intent opens in a modal instead of navigating away, so their in-progress work isn't lost. Your extension doesn't need to handle these cases differently — the same route, payload, and tools are used in both presentations. The contract between Sidekick and your app is unchanged. Your route still reads the invocation payload from shopify.intents.request.value , a live signal that's null when your app isn't running inside an intent workflow and updates whenever an intent is invoked. You still register tool handlers with shopify.tools.register from the route the url opens, and you still resolve the intent with shopify.intents.response.ok() , shopify.intents.response.error() , or shopify.intents.response.closed() . Note: Extensions that target admin.app.intent.render currently render inline as an overlay, so a UI extension app action behaves the same as before. If you noticed this change before this post and reported it as a regression, the new behavior is expected. The type , target , and url on your extension continue to work as declared. Who's affected This applies to apps with an admin_link extension whose targeting includes admin.app.intent.link . It applies on every API version and every store, and there's no feature flag, scope, or setting to opt in or out. These aren't affected: Extensions targeting admin.app.intent.render . Admin intents your app invokes with intents.invoke() to launch Shopify-native editors. Those are a separate system and their presentation hasn't changed. Apps that don't declare app intents. If your app declares both targets, only the admin.app.intent.link intents change. Why this matters Merchants now land on the real page in your app, at the URL you declared, with your own layout and navigation instead of a constrained overlay. For the actions admin.app.intent.link is designed for, the merchant now works directly on the page your app already renders. What to do No action is required to keep your extension working. The declaration this change affects is the admin.app.intent.link target in your shopify.extension.toml : [[extensions.targeting]] target = "admin.app.intent.link" url = "/app/campaigns/{id}/edit" tools = "./tools.json" instructions = "./instructions.md" This example shows a typical admin.app.intent.link configuration: the target, the route the admin opens, and the files that define tools and instructions. You don't need to change this structure for the new behavior. If your app has no extension with that target, nothing changes for you. If it does, verify that the route behind url works as a standalone page: Confirm the route renders correctly at full width. Layout that assumed a narrow overlay may need adjusting. The route should also still render correctly in a modal, since that's the presentation merchants with unsaved changes will see. Confirm the route reads the invocation payload from shopify.intents.request.value . Because it's a live signal, you can also subscribe to it to react when the request changes. Confirm the route calls shopify.tools.register when it mounts, so Sidekick can invoke your tools while the merchant is on the page. Confirm you resolve the intent when the merchant finishes, fails, or cancels. Test in a development store with shopify app dev , then ask Sidekick to perform the action. You'll know the update worked when the admin navigates to your declared url with your schema's values substituted into the path rather than a literal {id} , your tools respond while the page is open, and Sidekick reports the result after you resolve the intent. To see the modal fallback, start editing a form in the admin and invoke the action before saving. Related docs Build Sidekick app extensions Intents API reference Tools API reference
Read more →The Hydrogen developer preview adds new capabilities to the toolkit and extends the ways developers can build Shopify storefronts: Cart session attribution: Carts and Customer Account sessions stay in step, so signed-in shoppers reach checkout with their saved details instead of a guest flow. Cart attributes: Attach order-wide data like gift messages to the cart, and per-line data like engraving text to the lines it belongs to. Standard page view events: Hydrogen storefronts used to report only the first page load, leaving client-side navigations invisible to analytics and performance tooling. Every navigation now emits a page view, matching how liquid themes report events. Shop Pay button without shop-js: The button used to render blank until Shopify's hosted script loaded. Hydrogen now renders it directly, so it shows up styled and clickable right away, before any JavaScript runs. Local HTTPS for Customer Account development: Test login flows on a trusted local hostname, without a tunnel or hand-rolled certificates. Pluggable logging: Set how much Hydrogen logs and forward warnings and errors to your own observability tooling. To get started, visit the Hydrogen developer preview documentation . For a detailed breakdown of this release, read the full release notes .
Read more →The shop_campaign_insights schema is now available in the ShopifyQL . Analytics and reporting apps can query Shop Campaigns performance data on behalf of authorized merchants using the existing shopifyqlQuery field with read_reports scope. Available data Campaign-level and segment-level metrics including ad spend, sales, orders, ROAS, average order value, and average customer acquisition cost. Data is available by campaign name, customer segment, and time dimensions from hourly to yearly in the merchant's shop timezone. How to get started Query shop_campaign_insights using the same shopifyqlQuery field you use for other ShopifyQL schemas. No new scopes or integration work required if you already query ShopifyQL. Schema reference: shop_campaign_insights Building with ShopifyQL ShopifyQL API reference Also new: Analytics Web Components let you embed Shop Campaigns metrics directly in your app UI using with no data storage required. The Analytics Annotations API lets you create annotations on merchant analytics charts (e.g., "campaign started," "budget changed").
Read more →The updateCart standard action now updates cart attributes, and a new shopify:cart:attributes-update event fires whenever an attributes update is initiated. Before this, changing an attribute meant calling the Storefront API yourself, and nothing told your app when one changed. The action now handles attributes like any other cart update, and the event fires whether your app, the theme, or another app made the change. It carries the full new set of attributes and a promise for the result, so you can update your UI right away and roll it back if the cart declines the change. Learn more in the event reference and the updated updateCart reference .
Read more →We're consolidating how in-progress inventory holds are represented. Inventory that was previously tracked under the reserved quantity state for draft orders, transfers, and shipments is being moved to the committed quantity state. This change aligns these holds with how order inventory is already represented, so that committed reflects all inventory that is spoken for but not yet fulfilled. What's changing For draft orders, transfers, and shipments, quantities that previously appeared under reserved will now appear under committed . This is a one-time data migration that applies only to active draft orders and open transfers/shipments that are still holding inventory when the change runs. Completed, cancelled, or already-released holds are not modified, because they no longer hold reserved inventory. What's not changing available and on_hand quantities are unaffected. Total inventory is unchanged, and quantities are only moving between two “unavailable” buckets. Both reserved and committed remain valid, queryable quantity names. No fields are removed or renamed. Sellable inventory ( available ) is not affected, so this does not change what buyers can purchase. What you may need to do If your app reads InventoryLevel.quantities(names: ["reserved"]) , expect reserved values to decrease for affected shops, with a corresponding increase in committed . If you currently rely on reserved to detect draft-order or transfer/shipment holds specifically, you should read committed instead going forward. No code changes are required to keep existing queries working; only the values shift between the two states. Reporting note Merchants using inventory adjustment reports (for example, reports that break out adjustments by inventory state) will see reserved values migrate to committed , plus a one-time correction entry when the migration runs. This correction only covers active draft orders and open transfers/shipments at the time of migration. on_hand and available totals are unchanged, and historical data before the migration remains as-is. Related docs InventoryLevel — the quantities(names: [...]) field: https://shopify.dev/docs/api/admin-graphql/latest/objects/InventoryLevel InventoryQuantity — the object returned per name: https://shopify.dev/docs/api/admin-graphql/latest/objects/InventoryQuantity
Read more →Online stores now expose WebMCP tools that AI agents can call. Agents can search your catalog, manage the shopper's cart, and go to checkout on the shopper's behalf, all in the tab they're looking at. The tools work through WebMCP , a proposed web standard that lets a page register tools with the browser. Without it, agents have to read every page's code and simulate clicks, which is slow and error-prone. The tools are live today on every Liquid storefront and on the Hydrogen developer preview . There's nothing to install or configure. Everything an agent does happens on the shopper's live session. Cart tools call the same standard storefront actions that apps use, so if your theme opens a cart drawer on updates, agents trigger it too. Here's what agents can call: Catalog: search_catalog , browse_store , get_product , and show_variant Cart: get_cart , update_cart , and cancel_cart Checkout and orders: proceed_to_checkout and manage_orders Other content: search_shop_policies_and_faqs WebMCP is still an emerging standard, and agent support is currently limited to Chromium-based browsers through an origin trial . Shopify is helping shape the specification alongside Google and Microsoft. Learn more in the WebMCP docs . If you're building your own agent, see Build commerce agents .
Read more →You can now deploy Hydrogen storefronts to Oxygen from dev stores . Previously, Oxygen hosting required a paid plan. Note that development stores don't include public environments, so deployment URLs always require a store login. Learn more about supported plans .
Read more →Access Shopify changelog updates through our uniform API. Same JSON structure across all sources — no adapter-specific parsing needed.
GET https://watchchangelog.com/api/v1/entries?source=shopify-plus.updates{
"source": "shopify-plus.updates",
"vendor": "Shopify",
"id": "https://shopify.dev/changelog/four-additional-topics-are-now-available-for-events",
"published_at": "2026-08-26T17:00:00.000Z",
"title": "Four additional topics are now available for Events",
"url": "https://shopify.dev/changelog/four-additional-topics-are-now-available-for-events",
"summary": "Apps can now subscribe to events for Metaobject , MetafieldDefinition , MetaobjectDefinition , and InventoryTransfer . Apps can also subscribe to targeted metafield changes on InventoryTransfer . By subscribing to these topics, your app can react directly to changes in custom content, custom data definitions, and inventory transfer workflows. Apps can target the fields that matter in triggers, query the resource that changed, and avoid subscribing to broader updates just to diff payloads in their event handler. For example, the following subscription delivers when the value of the title field changes. The query uses the trigger's metaobjectId to fetch that Metaobject and field. [events] api_version = \"unstable\" [[events.subscription]] handle = \"metaobject-event\" topic = \"Metaobject\" actions = [\"update\"] triggers = [ \"metaobject(type: 'books').field(key: 'title').value\" ] uri = \"/api/events\" query = \"\"\" query MetaobjectTitleValue($metaobjectId: ID!, $fieldKey: String!) { metaobject(id: $metaobjectId) { id type handle field(key: $fieldKey) { key value } } } \"\"\" The complete payload body when the title field changes is as follows: { \"topic\": \"Metaobject\", \"action\": \"update\", \"handle\": \"metaobject-title-value\", \"data\": { \"metaobject\": { \"id\": \"gid://shopify/Metaobject/123123\", \"type\": \"books\", \"handle\": \"metaobject-event\", \"field\": { \"key\": \"title\", \"value\": \"My Book Title\" } } }, \"fields_changed\": [ \"metaobject[id: 'gid://shopify/Metaobject/123123', type: 'books'].field[key: 'title'].value\" ], \"query_variables\": { \"metaobjectId\": \"gid://shopify/Metaobject/123123\", \"metaobjectType\": \"books\", \"fieldKey\": \"title\" } } Events remain available in the unstable API version during developer preview. For topics that are not supported yet, continue using webhooks alongside Events. Learn more about: Events: https://shopify.dev/docs/apps/build/events Metaobject: https://shopify.dev/docs/api/events/latest/metaobject MetafieldDefinition: https://shopify.dev/docs/api/events/latest/metafield-definition MetaobjectDefinition: https://shopify.dev/docs/api/events/latest/metaobject-definition InventoryTransfer: https://shopify.dev/docs/api/events/latest/inventory-transfer",
"tags": [
"Shopify",
"shopify-plus.updates",
"ecommerce",
"enterprise",
"shopify"
]
}Sign up to access the full changelog API. All public sources are free — no credit card required.
Sign Up Free →+2 more
+2 more
+2 more
+2 more
+2 more