Type: Developer Guide / Decision Guide · Stage: Scale · Topic: Events / Webhooks / Product Sync
On this page
Quick answer
For an integration that listens to products/update only to synchronize variant prices, Shopify’s Next Gen Events can eliminate unrelated deliveries. Generally available since October 1, 2026, Events allow field-level triggers, custom GraphQL payloads, and filters that decide whether a delivery is needed. A title or tag edit no longer has to wake your price-sync handler.
Do not replace every webhook. Events support a subset of resources and must be configured in shopify.app.toml. Classic webhooks still cover more topics and support shop-specific subscriptions created through the Admin GraphQL API. Both can coexist.
Why the older pattern is noisy
A conventional products/update subscription often triggers a handler for every product edit. That handler may fetch the latest variants and metafields, compare the values against an external system, then decide there was nothing to do. During catalog imports or bulk merchandising changes, this creates unnecessary requests and queue work.
Webhook include_fields reduces the payload but does not turn the subscription into a field-change detector. Events divide the problem into triggers (which fields changed), a query (which current fields arrive in the payload), and a query_filter (which queried results qualify).
Choose the right mechanism
| Need | Recommended |
|---|---|
| Only variant price changes on active products | Events with field triggers and a query filter |
| Product metafields or external IDs included in the delivery | Events with a custom GraphQL query |
| Topics Events does not yet support | Classic webhooks |
| Different subscriptions for different shops through Admin GraphQL | Classic webhooks |
Example: an active-product price sync
Use Shopify CLI 3.92 or later and confirm supported trigger paths in the Events reference. This is a shopify.app.toml example:
[events]
api_version = "2026-10"
[[events.subscription]]
handle = "active_variant_price_sync"
topic = "Product"
actions = ["update"]
triggers = [
"product.variants.price",
"product.variants.compareAtPrice"
]
uri = "/events/app/products-price"
query = """
query price_change($productId: ID!, $variantsId: ID!) {
productVariant(id: $variantsId) {
id
price
compareAtPrice
}
product(id: $productId) {
id
status
}
}
"""
query_filter = "product.status:'ACTIVE'"
Price changes qualify for the trigger; title changes do not. The query returns the affected variant’s current price data and the product’s status. The filter suppresses events for inactive products. A filter is not a before/after comparison, and a current-state query should not be mistaken for a historical audit trail.
Practical migration
- Inventory the existing consumer. List all fields used by the current handler. If it also reacts to product status, tags, or deletions, a price-only replacement would silently lose those behaviors.
- Check Events coverage. Events use a resource topic such as
Product, not the classicproducts/updatetopic string. Use the Events reference to validate field paths. - Keep the query small. Events subscriptions have a 100-point GraphQL query complexity limit. Query a changed variant by ID rather than fetching a large variants connection.
- Validate before release. Use
shopify app deploy --no-releaseto validate an app version without releasing it to merchants. - Prevent duplicate writes. During migration, compare the old webhook and new Event consumers in a development environment, but designate only one to write to the external system. Use authenticated delivery handling and idempotency.
- Retire the old subscription only when covered. Keep classic webhooks for unsupported topics or actions.
Common misunderstanding
“Events replace all webhooks.” They do not; Shopify supports both mechanisms. “query_filter detects the changed field.” That is the job of triggers; the filter checks current query results. “The query can return everything.” Events queries are limited by complexity and should request only the data the consumer needs.
How to test this
- Confirm the CLI version, supported topic, triggers, and query variables. Validate the configuration in a development app.
- Change a product title without changing its price. Verify the price-only Event is not delivered.
- Change a variant’s price and compare-at price on an active product. Verify the delivery contains the expected IDs and values.
- Change the price of an inactive product. Verify the query filter suppresses the delivery.
- Make two rapid price edits and a bulk update. Verify the external system cannot overwrite a newer price with stale data.
- Test delivery retries and deduplication, then disable the redundant classic webhook only after the new path is stable.
Sources and further reading
- Shopify 2026-10 release notes: Events general availability
- Shopify developer docs: Events and webhooks
- Shopify developer docs: create an Events subscription
- Shopify developer docs: triggers and query filters
- Shopify developer docs: query complexity and optimization
Documentation checked October 18, 2026.

