Shopify webhook signature verification often fails due to two main reasons: the HMAC is Base64-encoded (not hex), and the raw request body must be used before any JSON parsing. This article provides a thorough guide on how to implement correct verification, which secret to use, and how to avoid common pitfalls. Additionally, we will see how solutions from Q2BSTUDIO can help you build robust and secure integrations.
When Shopify sends a webhook, it includes a X-Shopify-Hmac-Sha256 header containing an HMAC-SHA256 computed over the raw request body (untouched bytes). The key for this HMAC is your app's client secret, found in the Partner Dashboard. The result is Base64-encoded—unlike Stripe or GitHub, which use hex. If you copy verification code from another service, it will likely fail because the encoding differs.
The first common mistake is verifying the HMAC after Express (or any framework) has already parsed the body with express.json(). Parsing alters the original bytes: whitespace is removed, property order changes, characters are normalized. The HMAC you compute over a re-serialized object will never match Shopify's. The solution is to capture the raw body before any parsing. In Express, use express.raw({ type: '*/*' }) on the webhook route. Verify the HMAC against that buffer, then parse the JSON manually only if valid.
The second mistake is using .digest('hex') instead of .digest('base64'). Most webhook verification examples (e.g., for Stripe or GitHub) use hex because those services deliver the signature in hex. Shopify uses Base64. If you only change the header name but keep hex encoding, the comparison will always fail. Ensure your code generates the HMAC in Base64 and compares it to the header value.
Another critical point is the comparison itself. Using a normal equality (===) can be vulnerable to timing attacks. Always use a constant-time comparison function, such as Node.js's crypto.timingSafeEqual. Before calling it, ensure both buffers have the same length, otherwise it throws an exception. Also, respond with a 401 status if the signature doesn't match; Shopify expects a quick 200 to consider the event delivered.
The secret used is also a frequent source of errors. Shopify signs with your app's client secret, not the API key or access token. If you have multiple apps (e.g., development and production), each has its own client secret. Verifying a webhook from one app with another's secret will always fail. Double-check that you are using the correct secret.
Beyond technical details, webhook reliability is a business challenge. If your server goes down, is mid-deployment, or takes too long to process an event, Shopify will retry up to 8 times over about 4 hours. If all retries fail, the webhook subscription is automatically disabled. This means you could lose critical events like orders, refunds, or fulfillments. This is where a robust architecture makes a difference.
At Q2BSTUDIO, we understand that technical infrastructure must be resilient. That's why we offer custom software development services that integrate message queues, exponential backoff retries, and dead-letter queues. We also implement cloud solutions with AWS or Azure to ensure high availability. Our teams apply advanced cybersecurity practices to ensure every webhook is correctly verified, preventing spoofing and replay attacks.
Moreover, artificial intelligence plays an increasingly important role in process automation. For example, we can train AI agents to analyze patterns in Shopify events and trigger custom actions in your backend. Combined with Business Intelligence dashboards (Power BI), this allows you to visualize order flows, returns, and business metrics in real time—all on a solid cybersecurity foundation that protects your data and your customers' data.
If you want to avoid the headaches of manual webhook management, consider outsourcing that reliability layer. Platforms like EventDock offer a single entry point that verifies, stores, and forwards events with delivery guarantees. But even if you decide to build your own system, the advice in this article will help you avoid the most common traps. Remember: raw body, Base64 encoding, and the correct secret are your best allies.
In summary, verifying a Shopify webhook is not complex, but it requires attention to three key details: capture the raw body before any parsing, use digest('base64'), and compare with timingSafeEqual. If you add a resilience layer with queues and retries, your integration will be much more robust. At Q2BSTUDIO we are ready to help you design that architecture, whether from scratch or improving an existing one. Contact us for a no-obligation consultation.





