Every morning, before I built this system, my routine was always the same: open Ads Manager, choose an account, look at yesterday’s numbers, go back, choose another one. With multiple clients across different Business Managers, this meant spending the first hour of the day figuring out where to look instead of deciding what to do. The problem wasn’t a lack of data. Meta provides plenty of it. The problem was that none of those numbers arrived already sorted by importance.
So I decided to build a web app that connects directly to the advertising data from all the accounts I manage and handles the first pass for me: it reads, compares, and flags. In my head, I call it the control room.
The Problem Before the System
With a single client, checking campaigns manually is manageable. With many clients, the same activity stops scaling: the time required to review everything grows with the number of accounts, while the amount of time available to actually intervene stays the same. The real risk is that an account performing poorly for three days might only be noticed on the fourth, simply because that happened to be the day it came up in the order I opened the accounts.
Put simply, the problem was this: I needed to know where to look in advance, not look faster.
What I Actually Needed: Not More Data, but Priorities
The first temptation when tackling a problem like this is to build a dashboard that shows everything: spend, leads, cost per lead, frequency, for every account, every day. It’s a common mistake, and I made it in the first version too. The result was a screen full of numbers that still took time to read. I had simply moved the problem from Ads Manager to my own dashboard.
What I needed was different: a system that looks at every account, applies an attention threshold (spend increasing without results, cost per lead moving away from the account’s average, frequency getting too high), and returns only the accounts that deserve to be opened, ranked by urgency. Everything else remains available, but it doesn’t need to be the first thing I see.
How the Control Room Works
The basic setup is simple: the system reads the advertising data from every connected account, compares it with the account’s recent history (rather than a generic average, which wouldn’t make much sense across different clients), and runs a diagnosis.
The diagnosis doesn’t stop at “this number is low.” It tries to explain why. If a campaign generates plenty of clicks but few leads, the system flags that the problem is probably happening after the click, such as the landing page or form, rather than with the creative, which is doing its job of attracting attention. If clicks are low from the start, the suspicion shifts toward the ad’s image or copy. It’s a small distinction on paper, but it’s the one that saves the most time: knowing where to look before even opening the account.
On top of the individual campaign diagnosis, the system groups accounts by client and status: who needs to be watched, who is performing well, and who has no active campaigns. In the morning, the first thing I see isn’t a list of accounts. It’s a list of problems, already ranked.
What It Shows and What It Deliberately Hides
One of the most counterintuitive parts of the process, perhaps the most important one, was deciding what not to show immediately. An account with an old campaign that has been inactive for months, with no spend, doesn’t need to appear among the daily priorities: it’s noise. Campaigns with no recent activity remain visible, but they are grouped separately instead of being mixed in with campaigns that are actually spending budget right now.
The same applies to data from the current day. Looking at “today’s” spend halfway through the morning and comparing it with yesterday’s full-day spend almost always leads to the wrong conclusion: it makes the campaign look like it’s performing worse simply because the day isn’t over yet. The system keeps today’s data separate, marks it as partial, and compares today’s spending pace with what that same campaign was spending at the same time the previous day, rather than with yesterday’s final total. It’s a small but necessary adjustment: without it, the first alert of the day would almost always be a false alarm.
What I Had to Fix Along the Way
The first version of the system generated too many alerts. Any variation above an arbitrary threshold ended up on the list of things to check, and within a few days the list had become almost as long as the old manual routine. I had automated the noise instead of filtering the signal.
The fix was to raise the threshold only where it really mattered (spend without results, rather than a small fluctuation in cost per lead) and distinguish between an isolated one-day decline and a decline that lasts for several consecutive days. A single bad day can be caused by a thousand things, including the delay with which Meta itself records leads that came in during the last few hours. A trend that has lasted for a week is a different story.
What I’m Taking Away From This Project
The biggest benefit hasn’t been the time saved in the morning, even though that is real. It has been stopping problems from being discovered late. If an account starts losing effectiveness, I see it the next day rather than after a week in which nobody had a reason to open it.
The part that required the most work, and the lesson that applies far beyond this specific project, wasn’t connecting the data. It was deciding what actually counts as a “problem” and what doesn’t. A system that flags everything is just as useful as one that flags nothing.
The next step, which I explore in the related article, focuses on exactly this: how the diagnosis works when the system identifies a problem, and why I had to put precise limits on what the AI is allowed to suggest changing.



