AdFriend - Your Ad Blocking Sidekick


Let me introduce you to AdFriend — a customized Chrome AdBlocker that not only blocks annoying ads on your browser but also replaces them with meaningful content based on your preferences.
This article focuses more on the technical development rather than the product itself — the story of my sleepless, coffee-driven nights and a testimony that you can, in fact, bite more than you can chew :)
Deep Dive
This project was actually inspired by Julien Barbier’s challenge, and at the time, I had no idea, let alone, experience on building Chrome extensions. But that didn’t stop me from diving headfirst into the rabbit hole. Armed with way too many open tabs, a half-functioning debugger, and a vague understanding of how Chrome APIs worked, I set out to build something that could block ads and replace them with something better.
The first hurdle? Figuring out how to intercept and modify web requests. Chrome’s declarativeNetRequest
API seemed like the right choice—until I realized its limitations when trying to inject custom content. That led me to chrome.scripting
, which gave me the power to manipulate DOM elements dynamically. Sounds easy, right? Yeah, until you’re debugging scripts injected into a page that reloads every time you test it.
The "Why Is This Not Working?" Phase
If you’ve ever built a Chrome extension, or anything that involves code for that matter, you know that things never go smoothly the first time. Or the second. Or the tenth.
One of my biggest struggles was getting permissions right in manifest.json
. I must have gone through a dozen iterations, each time getting slapped with vague errors that felt more like riddles than actual debugging hints. At one point, I had an extension that could block ads… but not replace them. Then, I had one that replaced ads… but only after a manual refresh. And, of course, the version that worked perfectly—except on actual websites people use.
At 3 AM, fueled by coffee and stubbornness, I finally had a breakthrough: instead of replacing ads post-load, I needed to hook into the page lifecycle earlier using a MutationObserver
. This allowed AdFriend to detect and swap out ads as soon as they appeared, creating a seamless experience.
Adding the "Meaningful" Part
Blocking ads is one thing, but replacing them with content tailored to the user? That was another challenge altogether. I built a simple preferences system that let users choose what kind of content they wanted—motivational quotes, coding tips, news snippets, or even their own custom messages.
This involved setting up a lightweight storage system using chrome.storage.sync
, allowing settings to persist across sessions. From there, a small content-fetching module pulled relevant snippets and dynamically inserted them in place of ads. The first time it worked properly, I stared at the screen for a good minute, trying to process the fact that I had actually made it work.
Lessons Learned (and a Few Regrets)
- APIs are deceptive – Chrome’s documentation makes everything sound straightforward, but the reality is a game of trial and error.
Debugging extensions is a nightmare – Unlike web apps, where you can log everything to the console, debugging injected scripts comes with its own brand of suffering.
Don’t over-engineer – At one point, I considered integrating an AI-generated content system. Thankfully, I stopped myself before I went completely off the rails but that’s definitely on my to-do list regardless — nobody can stop reggae.
Final Thoughts
AdFriend started as an experiment, but it turned into something surprisingly useful. It’s not perfect, but it works—and more importantly, I built it from scratch with zero prior experience in Chrome extension development. If you’re thinking of creating your own extension, my advice is simple: start small, expect chaos, and just keep pushing through.
Now, if you’ll excuse me, I need to catch up on all the sleep I sacrificed for this project. Ohh, and please try it out yourself here
Subscribe to my newsletter
Read articles from ALLAN directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
