Blog
Technical9 min read

Setting Up Shopify Webhooks for Real-Time VIP Order Alerts

DH
Dennis Hegstad
Founder, sonarID · March 5, 2026
Setting Up Shopify Webhooks for Real-Time VIP Order Alerts

To set up Shopify webhooks for real-time VIP order alerts, subscribe to the orders/create topic (and usually customers/create), point it at an HTTPS endpoint that responds in under five seconds, verify each request with the X-Shopify-Hmac-Sha256 header, then queue the payload for enrichment so identity scoring runs off the critical path. Shopify fires the webhook the moment an order is placed, your endpoint pulls the email and shipping address, and an enrichment step decides whether the customer is a founder, investor, influencer, press contact, or affluent buyer worth a real-time alert.

That is the entire architecture in one paragraph. But the difference between a webhook that works in a demo and one that catches every VIP at 2am on Black Friday is in the details: HMAC verification, fast acknowledgment, retry handling, idempotency, and knowing which topic actually carries the data you need. This guide walks through configuring orders/create and customers/create end to end, validating payloads correctly, and fixing the failures that quietly drop alerts. If you would rather skip the engineering, SonarID registers and manages these webhooks for you on install, but understanding the mechanics helps you trust whatever runs in production.

Why Webhooks Beat Polling for VIP Detection

A VIP alert is only useful if it arrives while you can still act on it. If a journalist or a founder places an order and you find out three days later in a weekly export, the moment has passed. Webhooks are push: Shopify calls you the instant the event happens, so enrichment and scoring can run within seconds and a Slack or Klaviyo alert can land before the order is even picked.

The alternative is polling the Admin API on a schedule, asking "any new orders?" every few minutes. Polling burns API rate limit, adds latency equal to your poll interval, and scales badly when order volume spikes during a launch or a sale. For a deeper comparison of the two approaches and when polling still earns its place as a backfill, see webhooks vs. API polling. For real-time VIP detection the answer is almost always webhooks, with polling reserved for reconciliation and catching anything a delivery missed.

Choosing the Right Webhook Topics

Shopify exposes dozens of webhook topics, but VIP detection needs only a small set. The workhorse is orders/create, which fires on every new order and carries the customer object, email, and both billing and shipping addresses in a single payload. Because SonarID scores primarily on the shipping address (the residence) rather than billing, orders/create is ideal: the shipping zip, city, and street all arrive together, so affluent-zip matching and address signals run immediately. For why the residence matters more than the billing field, see what a shipping address reveals.

The second topic worth subscribing to is customers/create, which fires when a brand new customer record is created. This matters for stores where account creation can precede the first order, or where you want to enrich and pre-tag a customer before they check out. Note that the two events overlap: a guest checkout creates both a customer and an order, so your handler must be idempotent and not double-count or double-alert the same person.

A few other topics are situationally useful. orders/updated catches address corrections or a customer object attached after the fact. customers/update lets you re-score when an email or address changes. Resist the urge to subscribe to everything. Each topic is another delivery to verify, deduplicate, and rate-limit against, and more topics means more surface area for the silent failures described below. Start with orders/create, add customers/create if your funnel needs it, and expand only when you have a concrete signal you are missing.

Registering the Webhook

You can register webhooks two ways. The first is the Admin API: send a POST to the webhooks endpoint with the topic, your HTTPS callback URL, and a format of JSON. The second, and the right way for a real app, is to declare webhooks in your app configuration so Shopify registers them automatically on install and re-registers them if the URL changes. App-level subscriptions also support delivery over Amazon EventBridge and Google Pub/Sub, which add durability if you are operating at high volume and want a managed queue between Shopify and your code.

Whichever method you use, three rules hold. Your endpoint must be HTTPS with a valid certificate, because Shopify will not deliver to plain HTTP. Your URL should be stable, because re-pointing a webhook mid-traffic can drop in-flight deliveries. And you must capture the API secret used to sign payloads, because without it you cannot verify that a request actually came from Shopify. For a broader look at automating store operations around these events, Shopify Flow handles no-code triggers, while raw webhooks give you the control enrichment requires.

Validating the Payload With HMAC

This is the step people skip and regret. Anyone who learns your webhook URL can POST fake orders at it. Without verification, an attacker could flood your enrichment pipeline with junk or trigger false VIP alerts. Shopify signs every webhook with a keyed HMAC so you can prove authenticity.

The mechanics: Shopify computes an HMAC-SHA256 over the exact raw request body using your app secret as the key, base64-encodes the result, and sends it in the X-Shopify-Hmac-Sha256 header. Your handler recomputes the same HMAC over the raw bytes you received and compares. If they match, the request is genuine. Two details cause almost every verification bug. First, you must hash the raw, unparsed body. If your web framework parses JSON before you reach it, the re-serialized bytes will differ and the signature will never match, so disable body parsing on the webhook route or capture the raw buffer first. Second, compare using a constant-time comparison function, not plain string equality, to avoid leaking timing information. Reject anything that fails with a 401, and do it before any other work.

Respond Fast, Process Later

Shopify expects your endpoint to acknowledge a webhook within five seconds. If you do not, Shopify treats the delivery as failed and retries it, and repeated failures eventually unsubscribe your endpoint entirely. The mistake is doing enrichment inline: calling an identity provider, scoring the customer, and posting to Slack all before returning a response. Enrichment can take longer than five seconds, especially under load, and now your webhook is timing out.

The correct pattern is acknowledge then process. Verify the HMAC, write the payload to a durable queue or job table, and immediately return a 200. A background worker then pulls the job, runs free-layer signals (email-domain matching, spend analysis, and affluent-zip matching, all of which cost nothing per lookup), and only escalates to paid enrichment at $0.05 per enrichment when the free signals justify a full profile. This keeps the webhook response well under the timeout no matter how slow enrichment gets, and it means a downstream provider outage never causes Shopify to start dropping your subscriptions. SonarID is built exactly this way, which is why a traffic spike during a launch does not silently sever your alert pipeline. The wider trade-offs live in webhooks vs. API polling.

Idempotency and Deduplication

Shopify guarantees at-least-once delivery, not exactly-once. The same order can arrive twice: once on a successful delivery that your server acknowledged a beat too slowly, and again on the retry. If your handler is not idempotent, you will enrich the same order twice, wasting a paid enrichment, and fire two VIP alerts for one customer, which erodes trust in the alerts.

Build idempotency on a stable key. Every webhook carries an X-Shopify-Webhook-Id header, and the payload carries the order id. Record processed ids and skip duplicates. For the overlap between orders/create and customers/create, deduplicate on the customer identity itself, normally the email or customer id, so a guest checkout that fires both events results in one enriched profile and one alert. Good enrichment systems also dedupe identity across multiple emails and addresses for the same person, a harder problem covered in customer identity deduplication. At minimum, never let a retry become a second alert.

Testing Your Webhook Before You Trust It

Do not wait for a real VIP to find out your pipeline is broken. Shopify lets you send a test notification for any registered topic from the admin, which delivers a sample payload so you can confirm your endpoint receives, verifies, and responds correctly. For local development, a tunneling tool gives Shopify a public HTTPS URL that forwards to your machine so you can step through HMAC verification and enrichment against real payload shapes.

Build a deliberate test matrix. Send a known corporate-domain email and confirm it triggers email-domain matching. Send an order with an affluent shipping zip and confirm the address signal fires. Send a tampered payload with a wrong HMAC and confirm you reject it with a 401. Send the same order id twice and confirm the second is deduplicated with no duplicate alert. Send a payload, return a 500 on purpose, and confirm Shopify retries and your retry succeeds. Each maps to a real production failure mode, and a green run across all five means your alerts will actually fire when it counts. The signals you are testing here are the ones explained in 5 signals a customer order is worth 10x more.

Troubleshooting Common Failures

When alerts go quiet, work through the layers in order. Start at registration: list your active webhook subscriptions via the Admin API and confirm the topic is present and the address is your current endpoint. A surprising number of "broken webhook" cases are simply a subscription that was never created, or one pointing at a stale URL from a previous deploy.

Next, check delivery. Shopify tracks failed deliveries, emails the app owner, and eventually removes a subscription that fails repeatedly over roughly two days. If your endpoint is getting unsubscribed, the root cause is almost always slow responses (the five-second timeout) or your server returning non-200 status codes. Confirm your handler returns 200 the instant after queuing, not after enrichment. Then check verification: if every request is rejected, you are almost certainly hashing a parsed body instead of the raw bytes, or using the wrong secret. Finally, check the data itself. An order from a free email provider with a generic address will legitimately produce no VIP signal, and that is correct behavior, not a bug. A deeper, scenario-by-scenario walkthrough lives in webhook debugging for VIP alerts.

From Webhook to VIP Action

A verified, fast, idempotent webhook is the foundation, but it is only the delivery mechanism. The value comes from what happens next: enrichment turns a raw order into an identity, scoring decides whether that identity is a VIP, and routing sends the alert where your team will see it. Wire the pipeline to Slack alerts so a high-value order pings the channel in real time, or to Klaviyo so an identified founder or influencer drops into a tailored flow. For the broader pattern of building detection into daily operations, see workflow automation for VIP identification.

Get the plumbing right once and it disappears into the background, doing its job on every order without a second thought. That is the goal: not a clever webhook handler you have to babysit, but a quiet, reliable signal that tells you the moment someone worth knowing buys from your store. Whether you build it yourself with the steps above or let SonarID register and run it for you, the principles are the same: verify, acknowledge fast, process off the critical path, and dedupe relentlessly.

Frequently asked questions

Which Shopify webhook topic should I use for VIP order alerts?

Use orders/create as the primary topic since it carries the email and shipping address in one payload, and add customers/create if account creation can happen before the first order.

How do I verify a Shopify webhook is genuine?

Recompute an HMAC-SHA256 over the raw request body using your app secret, base64-encode it, and compare it in constant time against the X-Shopify-Hmac-Sha256 header, rejecting any mismatch with a 401.

Why are my Shopify VIP alerts not firing?

The usual causes are a missing or stale webhook subscription, responses slower than the five-second timeout, non-200 status codes, or HMAC failures from hashing a parsed body instead of the raw bytes.

How fast does my webhook endpoint need to respond?

Under five seconds, so verify the HMAC, queue the payload, and return 200 immediately, then run enrichment and scoring in a background worker off the critical path.

How do I avoid duplicate VIP alerts from retried webhooks?

Make the handler idempotent by recording the X-Shopify-Webhook-Id or order id and deduplicating on customer identity so retries and overlapping order and customer events produce a single alert.

Do I need to write webhook code myself to use SonarID?

No, SonarID registers and manages the orders/create and customers/create webhooks on install, handling verification, fast acknowledgment, and deduplication for you.

Ready to know who is buying from you?

Start identifying VIP customers, influencers, and notable figures in your order stream — automatically.

Start detecting VIPs
End
DH
Written by
Dennis Hegstad
Founder, sonarID