The syncing system for the Shopify Connection works by leveraging actions. Each time Gadget goes to sync the connected shop, Gadget creates a new Shopify Sync record and dispatches the Run and either the Complete or Error Actions based on the outcome of the sync.
There are three types of syncs for the Shopify connection: API-triggered, Manual and Scheduled.
API-triggered Syncs
An API-triggered sync can be initiated via the GraphQL API, JS clients, or the api object in the actions code. There are many ways that you can use API-triggered syncs. The three main ways are after a shop installation, on a model's action, and syncing data within a specified date range.
Do not add API-triggered syncs to the shopifySync model
Avoid adding an API-triggered sync to the shopifySync model's actions! This will cause an infinite loop of syncs. Instead, we recommend
adding API-triggered syncs to the shopifyShop model's install action to sync store data on app installation, or using a custom action
to trigger data syncs.
Sync on shop install
It may be necessary to run an initial sync upon installation. For example, you may want to display all products on a user interface immediately after a merchant installs your app. To do this, use the onSuccess function on the Shopify Shop model's install action with the following code:
You can optionally pass a models parameter to the runSync call to specify which particular Shopify models to sync. For example, if you wish to sync all products in your backend, but not orders, the models should be passed as an array of model API identifiers. If the models parameter is omitted or is an empty array, all Shopify models will be synced.
You may want to limit syncing to recent records. To do this, you can pass the syncSince parameter to indicate which records Gadget should sync. Gadget will check the shopifyUpdateAt field for each Shopify record, and only sync records created or updated within the specified window. Without this parameter, the API-triggered sync will copy every record to Gadget, regardless of when it was created or updated.
A sync will not update any fields or run any actions if the shopifyUpdatedAt value in the payload is less than or equal to the shopifyUpdatedAt value currently stored on the record. There are certain situations, such as Shopify API version upgrades, where you may want to backfill new values or re-run your actions on existing records. In these situations, you can run a sync with the force field set to true. A forced sync will update all values and re-run all actions on applicable records.
For applications on framework versions prior to framework v0.3.1 after connecting to Shopify, a globalShopifySync global action has been added to your Gadget app. This global action runs a forced sync across all stores your app has been installed on.
If you go to Global Actions, then select the globalShopifySync action and click Run Action, you will be brought to the API Playground with the globalShopifySync mutation loaded for you. To run a forced sync, you need to include "force": true in your variables, as well as the Client ID (aka API Key) of your connected Shopify app. You can also include syncSince and models variables to limit the scope of the sync.
Variables for the scheduledShopifySync mutation
json
{
"apiKeys":["<your Shopify app's API key>"],
"force":true
}
You can also run a forced sync on an individual store in JS or GraphQL by writing a custom action:
A sync will be queued (without a syncSince set) when clicking the "Sync" button next to your Shopify connection. This will make a call to the Shopify Sync model's Run Action.
This sync may take some time to complete, depending on how much data the shop has.
Scheduled syncs
When adding a Shopify Connection, you may have opted to connect to Shopify models that do not offer webhooks. Gadget refers to these as sync-only models, meaning that they can only be kept up to date by running a sync on a schedule.
Once the sync runs Gadget will automatically fetch all recent data on a schedule in the background as defined within the scheduler trigger within the scheduledShopifySync global action. If the sync fails or has scheduling issues, there's a possibility you may not have the most up-to-date data in Gadget. If this does occur, check the Shopify Sync data viewer or logs via the Sync History to identify any errors.
If you add any sync-only models to your Shopify connection, Gadget will automatically place a global action called scheduledShopifySync in your project's global actions folder.
This action allows you to control how the scheduled sync is run.
It calls on the globalShopifySync function to run the sync process. This function takes in the following parameters for the sync:
apiKeys: the list of Shopify APP API keys to trigger a sync for
syncSince: the start date to start syncing data from, by default: In the action code we create a new Date object representing a specific point in time, const syncSince = new Date(Date.now() - 25 * HourInMs) sets syncSince to a Date object that represents the time exactly 25 hours before the current time. The reason we've set the start of the sync to 25 hours before the current time is as a best practice to leave additional leeway time to avoid any possible errors there might be in the exact timing of the sync.
models: the list of model API identifiers to trigger syncs for, by default: We create a syncOnlyModels object that maps through an array of the existing available models with the Shopify connection and filter through identifying for sync-only models
You can also edit the rest of the action to configure it to your preference, by default the action is scheduled to run daily but you can configure the time it's run, head to the scheduler trigger associated with the action and set a time interval of your preference, like below:
If you also want to configure and add additional models to be synced with the sync-only models, you can do so by adding your custom preference in the models param as an array like below:
12//You have to pass the model params as an array of strings
13});
14}
if you want to remove a sync-only model from being included in the scheduled sync, then head back to the Shopify connection's settings page to edit your API scopes and simply unselect the model.
Do not remove the `globalShopifySync` function
Although the action is customizable avoid removing the globalShopifySync function from the code file as that mainly operates how your
Shopify data is being synced.
Removing your Shopify connection will not remove the scheduledShopifySync action file you must remove that yourself if left untouched
the action will simply break when run on the defined schedule
Applications on frameworks prior to v0.3.1
If your application is on a framework version before v0.3.1 the global action added to your app upon connecting to Shopify is known as the globalShopifySync which operates very similarly to scheduledShopifySync.
If users upgrade their applications framework version to v0.3.1 they will receive the scheduledShopifySync global action but you will also have your globalShopifySync action as well, but feel free to remove it or move any existing custom code to the scheduledShopifySync action as it is now redundant in use after upgrading.
Sync-only models
Several Shopify models are sync-only. This means they are not created or updated through webhooks, and are updated exclusively during a sync operation that is scheduled or manually triggered.
A small number of fields on Shopify models are also sync-only. This means that they are not created or updated on webhooks, but are set only during a sync. To handle changes to these fields you can detect the trigger type in your onSuccess function by checking the trigger property in the action context.
JavaScript
1exportasyncfunctiononSuccess({
2 api,
3 record,
4 params,
5 logger,
6 connections,
7 trigger,
8}){
9if(trigger.type=="shopify_sync"){
10// do something with a sync only field
11}
12}
For models that support webhooks, sync-only fields will initially be null when a record is first created via a webhook. These fields are populated during the nightly reconciliation sync process.
If you need these fields to be populated immediately you should fetch the data yourself using the Shopify API and update the record manually.
To detect changes in sync-only fields and perform actions based on those changes, use the record.changed() method in your action code. For example:
JavaScript
1exportasyncfunctiononSuccess({
2 api,
3 record,
4 params,
5 logger,
6 connections,
7 trigger,
8}){
9if(record.changed("someField")){
10// This code will run when someField is updated during a sync
11 logger.info(`someField was updated to: ${record.someField}`);
If an error occurs during a sync, the Shopify Sync model's Error action will be called. For example, here's how you teach Gadget to alert you via SMS when a sync fails.
31body:`Shopify sync failed with message: ${params.shopifySync.errorMessage}`,
32});
33}
id is the Shopify Sync id that was created
errorMessage contains a generate description of the error or errors
errorDetails contains a all error messages (if more than 1 occurred) joined by a \n
The best way to debug why a sync may have failed is to search for errors through your logs. Use the following log query to filter by sync ID (replace {syncId} with ID of the sync that has failed):
If you've accidentally synced the wrong model or perhaps have a long ongoing sync, you do have the ability to abort a running sync.
During an ongoing sync, head over to your shopifySync model.
Select the abort action and then click Run Action
Then invoke your action within the GraphQL playground, and once ran, your sync is then successfully aborted
Adding the abort action to older shopifySync models
You only need to add the abort action to your shopifySync model if it was created before November 17, 2023 and you wish to enable the ability to abort a running sync
To add the abort action, head to your shopifySync model and create a new action called abort
Then paste the following code within the abort action code file