Webhooks
How FilterIQ handles Shopify webhooks to keep product data in sync.
Webhooks
FilterIQ uses Shopify webhooks to keep your product data synchronized in real-time. When products are created, updated, or deleted in your Shopify admin, the search index is updated automatically within seconds.
Registered Webhooks
The app registers these mandatory Shopify webhooks:
| Webhook Topic | Purpose |
|---|---|
products/create | Index new products in the search engine |
products/update | Re-index updated products (title, price, inventory, etc.) |
products/delete | Remove deleted products from the search index |
app/uninstalled | Clean up shop data when the app is uninstalled |
Webhook Processing Pipeline
Shopify sends webhook
|
HMAC signature verification
|
Shop domain extraction (from signed headers)
|
Install status check (cached)
|
Product data transformation
|
Search index update
|
Database metadata update
Security
Every webhook request is cryptographically verified:
- Shopify signs the webhook payload with your app's API secret key
- The backend verifies the signature from the raw request body
- If the signatures do not match, the request is rejected with HTTP 401
- The app supports secret rotation for zero-downtime key changes
Install Status Caching
Before processing a webhook, the backend checks whether the shop has an active installation. This check is cached to avoid a database lookup on every webhook. If the shop does not have an active installation, the webhook is acknowledged (HTTP 200) but not processed.
Product Data Transformation
When a product webhook arrives, the raw Shopify product data is transformed into a search document:
Fields Extracted
| Shopify Field | Search Document Field | Notes |
|---|---|---|
| title | title | Primary searchable field |
| body_html | description | HTML tags stripped |
| vendor | vendor | Searchable and filterable |
| product_type | product_type | Searchable and filterable |
| tags | tags | Array of strings |
| variants | variants, price_min, price_max | Price range calculated |
| variants[].sku | sku | Searchable |
| variants[].inventory_quantity | inventory_quantity | Sum across variants |
| variants[].option1/2/3 | options | Variant option values |
| images | images | URLs for display |
| handle | handle | Used for product URL |
| published_at | published_at | Null for draft products |
| created_at | created_at | Used for "New Arrivals" sorting |
| metafields | metafields.* | Only configured metafields |
Variant Processing
For each product, the webhook handler:
- Extracts all variant option names and values (Color, Size, Material, etc.)
- Calculates
price_minandprice_maxacross all variants - Sums
inventory_quantityacross all variants - Maps variant options to the correct option name (option1 = "Color", option2 = "Size", etc.)
Webhook Reliability
Retry Behavior
Shopify retries failed webhooks (non-2xx responses) up to 19 times over 48 hours with exponential backoff. The backend always returns HTTP 200 quickly (within 5 seconds) and processes the webhook asynchronously if needed.
Idempotency
Product webhooks are idempotent -- processing the same webhook twice produces the same result. The search index uses the product's Shopify ID as its document ID, so duplicate updates simply overwrite with the same data.
Ordering
Shopify does not guarantee webhook delivery order. If a product is updated multiple times in quick succession, the webhooks may arrive out of order. The backend handles this by always writing the full product state (not incremental updates), so the final state is always correct regardless of order.
Monitoring
You can monitor webhook health in the app dashboard:
- Settings > Sync Status -- Shows the last successful sync time and any errors
- Settings > Sync History -- Shows recent webhook events and their processing status
If webhooks stop arriving (e.g., due to a prolonged backend outage), you can trigger a manual full re-sync from Settings > Sync Status > Re-sync Products.
Bulk Webhooks
For large catalog operations (e.g., importing 10,000 products via CSV), Shopify may send a high volume of webhooks in a short period. The backend handles this through:
- Concurrent webhook processing with connection pooling
- Batch indexing (multiple products per index request)
- Rate limiting to prevent overloading downstream services