All Tutorials

Build a Shopify App with Node and React

Listen for store events with webhooks

Webhooks are a useful tool for apps that need to listen and act on specific events that happen in a store. You’ll be using the Koa Shopify webhooks package to register and receive Shopify webhooks. This package uses the GraphQL Admin API and the webhook subscription mutation to register webhooks, so make sure to use the supported topics for GraphQL webhook subscriptions.

The General Data Protection Regulation (GDPR), which went into effect on May 25, 2018, imposes obligations on any party that collects, stores, or processes personal data of individuals located in Europe. Shopify, however, mandates these regulations for all user data, both for individuals located in Europe and those located elsewhere. Each app developer is responsible for making sure that the apps they build for the Shopify platform are GDPR compliant. Three webhooks are mandatory at Shopify and must be added to every app.

Validate and register your webhook

  1. Navigate to the app section in your partner account. Click on your app and head to app setup. Scroll down to Webhooks and ensure you're using the latest version of the API.

    admin alt
  2. Make sure ngrok is running, and that you’ve added the HTTPS version of your ngrok forwarding URL to your .env file:
  3. Install @shopify/koa-shopify-webhooks and koa-router:
                npm install --save @shopify/koa-shopify-webhooks koa-router
  4. In .server.js, import @shopify/koa-shopify-webhooks:


    code contained in /server.js
    require('isomorphic-fetch'); const dotenv = require('dotenv'); const Koa = require('koa'); const next = require('next'); const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth'); const { verifyRequest } = require('@shopify/koa-shopify-auth'); const session = require('koa-session'); dotenv.config(); const { default: graphQLProxy } = require('@shopify/koa-shopify-graphql-proxy'); Add:const Router = require('koa-router'); Add:const {receiveWebhook, registerWebhook} = require('@shopify/koa-shopify-webhooks');
  5. In your server.js file, add your HOST variable to the deconstructed variables from your .env file


    code contained in /server.js
    ... const { receiveWebhook, registerWebhook } = require('@shopify/koa-shopify-webhooks'); const getSubscriptionUrl = require('./server/getSubscriptionUrl'); const port = parseInt(process.env.PORT, 10) || 3000; const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY, Add: HOST, } = process.env; app.prepare().then(() => { ...
  6. In your server.js file, register a webhook for product creation:


    code contained in /server.js
    async afterAuth(ctx) { const { shop, accessToken } = ctx.session; ctx.cookies.set('shopOrigin', shop, { httpOnly: false secure: true, sameSite: 'none' }); Add: const registration = await registerWebhook({ Add: address: `${HOST}/webhooks/products/create`, Add: topic: 'PRODUCTS_CREATE', Add: accessToken, Add: shop, Add: apiVersion: ApiVersion.October19 Add: }); Add: if (registration.success) { Add: console.log('Successfully registered webhook!'); Add: } else { Add: console.log('Failed to register webhook', registration.result); Add: }
  7. Stop your server, navigate to the Apps section of your Shopify Admin, and uninstall your app from your store. Apps section of the development store Admin circling the sample embedded app's garbage icon
  8. Reinstall your app on your development store:

  9. Upon registration, your server console should log: Successfully registered webhook! console alt

Create a webhook subscription and receive a webhook

Now that you’ve registered the request, you can now subscribe and recieve a webhook. Since we’re using Koa router to make POST requests to the Shopify Billing API, we’ll be referencing the koa-router and multiple webhooks example.

  1. Set up your server.js file to receive webhooks when a product is created:


    code contained in /server.js
    await getSubscriptionUrl(ctx, accessToken); }, }), ); Add: const webhook = receiveWebhook({secret: SHOPIFY_API_SECRET_KEY}); Add:'/webhooks/products/create', webhook, (ctx) => { Add: console.log('received webhook: ', ctx.state.webhook); Add: }); server.use(graphQLProxy());
  2. Send verify.Request() and the app code through the router:


    code contained in /server.js
    server.use(graphQLProxy({version: ApiVersion.October19})) Remove: server.use(verifyRequest()); Remove: server.use(async (ctx) => { Remove: await handle(ctx.req, ctx.res); Remove: ctx.respond = false; Remove: ctx.res.statusCode = 200; Remove: }); Add: router.get('*', verifyRequest(), async (ctx) => { Add: await handle(ctx.req, ctx.res); Add: ctx.respond = false; Add: ctx.res.statusCode = 200; Add: }); Add: server.use(router.allowedMethods()); Add: server.use(router.routes()); server.listen(port, () => {
  3. Stop and restart your server to render the changes to your server.js file.

    In a production app, you would need to store the webhook in a database to access the response on the frontend.

  4. Navigate to the Products section in your development store’s Shopify admin.
  5. Click Add Product, enter at least a Title and Price, and then click Save.
  6. Your server console should now print out a success message: received webhook: { topic: 'YOURWEBHOOKTOPIC', domain: 'YOURSHOPIFYSTORE' }
  7. console alt subscription

Next steps

Congratulations on completing the tutorial! You’ve learned the basics of building a Shopify app. Want to learn more? Check out these additional resources: