How We Made All The Money

“You pay for the education of young players with points.”

Arsène Wenger

In November 2022, my co-founder Jake and I started a company to optimise mobile game ad auctions, helping publishers (people who make games, and want to show ads in their own games) make more money. If you want more on that story, read this

The title on this piece is ironic, because we didn’t actually make very much money with our company. Sure, we got some revenue, but we never got to month-to-month breakeven (a target that would have been something like £25k MRR), and decided to execute a pretty significant pivot on 15th August 2023.

Our product directly made publishers money in two ways. Mostly, we talked about how the product used ML to find publishers comparatively better auction setups. But the other part of the product worked much better, and made our clients way more money: AdMob refreshes.

This is the story of how we (briefly) built a (small) software company on a weird oversight from Google’s product team.

About AdMob

Waterfall ad auctions work by giving ad networks (Google, Facebook, Applovin, Unity etc) opportunities to buy specified ad inventory at specified prices. Google’s main ad network is called AdMob (advertising mobile, geddit?) - although they actually have another one, called Google Ad Manager. 

AdMob is a super cool company. It was founded in October 2005, and subsequently funded by Jim Goetz at Sequoia. Ahead of their first board meeting, AdMob had forecast $50 of revenue. When the meeting came around and they only had $48, Goetz was furious (OK, not really, but even if he was, I’m sure he soon got over it). 

In their first six months of operations, they served 70,000 ads; in the next six, one billion; in the next six, five billion. That sounds like a lot of ads; it really isn’t. In August 2023, AdMob and Google Ad Manager together served about three trillion ad impression a week  - around 400 ads for every person on Earth, or 16,120x the volume they did at the start of their second year of operations (citation - I know this because I looked at some secret dashboards). That’s why AdMob is a great company, and also why VC is a power law game. 

In 2009, AdMob decided to sell. Steve Jobs called them up, and offered to buy them for $600m - mostly in Apple stock. But the vesting conditions and earn-outs were pretty stringent, and the AdMob team ran the risk of becoming Apple employees one day, being fired the next, and losing the proceeds from the sale. As a result, Google came in with a $750m offer - without the aggressive vesting conditions. So that whole weekend, the AdMob leadership sat in a board room hashing out a deal with Google - as the phone rang off the hook with Jobs on the line. Google got the deal, and it worked out pretty well for them.

How did AdMob refreshes work?

If you want AdMob to buy inventory from you in a waterfall ad auction, then you need to send them a bid request containing an ad unit ID of the form ca-app-pub-3909869679745897/2337528391. AdMob passes the bid request through to their ad exchange, AdX, where the auction happens. You generate these IDs by logging into the AdMob platform and filling out a form - click interstitial, give it a name, set the eCPM floor, click confirm, and copy the ID. AdMob can then map that ID back to a set of parameters about the inventory - for example, it might be a chance to buy an interstitial (i.e. fullscreen skippable) ad in Solitaire iOS at a $20 CPM.  eCPM is estimated cost per mille, i.e. the average dollar amount paid for 1000 ad impressions.

Here’s the key. For some reason, AdX bids 25% higher on ad unit IDs that were created in the last 48 hours. This works on both Google Ad Manager (which also routes through AdX), and AdMob. Having spoken to people who’ve been in the game for a while, this has been true for years. It’s possible to think of a few reasons why this might be the case - maybe they’re giving their ML a chance to learn. But I’ve never spoken to someone who knows why this happens.

What this means is that you can go generate a new ad unit, with the same parameters, and you’ll get a different ad unit ID. So I can generate a $20 Solitaire IOS interstitial ad unit today, and then tomorrow a new one, and so on and so on, and keep plugging them into my app, and Google AdMob (often around 30% of revenue) will reliably bid up to 25% higher. Publishers can just trick Google into paying more for the same inventory. This is called an ‘AdMob refresh’.

At my old company, we did this manually every single day. Every morning, we’d spend probably six London-salaried-employee-hours doing this by hand. We started doing it daily in August 2022 - because my boss realised it made the company something in the order of an extra $100,000/day in pure profit.

AdMob refreshes were an open secret in the mobile game industry: check out the conversation 10 minutes into this popular podcast, from May 2023. The thing is that most games companies didn’t have the scale to justify the level of manual work required to do refreshes every single day - and AdMob didn’t have an API to create these ad units. So ad monetisation analysts (like me) would fill out these forms by hand, because Google was too dumb to fix the exploit, and our own engineers were too dumb to figure out how to automate a form. 

The thing is, my co-founder is very very smart. And pretty quickly, he realised that while AdMob might not provide documentation about a public API which you can spam every day to generate new ad unit IDs, when you hit ‘submit’ on the form to create a new ad unit, the AdMob website calls an API. And that API call contains, in plain text, the parameters for your new ad unit, and is authenticated with a session cookie that only changes every few months. So even though AdMob don’t advertise the existence of an API, there actually is one - and we could hit it whenever we wanted.

So rather than spending hours refreshing all your ad units, you could click one button in our app, and it’d do it for you. And that would print free money for you. 

This was kinda crazy. It meant that we didn’t have to do any Selenium-based browser automation. And while refreshes were an open secret, the existence of the front-end API wasn’t. We spoke to one large US mobile games company, making millions of dollars a year in revenue from AdMob, who told us that they didn’t bother with refreshes because they weren’t worth the manual work. Another US head of monetisation told us that they outsourced manual refreshes to their little brother. But we could do it via API. It worked really nicely, as you can see below.

This is a customer success email I wrote to one of our customers - the idea was to look at revenue from AdMob and non-Admob channels, in the 48 hours before and after a refresh happened.

Here’s a slide prepared by one of our clients for an internal presentation. Blue arrows are refreshes (performed by our tool). In the top graph, red is AdMob eCPM; black is eCPM for all the other ad networks.

So what happened?

Hemingway said that one goes bankrupt gradually and then suddenly. But for us, refreshes died suddenly, then gradually.

On May 1st, Google announced that they would deprecate AdMob waterfalls, and move to AdMob bidding. That was the “suddenly”. That’s also discussed from about 8 minutes in the video I linked above. Irritatingly, Jake had figured out the front-end API like… two days before that. So that sucked. We had a team meeting on the 2nd May, where I said this:

“Yeah, so ad network side. Good news and bad news. 

Good news is that Jake is a wizard. I don't know if you guys realize that yet. But Jake's managed to kick the AdMob front end and figure out how their API works, their kind of secret API. And so he can create AdMob placements…

The bad news is that yesterday Applovin announced that they were pushing out AdMob bidding to all clients, not just a select few. So this is a change that is like … it's obviously bad for us, right, because we optimize waterfalls.”

This was a bit of an understatement. AdMob said they would finalise the shift from waterfalls to bidding on the 31st October (that deadline was ultimately pushed back to Q1 2024). Refreshes continued to provide a 25% boost to AdMob revenue, but AdMob waterfalls share of wallet fell from c. 30% in May to less than 10% by August. The consequences of that shift killed our company, Waterfull. Again, more on that here. Over the course of the next few months, it got harder and harder to sell the product, since people knew that eventually waterfall auctions (of which AdMob was the main component) would be phased out. That was the “gradually”.

However, in the meantime we sold that real working solution to real paying customers, which was AWESOME. I can’t stress enough how COOL it was that real people running real businesses were paying us for something we made. Anyone reading this will be like, duh, SaaS companies exist, everyone on Twitter has one, you’re not special - but having OUR SaaS company was genuinely really special. We do our best not to take it for granted.

Frankly, it reflects very badly on my sales skills that we didn’t make more money selling our SaaS. Jake built a really neat solution, and I didn’t manage to sell it to every single person that needed it. If I’m being generous, I’d say that mobile game companies (like the Americans I mentioned above) were reticent to give control over their entire ad revenue stream to a tiny startup for the sake of a 1-5% revenue boost that was maybe in breach of Google’s policies, and was definitely going to go away at some point in the next six months. In fact, when I put it like that, it’s surprising that the company even existed at all. 

(Re the policy thing - I’ve read the policies, and I think that what we did was legit. However, I am not a lawyer, and I am very biased. Google account managers knew about AdMob refreshes, but rather than making a product change, they merely encouraged publishers to stop exploiting them. There may have been some teeth (in the form of bans/throttling) behind those encouragements, but at no point was there any suggestion that refreshes were illegal.)

For more detail on the whole affair, then Felix Braberg (the guy from the YouTube video linked above) wrote about the whole journey here. 


My main takeaway is that the world is much dumber than you’d think. It’s pretty remarkable not only that the opportunity existed in the first place, but also that companies exploited it very differently. Some automated refreshes fully; others did them by hand; others didn’t bother with them at all, a differential driven 1. by the slow spread of gossip across the industry, 2. differing levels of technical proficiency, and 3. my nascent sales skills. 

The other thing was that we should have been much nimbler in taking advantage of our insight. In retrospect, we should have pivoted to be an “AdMob refresh company”, putting all our product development into the feature and sending out a ton of outbound making clear that we could help publishers automate them. In actual fact, we continued with our main product roadmap (a full-stack auction optimisation solution) and stayed slightly reticent about refreshes, lest the goose that lays the golden eggs squawk too loudly and encourage Farmer Google to wring its neck. Next time we’re on to a winner, we’ll double down harder.

Our first company, Waterfull, changed our lives. It was made possible the product teams at Google (and also Applovin) not building fairly obvious features. So, thank you, Google and Applovin. We’re very grateful.

Previous
Previous

Historiography and Reality Distortion

Next
Next

Insurance Broking - the War for Talent