Hello! Welcome back to the course.
In our last lesson, we established the "why" behind webhooks. You learned that they are an efficient, event-driven alternative to constant polling, allowing your app to receive real-time notifications from Shopify. We covered the core concepts of topics, subscriptions, and payloads.
Today, we transition from theory to practice. The natural next question is: "How do I actually tell Shopify to send these notifications to my app?" This lesson is dedicated to answering that question. By the end of our session, you will be able to register a webhook for a specific topic (e.g., orders/create).
We'll focus on the hands-on process of configuring your Shopify app to subscribe to an event, laying the groundwork for the powerful, real-time features you'll build.
How an App Subscribes to Webhooks
In the previous lesson, we used the analogy of giving a delivery company your phone number. For a Shopify app, this "phone number" is a public URL endpoint, and the "act of giving it" is called registering a subscription.
There are a few ways to do this:
- Via the Shopify Admin UI: You can manually create a webhook subscription in your store's settings. This is useful for quick, one-off tests but is not a scalable solution for an app that will be installed on many stores.
- Programmatically via API: Your app can use the Admin API to create webhook subscriptions after it has been installed. This is a flexible approach for when subscriptions need to be managed dynamically.
- Declaratively via Configuration: The Shopify CLI allows you to declare your app's required webhook subscriptions directly in a configuration file. When you deploy your app, the CLI ensures these subscriptions are created.
For building a distributable app, the declarative and programmatic methods are the most important. We'll focus on the modern declarative approach, which is the current best practice for the Shopify CLI, and supplement it with the programmatic handler logic from the CLI template.
The Two Sides of Webhook Registration: The Subscription and The Handler
Registering a webhook in a modern Shopify app involves two distinct but connected steps:
- The Subscription (Configuration): You must tell Shopify which topic you are interested in and what URL (
uri) to send the notification to. We'll do this declaratively. - The Handler (Code): You must write the code in your Node.js application that will execute when a notification arrives at that URL. This is the function that actually does something with the webhook data.
Let's explore each part.
1. The Subscription: Declarative Registration with shopify.app.toml
The Shopify CLI uses a configuration file, shopify.app.toml, to manage your app's core settings. This is the recommended place to define webhook subscriptions that are static and apply to every store that installs your app.
This declarative approach is powerful because it makes your app's requirements explicit and lets the Shopify CLI manage the registration process for you during development and deployment.
The official Shopify documentation on App configuration explains the structure of the shopify.app.toml file. Let's look at how webhooks are defined.
Please review this document. Start by looking at the 'App configuration file example' to see where the [webhooks] section fits. Then, scroll down to the 'Reference' section and read the details under 'webhooks' and its subsection 'subscriptions'. Focus on the topics and uri properties.
As you saw in the documentation, you can define a [[webhooks.subscriptions]] block. To subscribe to the orders/create topic, you would add the following to your shopify.app.toml file:
# In shopify.app.toml
[webhooks]
api_version = "2024-04" # Or your target API version
[[webhooks.subscriptions]]
topics = [ "orders/create" ]
uri = "/api/webhooks"
topics = [ "orders/create" ]: This tells Shopify we are interested in theorders/createevent.uri = "/api/webhooks": This is a relative path. The Shopify CLI combines this with your app's tunnel URL during development (e.g.,https://your-tunnel-url.trycloudflare.com/api/webhooks) to create the full callback URL that it registers with Shopify. This endpoint is a route in your Express.js application.
2. The Handler: Processing Webhooks in Your App
Declaring the subscription is only half the story. Now we need to implement the code that runs when Shopify sends a POST request to /api/webhooks.
The Shopify app template generated by the CLI comes pre-configured with a central webhook processing system. You don't need to create the /api/webhooks route yourself; you just need to "plug in" your handler logic for the specific topic.
The following video demonstrates this process clearly. While the video might use a slightly older version of the CLI template where webhooks were configured entirely in code, the core concept of adding a handler function remains identical and is an excellent visual guide.
Handling Webhooks in Your Shopify App: HTTP + Amazon EventBridge
The video 'Handling Webhooks in Your Shopify App' by Dev With Alex provides a fantastic step-by-step guide to adding a webhook handler to a CLI-generated app. We will adapt this method for our orders/create webhook.
Watch the segment from 01:50 to 05:00. Pay close attention to how a new webhook topic (products_update in the video) and its corresponding callback function are added to the shopify.config.webhooks object. This is the pattern we will follow.
Based on the pattern in the video, you would find the shopifyApp configuration in your main server file (likely web/index.js). Inside the webhooks object, you can add your handler.
The Shopify API library for Node.js provides an object containing all webhook topics, which ensures you use the correct topic names. Here's how you would add a handler for orders/create:
// In web/index.js (or your main server file)
import { WebhookTopic } from "@shopify/shopify-api";
// ... inside the shopifyApp() configuration object
webhooks: {
path: "/api/webhooks",
// Add your new handler here
[WebhookTopic.OrdersCreate]: {
deliveryMethod: DeliveryMethod.Http,
callbackUrl: "/api/webhooks",
callback: async (topic, shop, body, webhookId) => {
console.log("--- New order received! ---");
const payload = JSON.parse(body);
console.log(`Shop: ${shop}`);
console.log("Payload:", payload);
console.log("--------------------------");
// In the next lesson, we'll do more than just log this.
},
},
// Keep the existing mandatory GDPR webhooks...
},
// ... rest of the file
A key point: The body of the webhook often arrives as a string. You need to use JSON.parse(body) to convert it into a JavaScript object you can work with.
Hands-On: Register and Test Your First Webhook
Now, let's put it all together.
1. Define the Handler:
- Open your Shopify app project in your code editor.
- Navigate to
web/index.js. - Locate the
webhooksproperty within theshopifyApp()configuration object. - Add the handler for
WebhookTopic.OrdersCreateas shown in the code block above. Make sure to importWebhookTopicfrom@shopify/shopify-api.
2. Declare the Subscription:
- Open the
shopify.app.tomlfile at the root of your project. - Add the
[webhooks]and[[webhooks.subscriptions]]sections as shown earlier to subscribe toorders/create.
3. Test the Webhook:
- Run your app with
npm run dev. - In a separate terminal, you can now use the Shopify CLI to simulate an
orders/createevent. This is an incredibly useful feature for local development, as you don't need to create real orders.
Handling Webhooks in Your Shopify App: HTTP + Amazon EventBridge
The same video from Dev With Alex also shows exactly how to use the CLI to trigger a test webhook. Let's watch how it's done.
Watch the segment from 05:50 to 07:25. Observe the npm run shopify webhook trigger command and the prompts that follow. This will guide you through testing your own webhook.
Now, run the command yourself:
npm run shopify webhook trigger
Follow the interactive prompts:
- API Version: Choose the same one you set in
shopify.app.toml. - Topic: Search for and select
orders/create. - Delivery Method: Choose
HTTP. - Address: Your
devserver will be running on a Cloudflare tunnel. The CLI should detect this and suggest the correct address (e.g.,https://your-app-name.trycloudflare.com/api/webhooks). Confirm this.
After you run the command, you should see the console.log messages from your handler appear in the terminal where your dev server is running. Congratulations, you've successfully registered and received your first webhook!
Test your understanding!
You now need to be notified whenever a customer's record is updated in the store. What two specific changes would you need to make to your application code and configuration to achieve this?
Show answer
- In
shopify.app.toml: You would add another subscription for thecustomers/updatetopic.[[webhooks.subscriptions]] topics = [ "customers/update" ] uri = "/api/webhooks" - In
web/index.js: You would add a new handler forWebhookTopic.CustomersUpdateinside thewebhooksconfiguration object, with its own callback function to process the customer data.
Conclusion
In this lesson, we bridged the gap from theory to practice. You now have the essential skill of registering a webhook, a fundamental building block for any app that needs to react to store events.
Key Takeaways:
- Webhook registration in a modern Shopify app involves a declarative subscription in
shopify.app.tomland a programmatic handler in yourweb/index.jsfile. - The
shopify.app.tomlfile tells Shopify what event to watch for and where to send the notification. - The handler function in your code defines what to do with the notification when it arrives.
- The Shopify CLI is your best friend for local testing, allowing you to trigger fake webhook events with the
webhook triggercommand, saving you from having to perform real actions in your store.
Next Steps
Right now, our webhook handler simply logs the incoming payload to the console. While this proves our connection works, it's not very useful. Furthermore, our endpoint is public, and we haven't verified that the requests are actually coming from Shopify.
In the next lesson, we will focus on building out a proper handler. You will learn how to create a webhook handler endpoint in Express.js to process incoming webhook payloads, which will include the most critical step in webhook security: verifying the HMAC signature to ensure the data is authentic and secure.