We really appreciate the community for building with Events in Developer Preview, and your feedback is actively helping us improve the contract before Events go to stable in 2026-10.
Across Partner conversations, DotDev workshops, and existing subscriptions, we heard four places where the current behavior is harder to understand or build against than it should be:
fields_changedtells you which path changed, but it cannot distinguish between a path beingadded,updated, orremoved.- Deleting a resource can produce follow-up update events for children that no longer exist.
- A parent trigger path such as
product.variantsbehaves like a wildcard, but the syntax does not make that breadth clear. - Redundant
shopify-event-idandshopify-resource-idheaders, which we’re removing before the stable release.
We’re making updates to address this feedback before we lock the Events contract. All breaking changes will roll out on September 16, 2026, and if you’re using Event in your apps, you’ll need to update your subscription configuration and payload handling. These changes apply to Events subscriptions and Classic Webhook subscriptions stay unaffected.
Additionally, we’re also introducing the ability to have a per subscription api_version override, so you can migrate API versions incrementally.
1. fields_changed will describe how each path changed
Today, adding and removing a variant produces the same fields_changed in the payload:
"fields_changed": [
"product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
]
You know which path changed, but you cannot tell whether it appeared or disappeared without making a query and inferring what happened from the result. Starting September 16, 2026, fields_changed becomes an object with three path buckets:
"fields_changed": {
"added": [],
"updated": [],
"removed": []
}
The buckets describe what happened to a path in the developer-visible GraphQL graph:
added: A resource or relationship was added, such as adding a variant to a Product.updated: A value changed on an existing resource, such as changing a variant’s price.removed: A resource or relationship was removed, such as removing a variant from a Product.
Adding a variant to a Product remains "action": "update" for the Product, with the variant path in fields_changed.added:
{
"topic": "Product",
"action": "update",
"fields_changed": {
"added": [
"product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
],
"updated": [],
"removed": []
}
}
Changing the price of an existing variant keeps the path present, so it appears in updated:
"fields_changed": {
"added": [],
"updated": [
"product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456'].price"
],
"removed": []
}
Removing that variant places the same addressable path in removed:
"fields_changed": {
"added": [],
"updated": [],
"removed": [
"product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
]
}
2. Deletes will no longer produce follow-up updates
Deleting a Product with eight variants can produce one Product delete event followed by eight Product update events, one for each cascading variant deletion. Those updates can arrive after the delete and the query for the Product or variant then returns null, because the resource no longer exists.
We’re actively rolling it across all topics, which means deleting a topic resource will produce one delete event. For example, deleting a Product with two variants changes from:
Product delete
Product update for cascading deletion of Variant 456
Product update for cascading deletion of Variant 789
to:
Product delete
The same rule applies when deleting a Metaobject with fields or a Collection with product relationships. Removing one variant from a Product that still exists remains a meaningful Product update:
{
"topic": "Product",
"action": "update",
"fields_changed": {
"added": [],
"updated": [],
"removed": [
"product[id: 'gid://shopify/Product/123'].variants[id: 'gid://shopify/ProductVariant/456']"
]
}
}
Independent effects across topics remain the same, which means deleting a Product will still produce a Collection update when that Collection’s membership changes.
create behavior continues producing follow-up update Events, so when a Product and its variants are created, those children exist and can be queried ensuring that every child is observable, including children beyond the first page of a GraphQL connection.
3. Parent trigger paths will use an explicit wildcard
Today, a parent trigger path such as triggers = ["product.variants"] means “subscribe to every triggerable field below product.variants.” The same path can reasonably look like it means only the variants relationship changed, making the wildcard behavior too easy to miss. Starting September 16, 2026, parent paths that subscribe to all supported descendants use a terminal .*:
triggers = ["product.variants.*"]
This makes the existing breadth of the subscription explicit. It does not change which underlying field changes match or affects event volume for an equivalent subscription.
Leaf triggers remain unchanged:
triggers = ["product.variants.price"]
product.variants.*means any triggerable field below variants.product.variants.pricemeans only variant price changes.product.options.optionValues.swatch.*means any triggerable field below swatch, including color or image.- Omitting triggers continues to mean that any supported change for the topic can qualify the subscription.
Your existing subscriptions will continue to work and the next time you deploy your shopify.app.toml, you’ll have to migrate to the new syntax, if you’re using triggers that require an explicit wildcard.
4. Redundant shopify-event-id and shopify-resource-id are being removed
Events deliveries currently include the shopify-event-id and shopify-resource-id headers. Both headers will be removed on September 16, 2026.
Updated Shopify API packages are available today which handles this change for you, so no additional header migration is required. If your own application code reads either header directly, remove that dependency before September 16, 2026.
What you need to update:
- Change code that expects
fields_changedto be an array. Read fromfields_changed.added,fields_changed.updated, andfields_changed.removed. - Add a terminal
.*to every parent trigger path that is intended to match all descendants, your existing subscriptions will continue to work as expected on deploys after September 16, 2026. - Review
action: deletehandling. A topic resource deletion is now represented by its single delete event, without child-derived updates from the same cascade. Keep handling independent child removals as updates to a surviving immediate parent. - Update your Shopify API packages to their latest versions. This handles the removal of
shopify-event-idandshopify-resource-idfor you. If you use custom packages, ensure the headers are not required for validation. - Set your Events API version to
2026-10on October 1, 2026.
These changes will result in a more predictable delete sequence, a payload that tells you how each path changed, trigger syntax that says exactly how broad the subscription is, and a simpler set of delivery headers.
If you’re testing Events today, we’d love to hear how these changes affect your integration. Share your questions or migration feedback below.
Learn more
Read more about Events: https://shopify.dev/docs/apps/build/events-webhooks
Events API reference: https://shopify.dev/docs/api/events/latest