Topics covered: Shopify connections, AI + vector embeddings, HTTP routes
Time to build: ~30 minutes
Large Language Model (LLM) APIs allow developers to build apps that can understand and generate text. We can use OpenAI's APIs to build a chatbot that can understand a shopper's question and respond with product recommendations.
In this tutorial, you will learn how to:
Requirements
To get the most out of this tutorial, you will need:
- A Shopify Partners account
- A development store
You can fork this Gadget project and try it out yourself. You will still need to set up the Shopify Connection and theme app extension after forking. Read on to learn how to connect Gadget to a Shopify store!
Your first step will be to set up a Gadget project and connect to a Shopify store via the Shopify connection. Create a new Gadget application at gadget.new and select the Shopify app template.
Our first step is going to be setting up a custom Shopify application in the Partners dashboard.
Both the Shopify store Admin and the Shopify Partner Dashboard have an Apps section. Ensure that you are on the Shopify Partner Dashboard before continuing.
Now we get to select what Shopify scopes we give our application access to, while also picking what Shopify data models we want to import into our Gadget app.
Now we want to connect our Gadget app to our custom app in the Partners dashboard.
Now you can install your app on a store from the Partners dashboard. Do not sync data yet! You're going to add some code to generate vector embeddings for your products before the sync is run.
Now that you are connected to Shopify, you can also set up the OpenAI connection that will be used to fetch embeddings for product descriptions. Gadget provides OpenAI credits for testing while building your app, so you don't need a personal OpenAI API key to get started.
Your OpenAI connection is now ready to be used!
Now we need a new data model to capture the chat responses from OpenAI, and the products recommended to shoppers. We need to use a <inline-code>has many through<inline-code> relationship to relate the chat response to the recommended products.
This string field will record the response coming back from OpenAI. We also want to keep track of the products that were recommended, so we need to add a has many through relationship to the <inline-code>shopifyProduct<inline-code> model.
Before you add code to create the embeddings from product descriptions, you need a place to store the generated embeddings. You can add a vector field to the <inline-code>shopifyProduct<inline-code> model to store the embeddings.
The vector field types store a vector, or array, of floats. It is useful for storing embeddings and will allow you to perform vector operations like cosine similarity, which helps you find the most similar products to a given chat message.
Learn more about OpenAI, LLMs, and vector embeddings
You are going to use Gadget's built-in OpenAI connection to generate vector embeddings for product descriptions. These embeddings will be used to perform a semantic search to find the products that best match a shopper's chat message.
LLMs and vector embeddings are relatively new technologies, and there are many resources available to learn more about them. Here are some resources to get you started:
- Building AI apps in Gadget
- Sorting by vector fields Gadget API docs
- OpenAI docs
To add a vector field to the <inline-code>shopifyProduct<inline-code> model:
Now you are set up to store embeddings for products! The next step is adding code to generate these embeddings.
Now you can add some code to create vector embeddings for all products in your store. You will want to run this code when Shopify fires a <inline-code>products/create<inline-code> or <inline-code>products/update<inline-code> webhook. To do this, you will create a code effect that runs when a <inline-code>shopifyProduct<inline-code> is created or updated.
In this snippet:
The internal API needs to be used because the <inline-code>shopifyProduct<inline-code> model does not have a Gadget API trigger on this action by default. You can read more about the internal API in the Gadget docs.
Now call this function from your <inline-code>shopifyProduct/actions/create.js<inline-code> and <inline-code>shopifyProduct/actions/update.js<inline-code> actions:
Now vector embeddings will be generated when a new product is created, or an existing product is updated.
Now that the code is in place to generate vector embeddings for products, you can sync existing Shopify products into your Gadget app's database. To do this:
Product and product image data will be synced from Shopify to your Gadget app's database. The code effect you added will run for each product and generate a vector embedding for the product. You can see these vector embeddings by going to the Data page for the shopifyProduct model. The vector embeddings will be stored in the descriptionEmbedding field.
Running into rate limit errors?
If you are running into rate limit errors when generating embeddings while syncing, try using your own OpenAI API key. You can add your own API key to the OpenAI connection by clicking on the Settings tab in the OpenAI connection and selecting the Use my own API key option.
We will use an HTTP route to handle incoming chat messages from the storefront. The route will take a message from the shopper, use cosine similarity to determine what products to recommend, and stream a response from OpenAI back to the client.
Your app now has a new HTTP route that will be triggered when a POST request is made to <inline-code>/chat<inline-code>. You can add code to this file to handle incoming chat messages.
This code will:
use the OpenAI chat API to generate a response
Before we can call our /chat route from a theme extension, we need to enable CORS handling. To do this we will use the <inline-code>@fastify/cors<inline-code> plugin.
Once the plugin is installed, you can add it to your app's configuration:
This will allow requests from ANY domain! For your actual, production app, you probably want to set the <inline-code>origin<inline-code> option to a specific domain - the domain of your store. Read more about CORS in Gadget in our documentation.
Your route is now complete! Now all that is needed is a frontend app that allows shoppers to ask a question and displays the response along with product recommendations.
We make use of an app embed block for our storefront chatbot theme extension. This means that our extension works with any Shopify theme, both vintage and Online Store 2.0 themes.
The script tag URL can be found in the Installing section of your app's API Reference.Your script tag needs --development added to your app-specific subdomain when working on your Development environment.
You should now be set up and ready to add the chatbot theme app extension to the storefront theme.
Your chatbot should now be available in your storefront - try it out!
You now have a chatbot that can respond to shopper questions with product recommendations! You can continue to build on this app by:
Have questions about the tutorial? Join Gadget's developer Discord to ask Gadget employees and join the Gadget developer community!
Want to learn more about building AI apps in Gadget? Check out our building AI apps documentation.
Theme extension overview
Theme extensions allow you to create custom blocks that merchants can place in the storefront theme editor. You can read more about theme extensions in the Shopify docs. This chatbot extension is an app embed block, so it works with both vintage and Online Store 2.0 themes.
In this theme there are 3 main files: