Sovren · Self-serve ads · Shipped 2024

How I built an ad platform seven people could run.

Advertising had to become a primary revenue line, and the whole team was seven people. So I built our own ad server, made every step self-serve from a funded account to a live campaign, and put the money on prepay. What I underplanned was the human work around it, and that's the part I'd size first next time.

RoleSVP, Product · the only product person on it
When2024 to 2025 · five ad surfaces across five products
OwnedBuild or rent, the studio, prepay and the minimum, the holdout threshold
ResultFive surfaces live, the first forty advertisers running, no ad ops hire.
01 · The problem

Advertising had to carry real revenue across five products, and seven people had to run it.

We ran five products. Leadership wanted advertising to become a primary revenue line across all of them, and I got the product from nothing. The team was an engineering lead, four engineers, a data scientist and me.

The standard answer is to rent an ad server and sell managed service. Plug into something like Google Ad Manager, hire people to set campaigns up for advertisers, and you're serving ads in weeks. At seven people that math breaks. Every advertiser you sign is a slice of a person you now have to hire. And the rented server comes with somebody else's roadmap.

02 · The ad server

Our own ad server: five surfaces on one auction, with the floors, caps and pacing ours to change.

I'd made this call once before. Six years earlier, at Skylab, we integrated a third-party ad server and then replaced it with a self-serve engine we built, to drop the revenue share and the roadmap dependency. The trigger was the same both times. The roadmap we needed stopped being one we could buy.

Here it was pre-roll video, channel partner pods, sponsored posts, banner ads in the payments product and promoted products in the shop, all sold to the same advertiser. They went in as one supply strip, so a new surface meant describing its inventory to the auction, and how it got sold stayed the same. Floors, frequency caps, pacing and the experimentation surface all lived where our own team could open them. Channel partner pods joined last, when live shipped, and cleared through the same ad server.

It cost us time to the first paid impression. I'd make the same call, and section six is why.

The auction, illustrated. Guardrails clear first, then price decides.

03 · Self-serve

Self-serve end to end: an advertiser funds, builds and launches a campaign with nobody on our side.

Self-serve was the harder build, and it was the point. Targeting, budget, pacing and creative all sit with the advertiser. Nobody on our side opens a spreadsheet to get a campaign live.

The advertiser studio. A campaign tree on the left holding three ad sets and six ads, the selected ad being edited in the middle with its creative, headline, caption and call to action, and a live preview of the ad on the right.

Research set the left rail. Advertisers test. Similar creative against different audiences, or different campaigns against one audience. Each test is a small edit to something that already exists, dozens of times a week. So the rail is an accordion. Campaign, ad set and ad stay open together, and moving between them is one click.

After launch, every stall in the funnel came back to me. Where advertisers dropped out, what they asked support for, what they wanted that we didn't have. I pulled it together every week and worked the list with design and engineering, in the order the people spending money set.

04 · Prepay

Prepay by top-up and a $50 minimum: no campaign goes in unless the balance covers it.

An advertiser tops up a balance. A campaign can't be submitted unless the balance covers it, and at submission that budget is committed to that campaign alone.

That took three jobs off the list before anyone had to staff them:

  1. Credit decisions. Nobody decides who gets to spend before paying.
  2. Collections. There's never an invoice to chase.
  3. Chargeback exposure. Spend can't run ahead of money we already hold.

The minimum was $50, on purpose. The first thing to prove was that a stranger could fund an account and get a campaign live without us. A high minimum hides that failure behind a sales call.

05 · The ops gap

The ops gap: vetting advertisers and walking them through setup, and I hadn't planned for either.

The engine could take a campaign from a stranger and serve it the same day. The work around it is what I didn't size. Moderation checked the creative. Three questions sat outside it:

  1. The advertiser. Was this a legitimate business?
  2. The fit. Did the campaign suit the audience it was buying?
  3. The first-timer. Would they get through setup without a phone call?

Advertisers arrived expecting Meta. They expected someone to review their account, know them by name and walk them through the studio. The team absorbed it alongside the build.

Situation
The product could get a campaign live alone. The relationship around it still needed people, and that time was in nobody's estimate.
Call
We added an advertiser review step above content moderation and gave advertiser relationships an owner.
Cost
Hours from the team the platform was built to protect.

Next time the operational work goes in the plan on day one, next to the engineering, with hours against it.

06 · The holdout

The holdout: a retention threshold set before the ad-load test, and it stopped a revenue win.

We tested a heavier ad load. Click-through rose and short-term yield rose. Then the long-term holdout came back. The retention cost outweighed the gain, so we didn't ship it.

The threshold was set on long-run retention before the test ran. eCPM and ARPU move the way everyone in the room wants them to. A holdout has no stake in the answer, so it got the final say, over my own revenue number too.

RETENTION, INDEXED TO THE HOLDOUT ILLUSTRATIVE 1009896 04812 WEEKS THRESHOLD, SET BEFORE THE TEST HOLDOUT HEAVIER LOAD
Illustrative figures, real sequence.

A marketplace makes this harder to read. Budgets and the auction are shared across both arms, so a naive A/B test partly measures the arms competing with each other. We ran sample-ratio checks, and every case for a change was made on incrementality.

The revenue number will always argue for more advertising. Something in the system has to be able to say no.

07 · The result

Five ad surfaces live across five products, the first forty advertisers running, and no ad ops hire.

Seven people ran both sides of an ad business. Advertisers built, funded and launched their own campaigns across five surfaces, and the money side never needed a person.

The first forty advertisers came in three waves:

  1. Relationships. Ten through people leadership already knew.
  2. Existing customers. Ten businesses already on our other products, who trusted us with a budget before they trusted the platform.
  3. Sales. Twenty through the sales team, on a go-to-market I built with sales and marketing.
08 · What I owned

Build or rent, the surfaces, the studio, prepay and the holdout line. The build was the engineering lead's.

An engineering lead ran the build with four engineers and a data scientist. I was the only product person on it.

Mine

  • Build or rent, and the call to build.
  • The five surfaces, which opened first, and what each one was worth.
  • The studio, from an advertiser's first login to a live campaign.
  • Prepay, the $50 minimum, and how money entered the system.
  • The holdout threshold, set before the test.
  • The weekly funnel list, and the order it set.

Not mine

  • The implementation, from the auction to the delivery path.
  • The relationships behind the first wave, and the selling behind the third.
09 · What this doesn't prove

How advertisers get found, demand from outside, and guardrails that depended on who asked.

Self-serve describes how a campaign got live. How an advertiser got found is a separate question, and half of the first forty came through people who already knew us.

Every advertiser bought through our own studio, on supply we owned, against about four million members. Outside bidders in the auction is a different job, and I haven't done it.

The holdout on the ad-load test existed because I asked for one. Guardrails on the ads side got built case by case, as each problem showed up, and applied by hand on the runs where someone knew to want them. The quality of the answer depended on who was asking. That's the first thing I'd make default.

The number I'd want first somewhere bigger: the share of advertisers who arrive cold, with no introduction, and run a second campaign.