Selling Digital Products on Shopify

I’m on my third digital delivery app for Stitch People, and I think I’ve finally found something that’ll work for me: SkyPilot. Here’s a review of what it does, why I like it, and why the other things I’ve tried have failed.



This is my current app. I made the switch final today (May 15, 2016) and things are now running smoothly. Here’s what I love about it:

  • While the actual files are hosted and served through, this is all done behind the scenes and masked through your own domain. When people click on the link to download their file, the link is your domain. The SkyPilot app then intercepts that request and serves the necessary file.
  • The entire experience is on my domain. SkyPilot gives you templates to manage, so you have full control over how the experience looks for your customers. It integrates into your existing theme and layout, so there’s no break in the visual experience for your customers.
  • It integrates into the order status page. When someone completes their order and it contains digital products, they’ll see a button on the order status page that takes them to another page (on my domain) that lets the customer download the file. I still send a follow-up email (see the next point), but that’s now a backup. People can immediately download their files after their purchase without having to go back to their inbox and wait for a link.
  • I can manage the email notifications entirely. I’ve turned off email notifications through SkyPilot, and instead I send the download links through my email marketing service, Drip. When someone orders something through Shopify, Drip is notified and stores the customer ID. I then use that customer ID to generate their unique download link and send it to them. All emails go through my domain and have the highest deliverability rates possible. No more lost notification emails.

I’m hoping that I’ll stick with this one for a while. So far, it has everything I want, lets me see how many times someone has downloaded a file, logs the IP address of each download, and gives me the flexibility I want to craft the entire experience.



This was the second app I used, after Digital Downloads (below). It worked well for about 6 months, but eventually three things made me start looking for a third option.

  • The email notification sent to customers through SendOwl is sent from They don’t have support for sending emails through your own domain, so even though I was able to set the ‘From’ name on the email, a lot of the download notification emails were going to customers’ spam folders. Not good.
  • Files were all hosted and downloaded directly on While they do offer some branding options, customers are ultimately leaving your site to go download their products elsewhere. This never really sat right with me.
  • Sometimes, customers would receive the email with the link, click on the link, and get a 404 error from SendOwl. Usually this resolved itself if the customer tried again in a few minutes, but this was completely unacceptable for me. A huge selling point to offering digital products it the immediate satisfaction a customer gets when they purchase and then download the file. A service that can’t reliably deliver a seamless experience isn’t worth my time.

Digital Downloads by Shopify


This was the first app I used and it’s been probably 8 months since I’ve used it, but based on my experience, I have no desire to try it again. For me, the biggest issue was the inconsistencies with the download limit feature (which limits the number of times a customer can download a file). The default had it set to 3, and I kept getting emails from frustrated customers saying that the first time they clicked the link, they were told that they had exceeded the number of allowed downloads. I was going in at least once a day to reset someone’s download limit.

Another thing that drove me crazy: all downloads logged the IP address that download came from. Problem was, all downloads were being attributed to an IP address associated with Shopify. I emailed the Shopify team about this, and they confirmed that this was happening with every store that had the app installed. Several months after alerting them to the issue, it still hadn’t been fixed. Between this and the download limit weirdness, I decided that this app wasn’t worth the headache.

Why ConvertKit Wasn’t The Right Choice For Me

A few months ago, I wrote a post on switching from MailChimp to ConvertKit. At the time, I knew I needed to get off MailChimp, but didn’t know exactly what features I needed to be looking for. After using ConvertKit for five months, I’ve decided that I need to find something else. ConvertKit is great (and works really well for a lot of people like Pat Flynn), but I need a little more than what it has to offer. Namely:

  • Event tracking. It’s not enough to just tag a subscriber with some info (like ‘customer’ or ‘free-guide-download’). I want to know WHEN that tag was applied, when that subscriber converted, etc. Knowing when would help me craft better email sequences and create a more personalized experience for a subscriber.
  • A robust API. I’m starting to use a lot of different services to manage Stitch People, and am building custom solutions to integrate them. For example, we use Zendesk for our support emails. When someone writes in, we have an app that displays customer information about that person from our Shopify store. I wanted the same kind of functionality for people who purchased our products on Amazon, so I built my own app for that. The next app I build will be for pulling in data from our email marketing tool with all that event data I already mentioned. When did they subscribe? How many emails have they opened? How engaged are they in the brand? All this information will help me provide better customer service, but I can’t get that data without a good API. The ConvertKit API isn’t robust enough to handle what I need.
  • Subscriber meta fields. I need to be able to store more information about a subscriber than just name and email. I’d like to eventually build out my own abandoned email recovery tool and email sequence, and need to be able to save things like cart recovery URL for a subscriber.
  • Lead scoring. This was a feature I enjoyed in MailChimp, but didn’t think I needed. Turns out I really do need it. We have a Facebook group full of really great, engaged customers. MailChimp’s engagement scores helped me handpick that group, but now that I don’t have anything that shows me my most engaged subscribers, I don’t know who to invite into the group to keep things fresh.
  • Subscriber tracking. I’d love to close the loop on interactions subscribers have with my site. I’m segmenting people for Facebook Custom Audiences based on how they interact with my site, and I’d like to do that same kind of segmentation for my email list. For example, with the purchase of the DIY Stitch People book comes access to additional patterns available only online. I want to build a series of emails that can account for whether or not a subscriber has visited that URL yet. And what about customers who have already purchased one product, but are back on the website looking at other products? I’d like to proactively reach out to them based on what they were looking at.

Right now, it looks like Drip is going to be my best option. But before I commit to moving all my subscribers over, I’m going to do the free trial and see how things go. I’m also concerned that if I leave ConvertKit, all the links in emails I’ve previously sent won’t work anymore (like what happened when I left MailChimp), but that may be worth the benefits I’d be getting from Drip. More to come as I try out Drip and make a decision.

Podcasts in Google Music

UPDATE (2/3/2016) – In October of 2015, Google announced that they’d be adding Podcasts to Google Play Music. Great news! It looks as if they’re starting to slowly roll out this functionality–some users are reporting that they’re seeing the new Podcasts section in their app. I don’t see anything in my app yet, but when I do, I’ll be sure to write a review here.

UPDATE (4/15/2015)Pocket Casts is my new favorite podcast player for Android.

UPDATE (8/26/2014) – Google Music still hasn’t added podcast support, and at this point I doubt they ever will. I’ve started using Podcast Addict to listen to podcasts exclusively on my Nexus 5, so I don’t need to sync podcasts and their playback status with another device or library. It even has Chromecast support.

UPDATE (8/9/2013) – Now that Google Music has become a subscription service, I’ve moved over to it exclusively for my music. So far, I’ve been very happy with the service–especially the seamless integration with the Chromecast at home. However, they still haven’t added native podcast support.

You can get the Chromecast at Amazon for $35. I highly recommend it.

Chromecast at Amazon

UPDATE (9/4/2012) – Still no native podcast support in Google Music. This continues to be the best way for me to get podcasts into Google Music.

A few people have said that they don’t have the check box for including podcasts. To make sure this check box appears, you need to tell Google Music that you keep your music in iTunes (look for “Location of my music collection” on the Advanced tab). Once you’ve done that, you’ll see the option to upload podcasts.

ORIGINAL POST (1/4/2012):

I still think it’s only a matter of time before Google Music adds podcast subscriptions natively. But until that happens, I’ve found a solution to get podcasts into your Google Music account that uses iTunes as the podcast manager.

With Google Music, you can download the Music Manager, a small application that acts as the link between your computer and Google Music. With Music Manager, you can upload your current library (you specify the location) or download the music you’ve purchased through Google (someday I expect the ability to also download music you’ve uploaded). But iTunes podcasts aren’t included in that library upload by default.

Under the Advanced tab in Music Manager is a checkbox to ‘Include podcasts in uploads’. Check that box and now you’ve got your podcasts available in the cloud, accessible from the web and the Google Music app on your Android phone. If you leave both iTunes and Music Manager running in the background, new podcasts will be downloaded and uploaded without any supervision.

Also, make sure iTunes is selected as the location of your music collection:

google music podcasts

Here are a few of my favorite podcasts:

Using Markdown for Email Templates in Rails

I’ve been working on a Rails freelance project that has a lot of email templates. For the last year, I’ve had two versions of each template–an HTML template and a text template. For a welcome email, I had both welcome.html.erb and welcome.text.erb. The worst part about this setup is that when you need to make a change to the email, you need to change two files. This isn’t very DRY, so I finally went in search of a better way to do this.
I found several StackOverflow questions that helped me get to my current solution. If you’re interested in the context, here they are:

Markerb gem

Using Markdown seemed like a great solution, so I started digging into the Markerb gem. This gem, combined with a parser (I’m using the recommended Redcarpet), allows you to write just one email template–in my case, welcome.markerb. Using standard Markdown format, I now only have to manage a single template, which is then parsed into both the text part and HTML part when the email gets sent.

Once you add Markerb to your Gemfile and run the bundle command, all you need to change is the extension on your template file and then reformat your templates to use Markdown. Nothing changes in your ActionMailer. When Rails goes looking for the template, Markerb takes over, parses the file, and spits out the text and HTML parts that get sent out.

Tagging past Shopify customers in ConvertKit via API

We’ve recently started using ConvertKit for our email marketing for Stitch People, and I LOVE IT. It’s flexible, easy to create automation sequences (called courses), easy to move people in and out of courses based on any number of events (purchase, link click in an email, etc.), easy to tell exactly which form someone signed up on, and much more.
The first step in my migration to ConvertKit was to start collecting new subscribers and customers into ConvertKit, and to tag them automatically for easy segmentation later. This included writing a small Shopify app to automatically subscribe customers and tag them based on what they purchased. I’ll write another post about this later.

Once all new subscribers were being funneled into ConvertKit instead of Mailchimp, it was time to clean up old data. The first place I started was to tag past Shopify customers based on the product they purchased. We have a relatively small number of products right now (different variants of a book is our main product), but this would work just as well for a large catalog of products and customers.

To do this, I’ll be using the ConvertKit API (documentation found here).

Step 1: Create the tags in ConvertKit

The main API endpoint we’re going to be hitting is the Add Subscriber to Tag endpoint. And since the API doesn’t support creating new tags yet, you’ll need to create these tags through the website first. Head to the Subscribers area, and click ‘Create Tag’ at the bottom of the right sidebar. That’ll bring up the box to create a new tag.

convertkit tag creation

You can come up with your own naming convention for tags, but my general rule of thumb is to be descriptive. You may know what an obscure tag means when you create it right now, but your 6-months-from-now self won’t, and you’ll kick yourself when you have a bunch of people tagged, but you don’t know why.

For example, I use tags like ‘diy-physical-book’ and ‘diy-ebook’ to differentiate between two different variants of the DIY Stitch People book. I prefixed it with ‘diy’ because we’ll be releasing more books later, for which we will have physical and digital copies. For those, I’ll create tags like ‘farm-animals-physical-book’ and ‘zoo-animals-ebook’. These will be easy to decipher down the road.

Step 2: Grab your list of customers from Shopify

Next, head to Shopify and do an export of all your orders. Head to the Orders tab, and hit the Export button at the top. Make sure you select the All Orders radio button, and export the orders, not transaction histories. I use the CSV for Excel, Numbers, etc. option. I’ll eventually be uploading this to Google Drive.

shopify order export

Step 3: Make separate lists of email addresses for each tag

This will likely be the most time-intensive step in this whole process. Now you need to take the CSV from Shopify and filter through several times to generate lists of email address for each tag you want to apply. For me, I created three lists: one for physical book purchasers, one for ebook purchases, and one for physical + ebook purchases. These are the three tags I’m using, and now I need to come up with three separate lists of email addresses–one for each tag.

For this step, I used Google Spreadsheets. You could also use Excel, Numbers, or any other spreadsheet program that lets you quickly and easily filter your table based on column contents. Once you have your CSV file loaded in whatever application you’re using, you need to filter the table by products/variants. In Google Spreadsheets, you can use the Filter feature and then select the ‘lineitem_name’. In my case, I’ve been through several different iterations of the product and variation titles, so for my ebook DIY book buyers, I had to select several values:

filtering lineitem_name

Once filtered, copy those email address and throw them into a new tab in the spreadsheet. Make sure you label the tab so you know which list you have. Repeat this step for any other tags you want to apply.

Step 4: Write the script to tag the subscribers

Now comes the fun part. You can choose whatever language you want, as long as you have a way to make an HTTP POST request. I chose Ruby and used Faraday. Here’s a gist:

First thing you’ll want to do is populate the arrays of email addresses. Take the email address lists from your individual spreadsheet tabs and format them as strings in an array. I used a text editor (Atom) to quickly do this, then just pasted in the result. I was dealing with about 2,000 email addresses total.

Once you’ve created the arrays, head to your ConvertKit account page to find your API key. Put that value in.

Finally, you’ll need to grab your ConvertKit tag ids and populate those into the URL strings. Head to ConvertKit, click on the tag you want, and grab the ID from the URL:

tag url

Put that value in for the XXXX between ‘tags’ and ‘subscribe’ for each tag.

Step 5: Run the script

Now it’s time for the magic. Save the file you’ve been editing and then run it. For Ruby, I just opened a terminal window, navigated to the folder where the file was, and typed ‘ruby filename.rb’ to run it. Mine took about 10 minutes to run to completion. Once that was done, all my subscribers were properly tagged with the product they had purchased, allowing me to create Courses and Segments based on those tagged subscribers.