February 13, 2024
•9 minutes read
Shopify webhooks: what they are and how to use them
How to create and listen for webhooks from Shopify.
1. What are webhooks?
Webhooks are a powerful tool for integrating third-party services with your application. They offer a way for these services to notify your application in real-time when something important occurs. In the world of Shopify Apps, webhooks allow you to get notified about events within a store that installed your app. For example, Shopify can let you know when an order gets placed in a store, or when a customer's profile gets updated.
There are actually hundreds of events or "topics" you can listen for via Shopify webhooks. Check out this page for a comprehensive list.
Webhooks versus normal API calls
You might wonder why use webhooks instead of hitting the Shopify API directly.
After all, any information you can read via a Shopify webhook you could also
read from API endpoints. For example, if you're interested in tracking the
latest orders placed by one of the stores that installed your app, you could use
the /orders.json
endpoint of their REST Admin API, like so:
This should return you all the orders of a store which were placed since TIMESTAMP
.
Alternatively, you could create a webhook for the topic orders/create
and ask
Shopify to let you know, by making a request to your server, whenever a new
order is placed.
Compared to the first approach, using a webhook offer several advantages. First,
they are real-time, meaning you don't have to wait until you hit /orders.json
for a particular store to hear about new orders. That also makes them easier to
reason about, because you don't have to worry about frequently hitting the API,
for each client store, nor keeping track of where you left of etc. Finally,
webhooks also make your server more resource-efficient because Shopify is
reaching out to you instead of the other way around.
Webhooks have their own downsides, however, especially when it comes to data integrity. We will talk more about this below.
Who this guide is for
This guide is aimed at app developers looking to build better integrations with Shopify stores. Webhooks can also be relevant for store owners, who should check out this Shopify guide here. Throughout this guide, we'll use Typescript and HTTP in our code examples. Even if you're not familiar with these technologies, the concepts and logic should be easily transferrable to other programming languages.
2. Creating Shopify webhooks
To register Shopify webhooks, we'll need to use the Shopify Admin API. In Shopify, webhooks are isolated at a store level. That means you'll need to register individual webhooks for each store you weant to receive notifications from. Let's dive right into a practical example.
Example: Slack notifications for Shopify
Suppose you're building a Shopify app that notifies store owners via Slack
whenever an order gets created or updated on their store. The app store is
filled with apps that do
this. As
we've seen, you have two options. You can frequently query the /orders.json
endpoint of the Shopify Admin API to check for new orders. Or, the superior
alternative, you can use webhooks to ask Shopify to let you know whenever a new
order gets placed in a store. We'll go with webhooks.
To manage webhooks via the REST Admin API, we'll need two things to start:
- The "myShopify" domain of a particular store. This is the unique identifier of
a store within the Shopify ecossystem, always in the format
STORE.myshopify.com
. You can read more about this here. - The "access token" for that store, which is required to authenticate the call. You obtain this when a store installs your app via OAuth.
Need help using OAuth to obtain the access token for a store? Check out our open-source project Handshake, a self-hosted solution for handling OAuth for Shopify and dozens of other APIs. It's built for easy self-hosting on Vercel.
With these credentials at hand, here's our code for registering webhooks.
Let's break it down. The registerWebhookTopic
takes in the credentials of a
particular store, together with a webhook "topic" and an endpoint to receive
Shopify requests. It then makes a POST
request to
https://${shopifyDomain}/admin/api/2024-01/webhooks.json
to create the webhook
object and begin to receive updates.
This code subscribes to four topics (ie. events) we are interested in:
orders/create
, orders/paid
, orders/fulfilled
, and orders/updated
. To
read about all the available topics and what causes Shopify to trigger them,
check out their API
documentation.
It's important to note that webhooks in Shopify have scope requirements. For
example, orders/create
requires the access token to allow the read_orders
scope, as well as access to the new "Protected Customer Data"
permission.
3. Receiving webhooks locally
So far we've covered how to register webhooks but not what it looks like when a webhook gets fired to your endpoint. And since every software development begins locally, we'll start by talking about how to receive webhooks to your computer.
Writing a webhook listener
Let's create a simple server using Fastify to receive webhook requests and print out their content.
Shopify requires you to respond to webhook requests with HTTP status 200, to indicate that the message was succesfully acknowledged. You must also do so within two seconds. Failure to respond with 200 in two seconds will cause Shopify to consider this webhook delivery as failed.
Exposing your listener to the world
One major challenge when working locally is that Shopify cannot directly deliver data to your localhost. This is for a variety of reasons. Your computer is behind a myriad of barriers like ISPs, routers, and firewalls. These not only make it hard to reach your machine but also to uniquely identify it (as "localhost:4000" is anything but unique).
Using Ngrok
To solve this, we'll need to use a tool like Ngrok. Ngrok allows you to route a
public URL, such as fiber-dev.ngrok.io
, to a server running in your localhost.
It does so via a mechanism called "reverse proxying", which is beyond the scope
of this article.
To install ngrok on Mac OS using Homebrew:
Head to ngrok.com/download to read instructions for installing Ngrok in other setups.
With Ngrok installed, you can expose a server running on port (eg. 4000) with the following command:
You should see output like the following:
ngrok-site
With this running, you can go navigate to fiber-dev.ngrok.io
or whatever your
public URL is on your browser. If you don't have a server running on 4000, you
will see the following error. This indicates Ngrok is running as expected.
ngrok-terminal
Now you're ready to go back to the registration code of the previous section and
replace the WEBHOOK_ENDPOINT
definition with your Ngrok URL eg.
https://fiber-dev.ngrok.io
.
Now we can run your server (here we're using Bun):
Sending a test request
Now, with the server running, we are ready to test the webhook handler we created. In a separate terminal session, fire a request to create a new order object:
You should see a log like this pop up on your server:
That's it! At this point, your server has been able to receive and acknowledge an incoming webhook. This same mechanism can be used to receive all the events we've specified.
In the next post of this series on webhooks, we will cover verifying the source of webhooks and how to safeguard your servers against malicious requests.