I was a web developer for nearly 20 years before I ever built web pages that accept payments from customers. I'm not sure if that's a comment on my career in particular or the industry as a whole. But the day finally arrived in 2013, when we at ThinkUp decided to try something uncommon: build a web business supported by customer subscriptions instead of advertising.
Since then, despite relying on third parties to handle all the complexities of credit card transactions, we've developed and deployed seven billing-related projects. SEVEN BILLING PROJECTS. It's April of 2015 now. That means our tiny team launched a new billing-related project every two to three months. In short, during the entire existence of our business, we've been constantly occupied by designing and building a system tangential to our actual product (albeit core to our business).
In order to assure myself that I'm not crazy for being tired of billing-related code, I'm documenting our journey so far here. Maybe it will help someone out there make decisions about their new subscription-based web product.
Project 1, October 2013: DIY Crowdfunding
Before we launched ThinkUp, we wanted buy-in from the community. As an open source project built for the community by the community, it made sense. Given the rise of Kickstarter into the mainstream and the audience that my co-founder and I had through our writing and podcasting, we knew we could pull off a successful crowdfunding campaign. We also knew that ThinkUp would be a subscription service, and we wanted to start capturing recurring payments from day one. At the time, Kickstarter and other crowdfunding platforms didn't support recurring payments. (Patreon hadn't launched yet; but it wouldn't have made sense for us anyway. ThinkUp is squarely a subscription service versus arts patronage.)
We knew we'd have to write a subscription billing system anyway, so why not start with the crowdfunding campaign? Following in Kickstarter's footsteps, we decided to use Amazon Payments over more developer-friendly options like Stripe to collect payments. Anil and I both loathe entering credit cards into web pages. Our target customers already have Amazon accounts. We felt that the user flow for backing Kickstarter projects, which ThinkUp would emulate, was so smooth and easy it would enable even impulse backers to pledge a subscription on their tiny mobile device screen.
Because it was a crowdfunding campaign modeled closely after Kickstarter's flow, there was one particular requirement that had serious repercussions for us down the road. During the campaign we'd collect credit card authorizations—agreements from our backers to let us charge them when the product was ready. We promised we wouldn't charge anyone until January, when ThinkUp was available for them to use.
This had two big implications on the backend: first, we'd have to use Amazon Flexible Payments Service, Amazon's more advanced, customizable payments API which allowed apps to collect authorizations first and not charge till some much later date. It also meant we could put off writing any software that performed actual charges until later.
So while over 1,000 backers gave us permission to charge their Amazon account a lot of money in aggregate, our system wasn't ready to do that—until a special day in January, the 17th, when it was time to run the charges. That day we collected a lot of money from our backers—and a hell of a lot of payment failures.
Remember the Target hack? Forty million credit cards were compromised, and a great deal of them were owned by people who backed ThinkUp's crowdfunding campaign. In the time between ThinkUp collecting the authorization to charge their card, and the charge itself, almost a third of our backers had changed their credit card thanks to Target. And thanks to things like Gmail's Priority Inbox (a majority of our subscribers use Gmail), spam filters, and just busy people who don't get through all their email every day (like me), a majority of those failed payments went unfixed because backers simply never saw the multiple emails from us and Amazon alerting them to the failed payment.
While I am eternally grateful to every single human who backed our campaign, failed payment or not, it was a bummer.
Project 2, March 2014: Annual subscriptions
ThinkUp launched on time to its crowdfunding backers in January, but it was available to only them. We weren't yet open to the public. Mostly this was because ThinkUp the product had a lot of bugs to work out, but we also didn't have the billing system in place to collect an authorization and charge it immediately. Each day, by hand, I'd run a script that collected stray charges left over from the crowdfunding campaign, and we scrambled to put out instructions on how to update your payment method and fix failures.
In March we finally opened up to the public, and began accepting annual subscriptions on the spot. We were still using Amazon's Flexible Payments Service, with the key difference that the charge happened immediately after the authorization. The immediacy of the charge cut down on payment failures a whole lot.
Project 3, July 2014: Free trial
Once ThinkUp was open to the public, the software was a reality, and we'd exhausted the goodwill of crowdfunders who were inspired by an idea presented in a video, it was time to get real. ThinkUp's annual subscription price was pretty high ($60/year for members, $120/year for Pro plans). Without a way to try the app out first, our subscriptions slowed to a trickle, and cancellations after a week or two of using the service spiked. We had to offer a free trial.
Our one big requirement for the free trial was that we could say: "Credit card not required." We hate free trials that collect your payment information upfront, and then when you forget to cancel, charge you automatically. So, on the backend, this project had less to do with billing, and more to do with building in a trial state where the user hadn't paid yet but was still getting access to the full app. We also needed reminder emails letting trialers know they had X number of days left to pay in order to keep their account active.
Once we launched free trials, it was a thrill to see so many people try out the app. This is when, as a business, we started concentrating on converting users—not just from landing page to signup, but from trial to paying subscriber.
Project 4, August 2014: Monthly subscriptions
With free 14-day trials in full swing, we poured a great deal of effort into making the first 14 days of app usage the best they could possibly be, in order to convert more subscribers. But the annual subscription fee was still pretty high, and we fiercely debated internally if we could market a $60/year product as $5/month. Not until our customers could actually PAY monthly, I argued.
It wasn't until we had to offer monthly subscriptions that all the highly-customizable-but you-gotta-do-it-yourself of Flexible Payments Service (FPS) became a liability. I didn't want to create cron jobs that ran daily charging people on a monthly basis. That figured out if someone paid on January 30th that it should recharge them on February 28th the next month. That had to deal with timezone stupidity. That meant we lost revenue if our servers had a problem. I wanted someone else to handle all that for us.
We were still convinced that Amazon Payments was the best user interface. So, since we wanted to stick with Amazon Payments, we switched to Amazon Simple Pay, a wrapper for FPS that handles recurring charges for you. Subscribing to a service via Simple Pay was still a one-click affair, and Amazon did all the recurring charges for you. Great!
Around this time, our Amazon Payments account manager got in touch, pitching Amazon's new payments product, Login and Pay with Amazon (LPA). He wanted to set up a call about ThinkUp migrating to LPA. I looked at LPA's documentation, and it appeared to be built for web sites selling physical products, geared towards businesses who needed a full shopping cart experience and had to collect shipping addresses. It didn't offer subscription management. That wasn't for us.
In a decision I regret to this day, we decided to go with the older, established Amazon Simple Pay instead of the new Login and Pay. Even though LPA didn't offer features we needed, I ignored very obvious signs that Simple Pay was no longer on Amazon's roadmap. The code libraries hadn't been updated in years. For a business as small as ours, our Amazon account manager pursued us with a lot of persistence to consider switching over.
Project 5, November 2014: Coupon codes
It's not easy getting consumers to pay for recurring subscriptions on the web. In an effort to boost our sales during the holiday season and give users the opportunity to give ThinkUp as a gift, we launched The Good Web Bundle. A partnership with four other subscription sites that we love, a user could purchase the "bundle" for a discounted price. When they did, they received a coupon code they could redeem at ThinkUp and at the four other sites for one year of use.
The big difference between this project and the earlier work we'd done was this was the first one-time purchase a user could make. We used Amazon FPS to give users a link to make that one-time purchase, then emailed them a unique coupon code. Just like the other four sites, we built in the ability to redeem that code for a year of ThinkUp in our membership system. Similar to free trials, this was a matter of creating a non-recurring subscription state in our system that ended on a date exactly a year away from redemption.
It was around the bundle's launch that we heard a troubling rumor from a reliable source. Amazon was going to discontinue Flexible Payment Service (including Simple Pay), and go exclusively with Login and Pay. Kickstarter was switching to Stripe.
THAT put a damper on the holidays.
Project 6, January 2015: First annual renewals
In January, our first annual renewals were up from the crowdfunding campaign. Since those came in via FPS and not Simple Pay, we'd have to recharge them manually. We were hyper-aware that most crowdfunding campaigns do NOT charge you again a year later, so we spent a good amount of time writing and designing email notifications for crowdfunders informing them that their annual renewal was coming up. We sent one 2 weeks before the member's renewal was due, and one week before. I wrote code that gave users the ability to close their ThinkUp accounts and get a pro-rated refund via FPS right inside ThinkUp. (Prior to that, they had to email us, which sucked.)
Then, each day we ran the annual renewal charge job by hand as members came up on their renewal date. There were a ton of payment failures again, due to expired or changed credit cards, and a good number of users closed their accounts because they hadn't used ThinkUp as much as they thought they would. That is understandable, if hard to watch. I was glad to finally give our members a guilt-free escape hatch if they wanted out.
Project 7, March 2015: End-of-life
In January, Amazon made the announcement official: Amazon Flexible Payments Service (FPS) would be discontinued effective June 1, 2015. Worse! Existing subscriptions would NOT get automatically migrated over to Login and Pay. Our customers would have to come in and pay again.
In short, the payments API our entire business was based on, and the sole source of our revenue, was going away. I'll be honest: I spent a couple of weeks feeling crushed. We'd worked hard to acquire every single paying ThinkUp subscriber, and we know that in the transition, because of lost emails or busy lives or second thoughts, we will lose customers. Not to mention rewriting our billing interactions and backend again to work with Login and Pay.
We thought long and hard about moving to Stripe. To Amazon's credit, our account manager and a solutions architect spent a great deal of time with us, offering help, making suggestions, accepting bug reports. Login and Pay does not offer subscription management, and that was not software I wanted to write in-house. Among a handful of other products, Amazon suggested we check out Recurly, which offers recurring subscriptions via Login and Pay. Beyond offering way better customer management features than Amazon Payments itself does, Recurly offers integration with Stripe and PayPal, generates customer invoices, and made offering both a monthly and an annual subscription plan very easy.
So, last month, we removed the Amazon Simple Pay code from ThinkUp, and we're now accepting payments via Login and Pay with Amazon (by way of Recurly). The customer experience is just as simple as it always has been, with one additional choice: between a monthly or a discounted annual plan. Recurly, of course, takes a cut, but given the dev time they saved us and the features we'd never build by hand, it's worth it.
Having been through these past 20 months of billing system development, I truly appreciate the value of app stores, and how they let software developers worry about their software instead of accepting payments.
It might seem like the moral of the story here is "Don't depend on third-party billing services—especially Amazon Payments!" But I don't believe that. As a small startup you don't have a choice about depending on third-party services that could get pulled out from under you on any given day. Even all this was more efficient than building our own in-house credit card transaction service. And there's no telling how things would have played out if we had, say, gone with Stripe from the beginning. Maybe we would have skipped a lot of steps in this journey so far and had a ton more time to focus on ThinkUp the product versus handling subscriptions. Maybe we would have had a lot fewer customers who didn't want to enter their credit card into a new app they didn't trust yet. Maybe in the end the dev time we saved would equal the revenue we'd lose. (Though I'm not sure Stripe would have supported delayed charges the way Amazon FPS did at the end of 2013.)
When I started building subscription payments into ThinkUp, I had zero experience and only vaguely understood the difference between a credit card authorization and a charge. I was dumb. Today, so far, I'm really happy to pay someone (sometwo, actually, between Recurly and Amazon) to do the work of dealing with payments, invoices, recurring charges, and expired credit cards for us.
Amazon FPS and Simple Pay will stop charging our customers as of June 1. Between now and then, our EIGHTH billing project will be asking our current customers if they will re-pay for their subscription. Wish us luck.
One year ago
I was sexually assaulted when I was 15. It was at a house party for my friend’s 16th birthday.
I was coaxed into trying rum and cola for the first time, gamely attempting to sip on the horrible concoction of cheap supermarket cola and an even cheaper rum miniature, stolen by someone from their grandma’s post-Christmas stash, before taking it to the kitchen sink to pour away.
A guy I knew vaguely from another senior school was there in the kitchen, along with a couple pressed up against the fridge. I knew her from primary school and later senior science classes, but mostly I remember she smirked when I entered, led her boyfriend out by the hand and shut the kitchen door behind her. For 15, I was pretty clueless with boys and relationships. There was a gulf between us. She might have been ten years older, and she knew it.
The boy I vaguely knew began to talk, leaning in close. I tried to smile demurely and dodge, assuming (correctly) he was drunk and lecherous. He half-pushed, half-walked me backwards, with his hand in my hair.
(My hair was long and curly. I usually wore it in plaits, or sometimes down in a mess of ringlets. It came down to somewhere around the middle of my back. It was well known you could clip 3 or 4 testtube-holder clips to my plait before I noticed. It was heavy duty hair.)
He had one hand in my hair, and another snaked around my barely developed curves. He was careful not to look me in the eye to see that I was unhappy, buried his head in my neck and made soothing murmurs about how much I would enjoy this. One of the kitchen drawers just behind me was ajar and my ponytail dipped into it. He pressed up against me so it shut, and I was trapped. I asked him to get off. He ignored me. I looked wildly over to the shut door and the shapes moving in the dark just beyond the thick frosted panes.
He fumbled about with fingers and knuckles, and tried to brush my hand against his crotch. He wanted to rape me, was trying to get that going on, but then someone opened the door again and I reached out a hand to them, surprising my attacker into taking a step back.
I didn’t know the guy that came in but he looked at me and across to my attacker and said, looking one to another, “You both cool?”. The boy who had just tried to force himself on me gave a shrug and said “You should’ve knocked.” I ran out to the garden.
I found two female friends there and told them what happened. They looked frightened for a moment and then it began. The rationalising. That this couldn’t have happened to someone they knew, by someone they knew. One of them tried to act as if she was impressed and delighted about my newfound sexual maturity. The other said it would cause trouble in our friendship group if I started spreading rumours, so did I have proof?
I realised then that, by that human instinct to avoid trouble, he was careful to leave plausible deniability in everything he did. My hair got into the drawer — he didn’t put it there. He didn’t injure me — I was too scared to move, and he was substantially bigger than me. He moved so that my hand fell across his crotch, he didn’t place it there. It wasn’t clever, exactly, but I realised I couldn’t say anything substantial.
I didn’t say anything else to my friends. I didn’t tell my family. I got asked a few times at school if I had had sex in the kitchen at someone’s party. I counted down the months until I could change schools for sixth form. I’ve seen him twice more. The second time, in a bar, I asked him outright — shaking — did he remember what happened? He looked at his feet and mumbled that we met at a party once but we were kids then. I told him he was a horrible person, and left.
Why am I sharing this, on the Pastry Box, in public? Because it is likely that some of you reading this don’t know why women can’t just report sexual assault, or that sexual assault happens to ‘others’ for some unknown reason, or that sexual assault is always overtly violent and the act of a mad monster. That’s not often the case. It is often sly, calculating and engineered for plausible denial. To be not believed is to relive the assault again, re-evaluating every moment, questioning your own sanity.
The other reason for sharing something so personal and painful relates more widely to our communities and cultures. People hate ‘drama’. They want bad stuff to go away and for things to carry on as they always have. They hate thinking that there is something more that they could have done or that they were somehow complicit, so they reject it. At some point or another, this has been all of us. This was my 15 year old girl friends who were frightened of what the things that happened to me meant for them and their understanding of their world. It is world leaders who can’t understand what the voice of the people is and why it differs from their own views. It is our coworkers and colleagues and industry compatriots when trouble rises up. People want desperately for things to calm down and go back to normal because it’s all so upsetting.
We rid ourselves of guilt that we cannot absolve by remorse or corrective action, by turning it into blame or ‘otherness’. We create narratives to explain shortcomings in ourselves, our friends and family members while demonising those who aren’t already part of our worldview. Abuse of many forms is often inadvertently perpetuated by individuals avoiding conflict. Intellectually, we know and recognise this. But then our own turf is rocked by ‘drama’, ‘scandal’, ‘accusations’, and we want to hush it all up so we can all go back to work.
So, I’ll leave you with this sobering thought, and what this whole soul-baring session was about. The tech industry, for all its logic and cleverness and money and lofty ambitions, is a cesspit for this kind of stuff. By shouting down those who try to speak up for themselves, even when all they can do is whisper, we are not creating good communities and supporting healthy cultures. We are creating a hegemony of cowards. Shout back and give voice to those being drowned out.