At the start of 2017 Littledata released its first Shopify app. A year on, here are my observations on the technical challenges we’ve overcome.
This week we’re at Shopify Unite in Toronto, and it’s no surprise that their app ecosystem continues to grow. We chose Shopify as our first platform partner due to their open APIs, quality documentation and enthusiasm from other developers. Much of that has been as expected, but to help all of you looking to build your own Shopify app I’ll share some of our learnings on the hidden challenges.
Littledata’s Shopify app makes it a one-click process for stores to set up for Enhanced Ecommerce tracking in Google Analytics, and then get actionable insights based on the Google Analytics data. It has to hook into Shopify orders and products, as well and modify the store’s theme and process ongoing transactions.
1. Handling re-installs gracefully
The great advantage of Shopify’s app store over, say, Magento marketplace, is that any store admin can install and pay for an app with a couple of clicks. The disadvantage is that stores can be as quick to uninstall as install. Store admins may start, realise they don’t have permissions, time or energy to continue and roll back to try again later in the day.
Since our app inserts a snippet into the store’s theme layout (see point two below), uninstalling removes the web-hooks we set up but does not remove the inserted snippet. When a store re-installs our app has to work out what state they were in when they uninstalled (audit, test mode or live), whether the script snippet is still there and what settings have been changed in the meantime.
It took us a few months to get a handle on all the possible user flows, and we’ve found automated end-to-end tests to really speed up running through the different scenarios. In our Meteor framework we use Chimp [link] to run tests through Selenium on localhost and on our staging server.
We’ve also found it essential to track our own stats of ‘installs + activations’ (including the date of first install and time to finally uninstall) rather than relying on the Shopify Partner stats of uninstalls and installs, which can hide the detail in between.
2. Working with script tags
The other side-effect of making apps easy to install is that you can assume the early-adopter stores who will try your app already have lots of other installs.
Shopify recommends using the Script Tag API to handle scripts linked to the app, so that when a store uninstalls your app it also removes any client-side scripts from the store. Unfortunately, in early tests we found the load latency to be unacceptably high: on some stores, only 50% of the page load events were getting fired before the user moved off the page.
So plan B was add a snippet to the store theme, and then load this snippet at the top of the <body> element on all the layout templates. This has worked much more predictably, except when theme editors remove the snippet reference without enquiring what the Littledata app does (see our fifth challenge).
Get the Littledata app
3. Charge activation vs authorisation
Now a very simple gotcha. In our first month we had around 60 installs at a flat price of $20/month, but apparently no revenue. After investigation we found we had not activated the recurring charges after the store admin had authorised them. Doh!
We’re still not sure why an app would want to have authorised charges which are not activated — seems like over-engineering on Shopify’s side — but luckily it was easy to correct without asking for more user permissions.
4. Tracking adds-to-cart
The first version of our app tried to run the script when customers got to the ‘/cart’ page of a store. The problem here is that many stores have AJAX or ‘mini’ carts where customers can checkout without every visiting the cart page.
We looked to trigger the script before the user got to the cart the page, but this appeared to run too many risks of interfering with the customer actually adding the item.
Our final solution has been to poll the Shopify store for the current cart, and see if products have been added (or removed) since we last polled (and stored the previous cart contents in memory). This is somewhat inefficient, as it requires continuous network activity to grab the cart JSON from Shopify, but we’ve reduced the network requests to one every 4 seconds – judging that customers are very unlikely to add a product and checkout in less than 4 seconds.
This cart polling has proved more reliable across different store templates.
5. Integrating with other Shopify apps
I mentioned that early-adopter stores tend to have lots of other apps: and those apps have loyal customers who push to make Littledata’s app to work their chosen app (not just vanilla Shopify).
The challenge is that most of these app development companies run a very Agile process, constantly changing how their app works (hopefully to improve the experience for store owners). An integration that worked a few months ago may no longer work.
We’ve found the best solution to be open developer-to-developer communications, via a Slack guest channel. Having the developers implementing the features on each side talk to each other really cuts down the delays caused by a well-meaning project manager slightly misinterpreting the requirement.
6. Handling ongoing updates
As tested improved client-side tracking scripts, we needed to update the script in the store theme (see point 2 above). This creates a small risk for the store, as there is no UAT or test environment for most stores to check before going live with the new script.
The store theme may also get edited, creating new layout templates where the Littledata snippet is not loaded.
In the first version of our app we tried to update and re-insert the latest Littledata snippet automatically on a weekly cycle. However, once we reached hundreds of active installs this became unmanageable and also opaque for the store admins.
In the latest version we now allow store admins to UPGRADE to the latest script, and then we check all the correct Google Analytics events are being fired afterwards. Giving the end user control of updates seems a better way of maintaining trust in our brand and also removing risk: if the update goes wrong, it’s quicker for us to alert the store owner on how to fix.
I’m still sure we made the right choice with Shopify as a platform, as their APIs, partner support and commercial traction are all number one in the ecommerce world.
But I hope that by sharing some of the hidden challenges in developing Shopify integrations, we can all build better apps for the community. Have you built something for the Shopify app store? Are there development problems you’ve encountered which I haven’t shared here?
PS. Are you a developer interested in joining an innovative analytics company? We’re hiring in multiple locations!