Working with Shopify webhooks 

Shopify webhooks in Gadget are used to keep your Gadget application and Shopify store data in match. When an event occurs in your Shopify store, such as the creation, update, or deletion of a product, Shopify sends a webhook to your Gadget application. This webhook contains information about the event that just happened.

In Gadget, each Shopify model has corresponding Actions (Create, Read, Update, Delete) that are triggered by these webhooks. For instance, if Shopify sends a products/create webhook, Gadget will run the Create action on the Product model in your app. This action typically uses the incoming parameters from the webhook to create a new record in your Gadget database.

To handle these webhooks:

  1. Gadget verifies the authenticity of the webhook to ensure it's coming from Shopify.
  2. It then triggers the corresponding Action associated with the webhook event.
  3. The complete payload of the webhook is accessible within the trigger object passed to your Action code, allowing you to use the data within your Action's logic.
  4. If an Action fails, Gadget will retry it up to 10 times with increasing delays between attempts. If the Action fails on the last attempt, the webhook is considered "lost", though Gadget will later attempt to automatically reconcile the missing webhook with Shopify.

Reconciliation of webhooks 

As described in the above process, in the case when a webhook fails or is missed, Gadget automatically catches the missed webhook during a daily reconciliation, and re-runs the corresponding action.

Effectively, this means that your data will always go back in sync with Shopify, even after an outage, because of the automated reconciliation that is built into our webhook processing.

Disable webhook processing per shop 

You may want to limit/restrict which webhooks are processed. Certain Shopify shops generate a ton of webhooks. Processing and storing these webhooks can add up to be quite the cost for developers especially since you do not want to pay to process and consume webhooks for all models for all shops that have installed your app. For example, within your Shopify app, you may want to disable certain webhooks from processing on Shopify models for free trial users so you do not end up adding up your costs for users on your free trial.

Within Gadget, you can disable certain webhooks from processing so you have greater control over your app. Every shopifyShop model has a disabledWebhooks field which is a boolean value set to false by default. When the value is changed to true this will disable webhooks within the scheduled sync from syncing data concerning the model associated with the disabledWebhooks value changing.

For example, let's take a look below at our update action with our shopifyShop model where within the run function we'll set our disabledWebhooks field to true when it's a shopifyProduct model. What we've defined here is any reconciliation sync going forward on webhook reregistrations will disable webhook processing and won't sync data for the shopifyProduct model. If we also head to our shopifyShop data we'll notice within the registeredWebhooks column that the shopifyProduct is no longer associated with its value.

JavaScript
1/**
2 * @param { UpdateShopifyShopActionContext } context
3 */
4export async function run({ params, record, logger, api, connections }) {
5 applyParams(params, record);
6
7 record.disabledWebhooks = { shopifyProduct: true };
8 // Disabling all webhooks that sync data for the shopifyProduct model
9
10 await preventCrossShopDataAccess(params, record);
11 await save(record);
12}
13
14/**
15 * @param { UpdateShopifyShopActionContext } context
16 */
17export async function onSuccess({ params, record, logger, api, connections }) {
18 // Your logic goes here
19}
20
21/** @type { ActionOptions } */
22export const options = {
23 actionType: "update",
24};

You have to explicitly set a model associated with the disabledWebhooks field value change like the above example, it will not work if you just flip the boolean value to true.

Handling deletion webhooks 

Any deletion webhooks will call the delete Action on the model, along with running the delete Action for all Shopify records associated with that model. For example, when a product is deleted, we delete all of its options, images, and variants. All other webhooks will call either the create or update Action, based on whether or not the record currently exists in Gadget.

Registering Shopify webhooks 

To ensure your Shopify app receives the necessary events from a store, you need to register webhooks for specific topics. Here are the scenarios when you should register Shopify webhooks:

  1. When Editing Connections: If you edit a connection to include new models, you may need to register new webhooks for those models. For example, if you add the Collection model, you should register webhooks for collections/create, collections/update, and collections/delete.

  2. When Missing Webhooks: If you notice that certain webhooks are not registered, as indicated on the Installs page, you should register the missing webhooks. This can happen if you are missing access scopes or topics/namespaces for your registered webhooks.

  3. After Re-authentication: If you have edited your connection to require additional scopes, you will need to re-authenticate your app for all stores on which it is installed. After re-authentication, you should register any new webhooks associated with the new scopes.

  4. API Version Upgrade: Shopify releases a new API version every 3 months, and when you upgrade your Shopify Connection's API version, you should ensure that your webhooks are still correctly registered for the new version.

  5. When Accessing Protected Customer Data: If you are using an Event subscriptions version later than 2022-07, you will need to request access permissions in the Protected customer data access section on the API access page of your Shopify app. After completing the required sections, return to your Gadget app and register the webhooks.

To register Shopify webhooks, you can navigate to the Installs page for your Connection in Gadget, click the More button (…) for any stores you have re-authenticated, and select the Register Webhooks option like below:

how to register Shopify webhooks