--- title: Filter your events description: >- A guide with an overview of webhook filters, which gate what event messages a dev will receive, depending on a set of rules they have defined. source_url: html: 'https://shopify.dev/docs/apps/build/webhooks/customize/filters' md: 'https://shopify.dev/docs/apps/build/webhooks/customize/filters.md' --- # Filter your events Shopify provides you with a way to manage the *number* of event messages your app receives. Unlike payload modifications, filters are made up of rules, applied to a webhook subscription, which then act as a gate for whether or not webhooks are delivered when an event occurs. **Info:** Filters are only available as of the `2024-07` version of the Admin APIs. *** ## Example: Filtering when products are updated Suppose you're building an app that relies on data when a product is updated. Because of your use case, you're only interested in this data if at least one product variant's price is greater than or equal to $10.00. However, because you've subscribed your app to the `products/update` webhook topic, your app receives webhooks any time the product is updated, regardless of the variant price. As a result, you receive far more webhooks than you care about, and must process them *all*, in order to get the information you really care about (webhooks for products where the variant price is at least $10.00). In this case, you can use the filter capability to define a rule on your webhook subscription. ## Example filter ```json [[webhooks.subscriptions]] topics = ["products/update"] uri = "https://example.com/webhooks" filter = "variants.price:>=10.00" ``` After you apply this filter, your app receives `products/update` webhooks for updates to products where at least one variant's price is at least $10.00. *** ## How to configure filters There are two ways in which you can filter webhooks: * In the `filters` argument when you create or update a subscription using your [app configuration file](https://shopify.dev/docs/apps/structure/configuration) * With the `filter` input field in the `webhookSubscription` argument when you create or update a subscription using the [GraphQL Admin API](https://shopify.dev/docs/api/admin-graphql/2024-04/mutations/webhookSubscriptionCreate#argument-webhooksubscription) To determine what are valid values for your filter rules, refer to the sample payloads in the [Webhooks reference](https://shopify.dev/docs/api/webhooks). You denote nested fields by using a period: ## Example nested field ```json "variants.price:>=10.00" ``` **Note:** The `variants` field is a top-level payload field. If you have **more than one product variant, and even one variant that has a price greater than $10.00**, when the product is updated (for example, title is changed) the webhook fires. ## Filter products/update webhooks ## Filter definition ##### shopify.app.config-name.toml ```toml name = "Example App" client_id = "a61950a2cbd5f32876b0b55587ec7a27" application_url = "https://www.app.example.com/" embedded = true handle = "example-app" [access_scopes] scopes = "read_products" [access.admin] direct_api_mode = "online" [auth] redirect_urls = [ "https://app.example.com/api/auth/callback", "https://app.example.com/api/auth/oauth/callback", ] [webhooks] api_version = "2024-01" [[webhooks.subscriptions]] topics = ["products/update"] uri = "https://example.com/webhooks" filter = "id:* AND status:active AND (product_type:Music OR product_type:Movies) AND -invalid_field:* AND variants.taxable:true AND variants.weight:<5 AND variants.price:>=100 AND variants.title:Album*" [app_proxy] url = "https://app.example.com/api/proxy" subpath = "store-pickup" prefix = "apps" [pos] embedded = false [app_preferences] url = "https://www.app.example.com/preferences" [build] automatically_update_urls_on_dev = false ``` ##### GraphQL ```graphql mutation subscribeToWebhook { webhookSubscriptionCreate( topic: PRODUCTS_UPDATE, webhookSubscription: { uri: "https://example.com/webhooks" filter: "id:* AND status:active AND (product_type:Music OR product_type:Movies) AND -invalid_field:* AND variants.taxable:true AND variants.weight:<5 AND variants.price:>=100 AND variants.title:Album*" } ) { webhookSubscription { id createdAt uri filter } userErrors { field message } } } ``` *** ## Filtering on nested array values For fields that contain arrays of objects, you can also create filters based on the properties of those nested objects. The filter matches if at least one object in the array meets the specified condition. ## Example payload with nested arrays ```json "line_items": [ { "product_exists": true, "product_id": 9554194432293, "properties": [] }, { "product_exists": true, "product_id": 9554194465061, "properties": [ { "name": "_your_custom_property", "value": "some-value" } ] } ] ``` For the above payload, the following filter triggers the webhook because there's at least one item in the `line_items` array that contains a property where `name` is `_your_custom_property`. ## Example filter for nested array values ```json "line_items.properties.name:_your_custom_property" ``` This means that if any `line_items` has at least one matching object in its `properties` array, the webhook is delivered. *** ## Differences between filters and search Webhook filters leverage [Shopify API's Search syntax](https://shopify.dev/docs/api/usage/search-syntax). However, there are slight differences in the behavior between filters and search. | **Filters** | **Search** | | - | - | | If you specify an invalid field, then **no webhooks are delivered**. | If you specify an invalid field, then all documents are returned. | | `:` operator is an **equality** operator for filters. | `:` operator does fuzzy matching when fields are tokenized. | | You must **explicitly specify the fields** that you want to filter on. | Term searches are supported (`query:"bob"`). | | Case-sensitive. | Case-insensitive. | **Note:** Tags in some webhook topics like `products/update` and `orders/updated` are listed as a string. To filter products webhooks using one or several tags, treat each tag as a key word in a string, rather than a distinct value in an array. *** ## Debugging filters In instances when an invalid filter is applied to a subscription, expect the following behavior: | **Scenario** | **Expected behavior** | | - | - | | Filter uses field that doesn't exist in payload | Filter can be created but no event messages are sent | | `include_fields`, `includeFields` or `metafieldNamespaces` doesn't include fields that are included in the filter definition | Subscription isn't created and an error is provided. | | Filter uses a rule that isn't possible (type mismatch) | Filter can be created but no event messages are sent. | | Incorrect filter syntax | Filter isn't created and an error message is returned. | *** ## Required filters for metaobjects webhooks The following webhook topics require a filter to be specified: * `metaobjects/create` * `metaobjects/update` * `metaobjects/delete` ### Filter format Use `type:{type}` where `{type}` is the [metaobject definition's](https://shopify.dev/docs/apps/build/custom-data#what-are-metaobjects) type: ## Example metaobjects filter ```toml [[webhooks.subscriptions]] topics = ["metaobjects/create"] uri = "https://example.com/webhooks" filter = "type:my-metaobject-type" ``` To subscribe to multiple metaobject types, specify each type explicitly: ## Multiple metaobject types ```toml filter = "type:banana OR type:apple" ``` **Note:** Wildcard filters like `type:*` aren't supported. You must explicitly specify each metaobject definition's type. ### App-owned metaobject definitions For [app-owned metaobject definitions](https://shopify.dev/docs/apps/build/custom-data/ownership#create-metaobject-definitions-with-reserved-types), use the full type value as it appears in query responses: `app--{your-app-id}--{some-namespace}`. The `$app:{some-namespace}` shorthand isn't supported in filters. ***