I thought the code was the hard part. Then I tried to get into the stores.
Nobody warns you that launching a multi-platform product isn't one launch - it's five separate negotiations with five separate gatekeepers, each with their own rules, their own review queues, and their own creative ways to silently eat your time.
I've spent the past 3 years building Zero Ad Network from scratch - an ad platform that gives site owners actual control over their own monetization. Two browser extensions, a WordPress plugin, a TypeScript npm module, a PHP Composer package, and a Stripe payout system later, it's finally live. Here's what the distribution layer actually cost.
Chrome will make you earn it - and that's not entirely a bad thing
Google's Chrome extension review process is, honestly, exhausting. Every permission you request requires a written justification. Every feature that touches the network, storage, or the DOM has to be explained in plain language to a reviewer who may or may not have the context to understand what you built.
3 rounds of back-and-forth and 3 weeks from first submission to approval. The email - "Your extension is now live in the Chrome Web Store" - felt so satisfying for what should have been, in theory, a routine task.
But here's the thing: this forced me to ask myself, genuinely, whether every permission was actually necessary. It's an uncomfortable question when you're deep in builder mode and you just want to ship. The answer, twice, was no. The review process made the extension tighter than it would have been if I'd just published and moved on.
Firefox was significantly more relaxed by comparison. Same codebase, different review culture - approved in 1 week with minimal back-and-forth.
Safari hit a hard wall almost immediately. Apple has decided that custom header injection into request payloads via declarativeNetRequest is simply not something they'll allow - no workaround, just suck it up. Their extension debugging tools are so miserable that Chrome's extension development process feels like a walk in the park by comparison. I'm keeping an eye on whether they loosen that grip at some point. For now: two extensions, not three.
npm and Composer are a joy. WordPress is not.
The TypeScript npm module and PHP Composer packages were, genuinely, easy. Set up your accounts on npmjs.com and packagist.org, connect the GitHub repos, push a tag - it's live. One of those rare developer experiences where the documentation says how it works and it actually works that way.
WordPress is not that.
You can't freely inject JS and CSS into your plugin-specific pages. You have to use WordPress's own PHP functions for that - understandable, they're protecting the ecosystem. But getting the plugin code to their standard meant 2 feedback emails, each presenting a new set of issues that weren't mentioned in the previous round. It's a slow, slightly opaque process that requires patience.
Eventually the plugin got approved and is now officially installable from the WordPress plugin directory. That felt like like a genuine win 🎉.
The ORM migration I'd make again without hesitation
I started the platform on TypeORM. It's the safe, familiar choice - well-documented, plenty of community knowledge, used everywhere in the Node.js ecosystem.
Here's what nobody says out loud about TypeORM: there's no proper tree-shaking. You include it, you bundle everything - all the drivers, all the decorator metadata, all of it. The bundle size hit is not small. And once you push past simple CRUD, the QueryBuilder starts showing its teeth. Queries you'd write in 3 lines of SQL become 15-line method chains that are harder to read, harder to understand, and fail in ways that aren't immediately obvious.
Then I switched to Drizzle. It's lightweight, the schema definitions feel natural to write, and the query abstraction stays close enough to SQL that there are no surprises about what's actually hitting the database. The migration tooling has a few rough edges, but generates extremely good quality migrations queries.
The pattern I kept hitting with TypeORM - write a complex query, fight the QueryBuilder for an hour, eventually give up and drop into raw SQL anyway - never happened once with Drizzle. If you're still on TypeORM out of habit more than conviction, it's worth spending an afternoon with Drizzle's docs.
Stripe payouts are deceptively involved
The partner onboarding flow and Stripe connected account integration looks clean on paper: calculate each site owner's payout, initiate the transfer, done. In practice, the payout calculations involve dynamic CTEs that would make a first-time reader pause - I'll admit they made me pause writing them. Getting the JOINS, timing windows, and edge cases right took considerably longer than I'd thought.
This is the kind of work that's completely invisible to users and takes weeks to get right.
The part I'm actually not ready for
Here's what I've realised after all of this: every technical challenge in this project - the extension reviews, the ORM migration, the Stripe edge cases, the platform gatekeepers - had an answer. Given enough time and enough iteration, there was always a path through.
Marketing doesn't work like that. There's no PR to merge that convinces site owners to integrate your plugin. No SQL query that gets everyday web users to switch their habits for a better ad experience. It requires a completely different set of skills, and for the first time in this whole project I'm genuinely unsure whether I have them.
All of this scares me, honestly. Working through technical problems is nothing compared to what comes next.
That's where Zero Ad Network is going now. If you run a website and want to understand how the integration works, the documentation is here. If you've been through your own "now I have to actually grow this thing" moment and have something useful to say about it - I'd genuinely love to hear it.
The source code for all of it - browser extension, TypeScript module, PHP module, and WordPress plugin - is publicly available under Apache 2.0 (GPL 3.0 for WordPress, because that's what they prefer). Study it, file an issue. Contributions are more than welcome.
Fingers crossed. 🤞
Stay tuned
