To get the most out of this tutorial, you will need
A Shopify merchant needs an automated way to tag products being added to their Shopify store inventory. They source hundreds of products weekly from various dropshippers and upload the unstructured data to Shopify programmatically. Because the data is unstructured, Shopify is unable to power the merchant's storefront search. While the merchant can add tags inside the Shopify Admin, the experience of doing this on hundreds of products weekly is time-consuming.
To solve this, the merchant wants to build a custom Shopify app on Gadget that will run every new product description through an automated tagging script.
In this example, we'll show you how to build a custom product tagging system that listens to the product/create and product/update webhooks from Shopify, runs product descriptions through a tagging script, and sets tags back in Shopify.
Our first step will be to set up a Gadget project and connect our backend to a Shopify store via Shopify Connections. Create a new Gadget application.
To connect our Gadget backend to a Shopify store:
At this point, Gadget copies the selected Shopify models, their types, validations and associations into your Gadget backend. These models are ready to process webhooks as soon as you install the app on a Shopify store.
We opted to install this app on our development store, using the Test on Development Store link on our Shopify Partners dashboard. Gadget handles OAuth for us, all we need to do is grant permission to the API scopes and the connection is made.
The next step is to create a list of vetted keywords that we can use to power our tagging script. These keywords can be different types of products or brands. Make sure to add keywords that will be found in your products' descriptions!
Gadget instantly creates and documents a GraphQL CRUD API for this model.
Using the API Playground, we can make a Create call to our Allowed Tag model in order to store a new keyword.
We can run the same mutation again with a different keyword value to store additional keywords.
We can also check to make sure our tag keywords have been saved. Go to the Data page for the Allowed Tag model and you should be able to see an entry for any tags that have been added.
Gadget keeps your app and store in sync by generating a CRUD (Create, Read, Update, Delete) API around each of your cloned models and wiring up each of the API actions to their corresponding Shopify webhook. If the Shopify store fires a product/create webhook, Gadget will run your Create action on the Product model. By default, this action uses the incoming params from the webhook to create a record in your database. Similarly, if Shopify fires the product/update webhook, Gadget will run your Update action which updates the record with the incoming params.
What makes Actions special is that they can be completely customized. You can change what happens when the action runs by adding Code Effects that you define.
Now that we have keywords to check against, we can write our tagging script. Because we want this script to run every time a product record is created or updated, we'll add an Effect to the Create and Update actions on the Shopify Product state machine:
Use the following snippet to run every create webhook through your tagging script, which cross-references the body of the incoming payload against the keyword list by making an internal API request to Gadget. Should any words match, they're sent back to Shopify as new tags for the product. Make sure to replace the placeholder with your store's name.
That's not a lot of code!
Gadget gives us a connections object as an argument to our effect function, which has an already authenticated API client for Shopify ready to go. We use this object to make API calls back to Shopify to update the tags and complete the process.
We also use Gadget's changed helper on our record to avoid entering an infinite loop. This looping can occur when a Shopify webhook triggers a Code Effect that updates our Shopify store. Because we have added this change detection, we can add the same applyTags.ts file as a Success Effect on the Update action.
The record.changed helper is a special field that Gadget has included to help prevent an infinte loop when updating Shopify records.
When we call shopify.product.update(...) the product in our Shopify store will be updated. This update action will fire Shopify's products/update webhook. If we are using this webhook as a trigger for running custom code that updates a product, we will be stuck in an endless loop of updating our products and running our custom code.
We can use record.changed to determine if changes have been made to the key on this record and only run our code if changes have occured.
For more info on change tracking in Gadget, refer to the documentation.
We're done, let's test it out!
Go back to the Connections page and click Sync on the connected store. Gadget will fetch each of the records in Shopify and run them through your actions. Not only will this populate your Gadget backend with the store's inventory, but it will also run the effects we added, updating the tags for each synced product. Our tagging application will also run on products when they are added to the store, so any new products will also be tagged for us automatically.
In about 10 minutes, and with under 10 lines of code, we were able to build a custom app that updates tags in Shopify each time there is a match against our Allowed Tags list.