Time to build: ~1.5 hours
Building product bundling applications for Shopify stores is a complex task - you need an app in the Shopify admin for bundle management, a place to store and manage all of your bundle information, and changes to the Shopify storefront so the bundle information is correctly presented to shoppers. Bundling products together are a great way to increase storefront revenue, and Gadget's low-code BaaS (Backend-as-a-Service) platform makes it simple to set up a backend that manages all your bundle data.
Before starting this tutorial you need the following:
-> A Shopify Partners account
-> A development store with Checkout Extensibility developer preview enabled, and some sample products added
Prefer a video? Follow along to build the bundle tutorial by creating a Gadget app, getting the Admin app running, and deploying a function.
In this tutorial, you will use Gadget to build an application that can create bundles in the Shopify admin and manages your bundle information that is needed when making storefront enhancements. The provided admin app also includes a Shopify Function extension that will apply bundle discounts to your cart's line items.
You can fork this Gadget project and try it out yourself.
The admin app + Function extension is available in our examples repo on Github.
You will still need to set up the Shopify Connection after forking. Continue reading to learn how to connect Gadget to Shopify!
Brooklinen's bundle app is used as inspiration for this tutorial. In this style of bundle app, Storefront changes are made so that it looks like only a single bundle product is added to the cart. In reality, individual line items for bundled products are added to the cart. This isn't the only way to build a product bundle application. This method was chosen for this tutorial because it allows you to track both individual product inventory and the number of times a bundle has been sold.
This tutorial does not include storefront changes so when testing you will add products to your cart individually. Once all products that are part of your bundle are included, the discount will be applied.
Our first step will be to set up a Gadget project and connect our backend to a Shopify store via the Shopify connection. Create a new Gadget application.
To connect our Gadget backend to a Shopify store you have two options. The recommended option if you are new to Gadget and Shopify is to create a custom app via the Shopify Partners dashboard. You can also create a custom application on your Shopify store Admin page. Both of these types of custom apps have a slightly different workflow for connecting, and are detailed below:
To complete this connection, you will need a Shopify Partners account as well as a store or development store
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.
We have successfully created our connection!
Now we want to connect our Gadget app to our custom app in the Partners dashboard.
Gadget will copy 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.
You need to add custom models to keep track of our bundle information. A custom Bundle model can store the following information:
An intermediate model, Bundle Elements, will be used to track information about products and variants that are part of a bundle. This will be built in Gadget using a HasManyThrough relationship. Each Bundle Element will contain:
You need to create a new Bundle Element model to store data relating to individual items in a bundle.
The relationship fields needed will be added in the next step.
You need to create a new Bundle model and its required fields in your Gadget app.
Now you have all the custom models needed to store bundle information in Gadget. There is one final step before you set up your admin app - you need to run custom code after a new Bundle is successfully created.
When a new bundle is created in Gadget, you need to save a tracker product back to Shopify, so the bundle can be surfaced in your store. You can run a custom Code Effect to write this new product, along with metafield data containing a reference to the Bundle Id, back to Shopify. To write this product back to a store:
In addition to adding tracker product metafield info and linking tracker products to your bundles, the code effect will also:
There is a sample bundle admin app that can be used to create new bundles. To get a copy of this project locally, run:
The bundle admin app is a Shopify CLI 3.0 app using Shopify Polaris components and the provided Gadget React tooling. It also has a Functions extension that will be used to apply discounts in your store's cart.
Before you run the admin app, you need to make changes so that your Gadget app is used as the backend.
To use your local application as your admin app, you need to update the App URL for your connection. Your App URL should look like https://<your-app-slug>.gadget.app/shopify/install.
You need to make a similar change to the App URL on the Partners dashboard.
These are all the changes that need to be made in Gadget and the Shopify Partners dashboard. Now you need to update the admin app to use your Gadget client.
You need to update the admin app so that you are using your project's Gadget client. These instructions can also be found in the sample admin app's README.
Also, update the @gadget-client import statements to use your gadget app slug in
You also need to add your Shopify Partners app's API key as an environment variable.
You now need to deploy the Shopify Function included in the admin app's extensions folder. Functions allow you to run custom backend logic in Shopify's environment to apply custom discounts. You will use this Function to apply your product bundle discount to line items in your cart.
Shopify Functions need to be written in a language that compiles down to a WebAssembly .wasm file. Shopify is primarily using Rust for their Functions tutorials and examples, but you can use any language that compiles down to .wasm. The sample Function extension in the admin app is written in AssemblyScript and looks similar to TypeScript.
Shopify Functions work by reading cart and discount metafield data from STDIN, applying custom logic to apply the desired discounts, and writing a result to STDOUT. The provided Function has 3 main code files located in extensions/bundle-tutorial-function/assembly:
The values being passed into your Function are declared in input.graphql.
You need to deploy the Function extension to your Partners app:
The Function will then run the build process specified inside the shopify.function.extension.toml file, which compiles the AssemblyScript down to a .wasm file. Once your Function is deployed, you should be able to see it in your app's Extensions in the Partners dashboard.
Once your Function is deployed, we need to make some additional changes to the Gadget app so that we can pass bundle information into the Function.
When you deployed your Function, a FUNCTION_ID was written in your app's .env file, for example SHOPIFY_BUNDLE_TUTORIAL_FUNCTION_ID=<your-key>. We need to copy this value and add it to our Gadget app as an Environment Variable.
You also need to add the metafield namespace and key as environment variables in Gadget. These values can be found in your input.graphql file that is in your Function extension.
First, add the metafield key:
Then, add the metafield namespace:
If you try to run your admin app and create a bundle you will be greeted by a GGT_PERMISSION_DENIED error! We need to grant admin app users permission to our Bundle and Bundle Element models in Gadget.
Everything is now set up to be able to run your admin app and create a new bundle in your store Admin!
On the bundle creation page, you can add a title for your bundle, upload an image, and enter a discount percentage for all products in your bundle. If you click Add product you will be able to select a product and the product variants you want to add as options to your bundle. You can also choose the quantity of this product included in a single bundle.
Finally, clicking Save bundle will save your new bundle to your Gadget application's database! If you go back to your Gadget application and look at the Data pages for the Bundle and Bundle Elements models, you will see the newly created bundle data.
You should also see a Discount created in your Shopify Store. You can verify by going to your store's Admin and clicking on Discounts in the left navbar.
If your Bundle discount appears, you are ready to test the Function!
View your online store in Shopify and add the products contained in your bundle to your cart.
You need to add the individual products in the correct quantity to your cart, not the bundle tracker product!
Once you have added all the products contained in your bundle to your cart, you can view the cart. The items in your cart will be passed to your deployed Function. If the cart contains all items included in the bundle, a bundle discount will be applied to those cart items.
Congrats, you have built a product bundle application using Gadget, Shopify CLI 3.0, Shopify Functions, and AssemblyScript!
Now that you have a sample bundle app set up, you can go about customizing it to suit your needs.
Features that could be good to implement on top of this tutorial:
Some resources to check out include: