When we first started building our Shopify App, we knew there was lots of opportunity—Shopify has a well documented platform with a comprehensive API, and an ecosystem of over 2,000 apps to choose from. Our goal was to build an app that would allow store owners to leverage Facebook Messenger as a powerful abandoned cart recovery tool.
When we started working on our app, it wasn’t always obvious which API was best suited for the task at hand. We learned a lot from the experience. And since we know there are likely other developers who might be exploring Shopify as a platform to develop on who are also confused where to start, we’ve put together a list of things to keep in mind. Using our Shopify App as an example, I’ll walk through how we built our components and integrated them with Shopify.
Interested in getting started with Shopify app development? Learn more about how to build a Shopify app. Or, for more tools, check out our list of favorite Sublime text plugins.
Our Shopify app
Our app has three user-facing components:
- The app admin for the merchant, built using React and the Shopify Polaris library
- The backend API built with NodeJS
- A Vanilla Javascript bundle which is injected into the storefront
Below, we look at each of these components and the lessons learned for each.
Merchant’s app admin
The user interface of our app is built with Shopify Polaris. Polaris components share the same design language as the rest of the Shopify Admin, resulting in a well thought out and consistent experience across Shopify.
With Polaris in mind, here is what we learned about building our app’s admin.
1. Shopify Polaris
Polaris supports Typescript, a big plus for us. Our front end developers loved the extensive library of components available. The Polaris library includes every general and some not so common components for building an app. In particular, we found the resource list component very useful. It’s a tabular display oriented towards displaying a collection of similar objects, like customers or products.
As a team of developers for whom English is not their first language, the best practices and do’s and don'ts accompanying each component were a big advantage, and helped us understand the right kind of language and text to use.
2. Styling components
Polaris components also come with an extensive prop list for styling components. However, we found that sometimes it wasn’t enough, and wanted more control using CSS. Unfortunately, Polaris does not support styled components, which means we ended up with a bunch of wrapper components to achieve custom styling.
Our advice to developers starting with a similar project: use Polaris as the building blocks for your app. Not only did it save us a lot of time not having to write basic components, but our app also integrates right into the Shopify design.
"Our advice to developers starting with a similar project: use Polaris as the building blocks for your app."
Backend API
For the backend, we started with Shopify’s guide for building an app with Node and React. Using Heroku, we had an app with Shopify authentication running in less than half an hour. When an app is installed, it asks for access to the API scopes you need, depending on the kind of app you are developing. When choosing which scopes to access, keep in mind possible future use cases as well.
You might also like: 10 Ways to Establish Trust on Ecommerce Sites and Apps.
3. Shop identifier
Shopify does not use numerical IDs as unique shop identifiers. Instead, every shop has a subdomain on the myshopify.com
domain name. This subdomain is set once the store is created and cannot be changed. We use it as the unique identifier in our database.
4. Webhooks
Webhooks provide a powerful way to plug into events happening in the Shopify store. There are two store webhooks that in our opinion an app should always subscribe to: app/uninstalled
and shop/update
.
The uninstall webhook lets us know when a shop uninstalled our app so we can invalidate the entry in our database. A store owner can reinstall an app, which means the onboarding steps need to be triggered again.
The shop update webhook sends us the updated shop information, which has the email address we use to keep in touch with the store owner.
5. API access scopes
One thing that was confusing when starting off was that Shopify only allows one app URL, which could either be a new install for the app, or an existing customer. This distinction needs to be made at our own end with a database query. This limitation is a result of Oauth, which Shopify uses for authentication.
6. Cart permalinks
As one step of our abandoned cart recovery process, we redirect customers to a checkout page with the same cart contents they had previously. It is possible to create cart permalinks, but it’s buried on an unrelated page in the Shopify documentation about theming.
7. Onboarding steps
The app onboarding kicks off the first time a user logs into the app. During this step, we exchange the temporary Shopify access token for a permanent one, create webhooks, and add script tags on Shopify. We store the token and IDs in our database to ensure this step happens only once.
8. Recurring charge updates
We ran into another issue when we added recurring billing to our app. Shopify doesn’t have webhooks for payment status updates. Polling the Billing API to get the status of an active recurring charge for each shop at regular intervals is the only way to validate the charge.
You might also like: User Testing Your Shopify App: Public App Use Cases You Should Test.
Injected script
Shopify provides ways to integrate with the storefront section by directly injecting a script tag into the store. This provides no-holds-barred access to change the experience for the shopper. For security reasons, the script tag does not trigger on the checkout pages.
The script tag(s) are associated with each store, so the URL can be tweaked specifically for every store. However, we opted to go for a single static script tag URL. With this approach, we do not have to dynamically create a script for every request, and our requests are cached across multiple Shopify stores.
When the injected script loads, a window.Shopify
object with some basic info about the shop—including the myshopify domain—opens. We use this to get the configuration from the API and initialize our static script.
9. Keeping track of carts
Abandoned cart recovery is the core of our product, and to do this effectively we have to track the cart status as the customer navigates through the store. Every customer who lands on the store gets a 32-digit unique hexadecimal cart ID. We use this cart ID to keep track of customers on Shopify stores. One limitation we ran into is that the cart ID is not constant across page visits until there’s an item added in the cart.
10. Applying discounts automatically
Shopify separates the concepts of a cart and a checkout. A discount code can only be applied to a checkout. Because a script tag does not trigger on the checkout page, it is not possible to use the script tag to add a discount code. It’s possible, however, to “create” shareable links to discount codes, and then redirect the shopper to the link right away. During the checkout, the code will be applied automatically.
Summarizing what we learned
In a nutshell, here are the main lessons we learned:
For everyone:
- Use Polaris for the front end.
- Follow best practices when using Polaris components.
- Create wrapper components to work with styled components.
- Use shop domain as the unique identifier.
- Always subscribe to the
app/uninstalled
andshop/update
webhooks. - Request access to API scopes considering future use cases.
- Recurring charges have no webhooks; you will need to poll to get billing updates.
- Script tags provide a powerful method to alter the customer experience for a store.
When working with carts:
- Cart ID is only constant after an item is added to cart.
- At the time, discounts could not be applied to carts, only to checkouts. With the release of the Discounts API, they can now be applied to both.
- Cart permalinks can be created to directly link to a checkout
Final thoughts
There were a few aspects where we found the platform lacking, however nothing that was more than a small obstacle. Shopify’s platform allowed us to quickly provide value to merchants and shoppers alike.
As someone who has worked on custom billing and authentication implementations in the past, achieving the same results on Shopify’s hosted platform was a breeze. Webhooks let us plug into the event stream of the store, and the Polaris library provided us a solid collection of components and script tags that hook into the storefront—in retrospect, the popup and abandoned cart messages are simple components compared to what is actually possible.
Read more
- Introducing new app billing capabilities: discounts, trial extensions, pro-rating and more
- How to Optimize API Rate Limits
- Learn About Shopify App Development at React Summit 2021
- 10 Usability Heuristics and How to Apply Them to App Design
- Three Types of Trending Apps in 2017 and What You Can Learn for 2018
- How to Level Up Your App with Theme App Extensions
- Guidelines and Resources for Getting Listed in the Shopify App Store
What were the biggest lessons you learned building your first Shopify App? Share your experience in the comments below!