Developer Changelog / Events (Developer Preview)

Events adds metafield triggers
and new topics

Order / Collection / InventoryItem / InventoryShipment / Location can now be subscribed to. On top of that, for Product, Order, Customer, Collection, and Location you can now subscribe to metafield changes themselves by namespace and key. No more handlers that take every update and diff it yourself.

On this page
  1. In 30 seconds: what you can do now
  2. Newly supported resources
  3. How it works: from metafield change to your handler
  4. Configuration example: shopify.app.toml
  5. Structure of the payload you receive
  6. Trigger granularity: 3 patterns
  7. Limitations and caveats
  8. 5 key points for developers
  9. 3 use cases you can put to work
  10. One-line summary for your pitch

1In 30 seconds: what you can do now

What Events can subscribe to has expanded to Order / Collection / InventoryItem / InventoryShipment / Location , and
what's more, you can now subscribe to the metafield value change itself by specifying a namespace and key.

Before: receive everything, diff it yourself

Even when you only wanted to act "when this one metafield changes," you had to subscribe to the resource's entire update and compare payloads in your handler.

Now: target only the fields you want

List the target metafield under triggers and the event fires only when that value changes. You then query the changed resource yourself and receive just the data you need.

In Shopify's own words: apps can "target specific fields with triggers, query the changed resource, andavoid subscribing to full resource updates just to diff payloads". In other words, fewer notifications and simpler handlers — two wins from a single change.

2Newly supported resources

Topics you can now subscribe to

Order
Orders
Collection
Collections
InventoryItem
Inventory items
InventoryShipment
Inventory shipments
Location
Locations

Resources that support subscribing to metafield changes

ResourceMetafield subscriptionsNotes
ProductSupportedProductVariant metafields are also via the Product topicsupported
OrderSupported
CustomerSupported
CollectionSupported
LocationSupported
Anything elseNot supportedFor unsupported topics, keep using webhooks as well (the two can coexist in the same shopify.app.toml )
$app metafields and standard metafields are both supported.App-reserved namespaces and merchant-defined ones such as custom can be listed side by side in the same subscription.

3How it works: from metafield change to handler

Product custom.care_label custom.material ← changed $app.sourcing_status ① The value changes Match against triggers Check whether namespace + key match match ✓ ② Fires only on a match Run the query $productId $metafieldNamespace $metafieldKey query_variables is filled in automatically ③ Fetch what changed uri = "/events/product" data: exactly the shape you designed fields_changed: what changed query_variables: the values used ④ Your app receives it (no diffing needed)
The key point is ③'s query_variables. Since "which metafield changed" is passed into the query as a variable,a single query definition can be reused across multiple metafields. You don't need to write a separate query for each trigger.

4Example config: shopify.app.toml

The official example: target two Product metafields and fetch whichever one actually changed with query_variables .

[events]
api_version = "unstable"

[[events.subscription]]
handle = "product_material_sync"
topic = "Product"
actions = ["update"]
triggers = [
 "product.metafield(namespace: 'custom', key: 'material').value",
 "product.metafield(namespace: '$app', key: 'sourcing_status').value"
]

uri = "/events/product"

query = """
query ProductMetafieldSync(
 $productId: ID!
 $metafieldNamespace: String!
 $metafieldKey: String!
) {
 product(id: $productId) {
 id
 title
 metafield(namespace: $metafieldNamespace, key: $metafieldKey) {
 namespace
 key
 value
 type
 }
 }
}
"""
triggers

Specify with a field path expression

product.metafield(namespace: ..., key: ...).value — that's the format.custom -style regular namespaces and $app can be listed in the same array.

query

Design the payload shape yourself

Write the GraphQL query inside the toml and let your app decide the shape of the payload. If you turn namespace / key into variables, you can share it across multiple triggers.

actions

Specify update

In this example, actions = ["update"].handle is also included in the payload as-is, so you can use it as a routing identifier.

5Structure of the payload you receive

With the configuration above, this is the payload delivered when custom.material changes.

{
 "topic": "Product",
 "action": "update",
 "handle": "product_material_sync",
 "data": {
 "product": {
 "id": "gid://shopify/Product/1234567890",
 "title": "Canvas Tote",
 "metafield": {
 "namespace": "custom",
 "key": "material",
 "value": "Cotton",
 "type": "single_line_text_field"
 }
 }
 },
 "fields_changed": [
 "product.metafield(namespace: 'custom', key: 'material').value"
 ],
 "query_variables": {
 "productId": "gid://shopify/Product/1234567890",
 "metafieldNamespace": "custom",
 "metafieldKey": "material"
 }
}
KeyContentsWhere it's useful in your handler
topic / actionProduct / updateHigh-level routing
handleThe handle of the subscriptionIdentifies which subscription config it came from
dataThe result of the query written in the tomlCan be fed straight into your business logic
fields_changedArray of the field paths that actually changedBranching when multiple triggers are bundled into one subscription
query_variablesThe actual values of the variables passed to the queryReuse for logs, idempotency keys, and as input when re-fetching

6Trigger granularity: 3 patterns

A

Omit triggers

Metafield change events for supported resources are also delivered to you. Nothing is missed, but the notification volume is at its highest.

B

Parent trigger (e.g. product)

If you specify the parent, metafield change events arrive in the same way. The scope widens while your existing subscription config stays as is.

C

Explicit targeting

Adding a metafield trigger that explicitly specifies namespace and key meansonly that changeis delivered. Notification volume stays minimal.

Existing apps may fall under A or B.Subscriptions with no triggers, or on the parent trigger, will start firing on metafield changes as of this change. If you want to avoid an unexpected jump in calls, rewriting them to the targeted form in C is the safer move.

7Limitations and caveats

Access control still applies

The appmust have access to that metafield— that is the condition for both subscribing and receiving data. Without permission, you can neither subscribe nor receive query results.

unstable

Developer preview / unstable only

Events is in developer preview and isavailable only on the unstable API version. No timeline for general availability is given.

Events Webhook

Use webhooks alongside for unsupported topics

For topics Events doesn't cover yet, keep using webhooks as before.In the same shopify.app.toml , declare both Events and webhooks— that's the official guidance.

Variant

ProductVariant goes through Product

Variant metafields don't get their own topic; they'resupported through the Product topic. Write the subscription config on the Product side.

Rate limits, delivery guarantees, retries, and event ordering guarantees arenot mentionedin this announcement. If you plan to depend on them in production, check the Events documentation.

8Five points engineers should know

1. The design shifts to "keep diff detection out of the handler"

The "stash the previous value somewhere and compare" logic that used to live in the handler is no longer needed.From a stateful receiver to a stateless one. There's room to remove the previous-value cache in your KVS.

2. query_variables lets you consolidate queries

Since namespace / key can be taken as variables, multiple metafield triggers can be handled with a single query definition. More triggers no longer means the toml grows linearly.

$app

3. $app and regular namespaces can be mixed

App-owned $app metafields and merchant-side custom can go in the same triggers array. "The app's internal state" and "the merchant's input" arrive through the same path.

4. Permission design feeds directly into event design

Metafields the app has no access to can't be subscribed to or read.Missing scope / metafield access requests tend to surface as "the events never arrive,"so suspect permissions first when narrowing down the problem.

5. Watch out for existing subscriptions firing more often than before

With no triggers, or with product as a parent trigger, apps subscribed this way will, with this change,now also fire on metafield changes. Endpoint call counts, billing, and job queue inflow may all grow more than expected, so monitor inbound volume after the release and narrow things down with target specifications if needed.

9Three use cases you can put to work

Shopify Core systems PIM
USE CASE 1

Sync only the attributes that changed for PIM / core system integrations

Problem
A product master sync app receives every product/update and compares against previous values inside the handler to determine whether attributes such as "material" or "country of origin" changed. Maintaining the previous-value store for comparison and processing unnecessary deliveries is expensive.
Approach
Target only the metafields in scope for the sync in triggers , and usequery to fetch only the value and type of the metafields that changed.fields_changed to branch on which column to update in the destination system.
Impact
Fewer inbound events, no more previous-value cache, and a simpler handler. The number of sync job runs itself goes down.
Technical notes
ProductVariant metafields come through the Product topic, so variant attribute syncing can be consolidated into the same subscription.
Order processing meta
USE CASE 2

Trigger downstream processes from custom attributes on orders

Problem
Values like "delivery instructions," "gift settings," and "review status" are managed as order metafields, but there is no way to detect when a value is set, so they are picked up by polling or batch jobs. Updates are slow to reflect.
Approach
Subscribe to Order metafield changes and make the flow event-driven, narrowed to the target namespace / key.$app metafields, status transitions written by the app itself can be picked up through the same mechanism.
Impact
Shorter lead times by eliminating batch waits, fewer API calls for polling, and an event-driven business workflow.
Technical notes
You cannot subscribe to metafields you do not have access to, so check the app's metafield access settings first. Beyond Order, the same applies to Customer / Collection / Location.
USE CASE 3

Consolidate inventory and location integrations on Events and tidy up your webhooks

Problem
Inventory, shipment, and location integrations are built on webhooks, and subscription settings are scattered. Extra API calls pile up after each delivery just to get the data you need.
Approach
Move the newly supported InventoryItem / InventoryShipment / Location / Order / Collection over to Events, and usequery to fetch the fields you need from the start. For topics that are not supported yet, keep webhooks in the same shopify.app.toml and use both side by side.
Impact
Fewer follow-up API calls after receipt, consolidated subscription definitions, and simpler handlers because the payload shape can be designed on the app side.
Technical notes
Events is in developer preview and available only on unstable. Rather than treating it as a prerequisite for switching production over,run it alongside in a test environment and compare behavior and delivery volume— that is the realistic plan.

10One-line summary you can use in a proposal

"Shopify Events now supports Order, Collection, inventory, and location,
and metafield changes themselves can be subscribed to per namespace / key.
You can drop the 'receive every update and diff it yourself' handler and pick up only the fields you need, event-driven.
For now, though, it is an unstable developer preview, and unsupported topics still need webhooks."

+Related documentation