Deliver webhooks through HTTPS
You might want to use HTTPS rather than a cloud-based event bus due to infrastructure requirements, where your domain knowledge lies, budget constraints, or because you want full control to customize your webhooks system. This approach will require additional steps, however, to ensure your system is production-ready and can handle receiving Shopify webhooks at scale. Shopify recommends using cloud-based event buses whenever possible to minimize this overhead.
What you'll learn
Anchor link to section titled "What you'll learn"- Notify Shopify that your app is receiving webhooks
- Validate the origin of each webhook
- Prepare your system to handle occasional bursts of webhook traffic
Requirements
Anchor link to section titled "Requirements"- An app with webhook subscriptions configured using HTTPS delivery
- Ensure your server is correctly configured to support HTTPS with a valid SSL certificate.
Shopify sends an HTTP POST request to the URI you have specified every time that event occurs. The HTTP POST
request's parameters contain the JSON data relevant to the event that triggered the request. Shopify verifies SSL certificates when delivering payloads to HTTPS webhook addresses.
Step 1: Notify Shopify that your app is receiving webhooks
Anchor link to section titled "Step 1: Notify Shopify that your app is receiving webhooks"Respond with a 200 OK, quickly
Anchor link to section titled "Respond with a 200 OK, quickly"Your system acknowledges that it received webhooks by sending Shopify a 200 OK
response. Any response outside of the 200 range, including 3XX HTTP redirection codes, indicates that you didn't receive the webhook. Shopify will consider these codes to be an error response.
Because Shopify has a connection timeout of one second, the your server must accept connections within one second.
Manage your connection to optimize your system
Anchor link to section titled "Manage your connection to optimize your system"Shopify's webhook delivery system uses HTTP Keep-Alive to reuse connections to the same host and endpoint. This reduces network congestion and the latency in subsequent requests. Ensure that you have Keep-Alive enabled for your endpoint to reduce the overhead of receiving concurrent requests.
Consider building a reconciliation job if you can't afford to miss webhooks
Anchor link to section titled "Consider building a reconciliation job if you can't afford to miss webhooks"In instances where you can't provide a response in less than five seconds, Shopify recommends queuing your webhooks. Your queue should be persistent. Common practice here is also to build a reconciliation job that retrieves the data that is important for you, and you might have missed, periodically using our APIs.
Shopify will always try to re-deliver your webhooks even if they are failing
Anchor link to section titled "Shopify will always try to re-deliver your webhooks even if they are failing"Shopify waits five seconds for a response to each request to a webhook. If there's no response, or an error is returned, then Shopify retries the connection 8 times over the next 4 hours. If there are 8 consecutive failures, then the webhook subscription is automatically deleted if it was configured using the Admin API.
Warning emails that the subscription is failing, and could be deleted, are sent to the app's emergency developer email address. This is the email address that was used to create your Partner account.
You can learn more about troubleshooting your webhooks in the Troubleshoot your webhooks guide here.
Step 2: Validate the origin of your webhook to ensure it's coming from Shopify
Anchor link to section titled "Step 2: Validate the origin of your webhook to ensure it's coming from Shopify"Before you respond to a webhook, you need to verify that the webhook was sent from Shopify. You can verify the webhook by calculating a digital signature.
ShopifyApp abstracts this from you with the authenticate method, which also validates the origin.
If you use the default REMIX template, then this is already prepared for you right before processing the webhook with the following line:
If you just want to validate, then you can make the call yourself.
Each webhook includes a base64-encoded X-Shopify-Hmac-SHA256
field in the payload header, which is generated using the app's client secret along with the data sent in the request.
Compute the HMAC digest according to the following algorithm. This code snippet is specific to Javascript.
Compare the computed value to the value in the
X-Shopify-Hmac-SHA256
header. If the HMAC digest and header value match, then the webhook was sent from Shopify.For that means, ket the ShopifyApp library pick up the appropriate header, stringify, and parse the request payload:
If you needed a finer-grained implementation, then you can also check the library documentation for webhooks and validation.
Common pitfalls and nuances to be aware of during validation
Anchor link to section titled "Common pitfalls and nuances to be aware of during validation"Raw Body Parsing: Shopify's HMAC verification requires the raw request body. If you're using a body parser middleware like
express.json()
, it will parse the body before your webhook verification code gets to it. You need to capture the raw body before it's parsed.Buffered Raw Body: You should use the raw buffered body for the HMAC calculation.
Middleware Order: Ensure that your webhook verification middleware is placed before any body parsing middleware in your app.
Encoding: Ensure your encoding is set properly.
Step 3: Queue your webhooks to process later in case of bursts of traffic
Anchor link to section titled "Step 3: Queue your webhooks to process later in case of bursts of traffic"Queuing is a useful pattern to also handle occasional bursts of traffic. To queue, you can install a package like Better Que (or similar for the programming language of your choice) to store the webhook payload in a message queue to process later.
Queuing reduces the chance of the request timing out and having the webhook delivery count as a failure. This should enable your app to respond quickly, and for your job to take as long as it needs to complete, ensuring that your system is resilient to a high volume of requests.