The report that builds itself: how btodigital's Cerebro IA stopped copy-pasting numbers
37 clients, one click per report and an AI that only writes about numbers code already computed. Architecture, rules and what we learned.
AI, digital marketing and medical marketing consultant · btodigital
The August ad performance reports for 37 btodigital clients were generated with one click each: 39 PDFs since 2 September, produced by 8 people on the team without copy-pasting a single number.
Automating reports is not hard. The hard part is making sure the automated report does not lie in beautifully written prose.
This piece is for you if you run an agency or a services firm with 20 to 100 clients, or if you lead marketing and every month-end disappears into exporting, pasting and explaining numbers. You get the architecture we use, the rules that prevent the most expensive mistakes, and what we learned along the way. For context: btodigital is the digital agency I founded in Medellín, Colombia, in 2013.
What builds itself today?
Three kinds of report now run on the Cerebro IA de btodigital (btodigital’s AI Brain), the internal system that holds each client’s memory.
| Report | Scope | How it is built | Verified figure |
|---|---|---|---|
| Monthly ad report as a branded PDF | 37 clients (August 2026) | One click: Meta Ads, Google Ads, Google Business Profile and Analytics, written up by the AI | 39 PDFs since 2 Sep, by 8 people |
| Web audience report | A regional media outlet | Fully automatic: generated on the 3rd (monthly) and 18th (fortnightly), published and emailed | 15,706 users in September, 3,696 automated visits excluded |
| Weekly “improving, same or worsening” dashboard | A clinic | Fully automatic, with closed weeks and noise bands | As of 2 Oct: 4 weeks “same”, 13 weeks “improving” |
The audience report is the most automated. Nobody on the team touches it: at 7 a.m. on the 3rd of each month the data is collected, the PDF is assembled, published and emailed to the recipients the team configured in the dashboard. It includes a section on the technical maintenance done on the site during the period. If anything fails, the alert goes to the team, not the client.
How is it built?
Six layers. The rule that governs them: the AI computes no numbers at all. It only writes about figures the code has already calculated.
| Layer | What it does | With what |
|---|---|---|
| 1. Sources | Ads, analytics, Google Business Profile, CRM, WhatsApp, invoicing | Meta, Google Ads, Analytics and Search Console APIs, the client’s CRM |
| 2. Scheduled ingestion | Pulls data at fixed times with nobody pressing a button | Cloud Run and Cloud Scheduler |
| 3. Storage | Holds data, configuration and report history | Firestore and BigQuery |
| 4. Rules | Computes changes, filters bots, decides whether a change is noise or signal | Our own code, with tests |
| 5. AI that writes | Turns already-computed figures into a summary, findings and recommendations | Gemini with JSON output and a thinking budget of 0 |
| 6. Delivery | Branded PDF, permanent link, email, approval where needed | Our own PDF generator and transactional email |
Layer 5 is the one everyone sells and the one that should decide the least. We pass the model a JSON with the figures and their changes, and ask for another JSON with the text. No free-form reasoning: switching it off stops the model from burning the output limit on thinking and returning a truncated JSON, something that already happened to us and that I described in the piece on the Gemini 2.5 retirement.
And nothing learned is lost: every generated report feeds the Cerebro IA de btodigital with what worked in the period (best-performing ads, traffic, findings), so each client’s memory is built from results and not only from what the team remembers.
Which rules stop the report from lying?
Every one of these rules came from a specific case.
- Closed weeks only. The dashboard compares full Monday-to-Sunday weeks. The current week never counts, and the latest week only counts once it has matured, because many appointments are recorded days after they are booked.
- Grey when a source is late. If the CRM did not sync, if ad spend shows as zero, or if WhatsApp brings no messages, the dashboard gives no verdict: it turns grey and says why.
- The same bot filter on both periods. Comparing a clean month with a dirty one manufactures growth that does not exist.
- What gets saved is what the client sees. A result is never trimmed when stored. If the saved report loses detail, the client gets bars with no explanation.
- A guard against account cross-overs. Before linking an ad account, an Analytics property or a Business Profile, the system checks whether it already belongs to another client and warns.
- The AI only writes on deterministic data. If the code did not compute a figure, the AI does not mention it.
The rule that saves the most arguments is the noise band. Each metric has a normal range of variation, measured from its own history between November 2025 and September 2026: for appointments, around 12 to 15% over a four-week window; for cost per appointment, 15 to 20%. If a change falls inside that band, the dashboard says “same” even though the number moved. Between one and two bands, it says “signal”. Two bands or more, “confirmed”. Longer windows narrow the band, and with few cases it never drops below the statistical noise you would expect anyway.
A real example: in the four weeks ending 27 September, the clinic’s appointments were down 6% and cost per appointment down 5%. Both were inside the noise, so the verdict was “same”. Without the band, either number would have been enough to start an argument.
Does it lead to better decisions?
One case. In August the clinic’s appointments fell. There were several possible explanations: the sales team, the budget, audience fatigue.
Matching every WhatsApp conversation to the ad that triggered it told a different story. Thirteen winning ads were switched off between July and August, and those thirteen carried 1,379 conversations; the total drop was 992. The sales team’s conversion rate held steady at around 12%. Ad frequency was flat, so it was not audience fatigue either.
That produced a rule for the media roadmap: never switch off a winning ad without a proven replacement. And a conversation with the client grounded in evidence rather than suspicion about their sales team.
What we learned
A list-based bot filter is not enough. Automated traffic does not always carry known page titles, and a filter that only looks for those titles misses it. That is why the filter detects by behaviour (country, volume, duration) and is applied identically to both periods being compared. It also explains why the automatic figure can differ slightly from a manual clean-up, and I would rather say so than hide it.
A late source must not look like an up-to-date one. A dashboard that keeps showing confident-looking numbers when the sync fails misleads without meaning to. That is why the grey rule and a visible stale-source banner exist.
A year-over-year comparison only works if last year is comparable. At the clinic, 90% of 2025 appointments had been marked as won in the CRM on 11 and 12 March 2026, in a bulk clean-up of old records. Year-over-year comparison of appointments is not valid until March 2027, and the dashboard now says so instead of calculating it.
Stagger sends before paying for a bigger plan. Two weekly reports went out on the same Monday at 8 a.m., and that day our email provider logged 108 sends against a 100-per-day limit, while the month total was only 434 of 3,000.
Context notes change the report. Reports let the team add context notes (“we cut budget”, “we changed strategy”). We tested it on a real client whose conversions had fallen 57.4%, from 535 to 228. Without a note, the summary treated the drop as a drop. With a test note describing a strategic decision, the AI rewrote it as a “deliberate strategic adjustment” and its first finding became a success story. We deleted the note and regenerated the report. The AI believes what you tell it, with the same conviction whether it is true or not. Any context feeding a report has to be real and verifiable, because the AI will amplify it in very persuasive prose. We later adjusted the prompt so it also works the other way: if a note explains a one-off spike, the AI does not present it as a trend.
How many hours does it save?
I do not know, and I am not going to make it up. We never measured how long a manual report took, so there is nothing to compare against.
What we will measure from now on:
- Time per task type. A “monthly report” task type with mandatory time logging, to build a real baseline.
- Days between month-end and delivery. If the report lands on the 3rd instead of the 12th, the value is there even if the hours look similar.
- Correction emails per report. Every time a client replies “this number does not add up”, it gets counted. It is the best quality metric I know.
When I have those numbers, I will publish them. Same approach as when I measured where my leads came from: data first, conclusion second.
How can you apply this in your agency?
- Start with one report, not all of them. The one that repeats most and requires the fewest judgement calls.
- Separate calculation from writing. Code computes; the AI only turns figures into text, with structured output.
- Define the noise band for your three main metrics using at least six months of history. Without it, every movement becomes a debate.
- Compare closed periods only, with the same bot filter on both.
- Make the dashboard go grey when a source is late, instead of showing stale numbers.
- Audit account cross-overs before the first automated send: an account linked to two clients is the fastest way to lose trust.
- Stagger your sends and check your email provider’s daily limits.
- Require context notes to be verifiable facts, with a date and an owner.
- Measure your baseline before automating: hours per report, days to delivery and correction emails.
If you want to build something like this in your company, this is how I work as a digital marketing consultant.
Frequently asked questions
Can a marketing report be fully automated with AI? Collection, calculation, PDF and delivery, yes. Nobody touches our audience report. But the AI should be limited to writing about figures already computed by code. Let it calculate and, sooner or later, it will invent.
Which AI model writes the reports? Gemini, with JSON output and the reasoning budget set to zero. That way the text always arrives complete and in the same structure, ready for the PDF.
How do you stop bots from inflating the numbers? By detecting automated traffic through behaviour (country, visit volume, duration) in every period and applying the same filter to the comparison period. A filter based on a list of known names was not enough.
What is a noise band? It is a metric’s normal range of variation, measured from its own history. If a change stays inside the band, it is reported as “same”. It stops you reacting to movements that are pure chance.
How much time does automating reports save? We did not measure before automating, so I have no honest figure. We are measuring it now through time per task, days between month-end and delivery, and correction emails per report.
Can the client request corrections? Yes, and it is one of the metrics we care about most. Every correction points to a missing rule.