← The archive

How I automate an entire paid media agency with Claude Code

Stephan Ochse ·

At 5:47 this morning, while I was asleep, 107 Google Ads accounts got audited.

223 checks each. Two problems surfaced. A spend spike on one, a broken feed on another, and both fixes were written up before I opened my laptop. I read the thread, typed one word, went back to my coffee.

The word was "approved." That was my whole job this morning.

I run 100+ accounts spending between $300k and $2.5M a month, and I don't live inside dashboards to do it. One person, no ops team. So here's the actual machine, tool by tool, setting by setting. Nothing held back. Steal the parts that fit your business, that's what this is for.

First, the boring truth.

There's no war room. It's a row of Mac minis next to my desk and one power strip. Total payroll is an electricity bill. And boring is the point. Anything exciting in an ops system is usually a thing about to break. It took me two years to make this dull.

[IMAGE-1: hyper-real Slack channel #ops-audit at 5:47 AM, a thread reading "Nightly audit complete, 107 accounts, 2 flags" with two proposal cards below, one "Spend spike: account ****72, 41% over pace", one "Feed: 183 products disapproved", each with a small green "approved" reply underneath]

The stack is Claude Code plus a handful of scheduled jobs. That's it. No custom app, no $2k-a-month platform with a login I forget. Claude Code is the worker. The schedule is the manager. I'm the one who says yes or no.

Let me show you how the manager works, because this is the part people overbuild.

The trick nobody tells you about scheduling.

You don't need an app to run an agent on a timer. You need cron and a text file.

Here's the whole shape. I write the job as a plain markdown file, the way I'd write instructions for a new hire on day one. A one-line shell script feeds that file to Claude Code in headless mode, and a cron entry fires it on a schedule. Think "run this SOP at 2am, every night." The schedule decides when. The markdown decides what. The agent does the work, writes the result to a folder, and drops a summary in Slack.

So the job description is the product. Not the code. The code is four lines and you'll never touch it again. The value sits in how well you wrote the instructions, same as it would for a person you onboarded.

One thing I learned the hard way. Make the job check its own work before it reports. My audit re-pulls every number it's about to flag and reads it a second time against the source of truth, Shopify for revenue and the bank for spend, not whatever a single dashboard claimed. An agent that reports without verifying will hand you a confident wrong answer at 2am, and you won't catch it until a client does.

[IMAGE-2: hyper-real macOS terminal, a crontab line up top reading "0 2 * * * /Users/ops/run-audit.sh", below it a Claude Code headless run streaming "Account 12/107 · 223 checks · verifying against Shopify · done" in clean monospace, a couple of green check glyphs]

What the nightly audit does.

Every night it pulls each account through the Google Ads API, runs 223 checks against it, and writes down what it finds. Three hours of manual work per pass, done in 28 minutes while I sleep.

The 223 checks live in one file. A checklist. Wasted spend on search terms nobody would buy from. Budgets capped on the campaigns doing the converting. Bid strategies fighting each other. Conversion tracking that stopped firing three weeks ago. Every check has a rule and a dollar figure attached, so the output never reads "consider reviewing your search terms." It reads "you're paying $6.1k a month for traffic that has never once converted, here's the exact list."

You don't build an AI to do this. You write a very good checklist and hand it to something that never gets bored on check number 190. That's the reframe it took me too long to reach. The checklist is the intelligence. The agent just reads it without complaining.

[IMAGE-3: hyper-real audit report document titled "Nightly audit · account ****72", priority rows each priced in the margin, "$6,100/mo capped campaigns", "$2,400/mo uncovered search terms", "$1,900/mo PMax eating brand", red and amber status dots down the left, a bold "leaking $10,400/mo" total at the bottom]

The one dropdown that pays for everything.

Here's a setting most accounts get wrong, and it hides money in plain sight.

Read performance on conversion time, never click time. In Google Ads reporting that's one dropdown. Most agencies leave it on the default, which is click time, and the default lies to you in a specific way. It lets brand campaigns take demand you were always going to get, the people typing your own store name into Google, and sell it back as a fresh win. On click time the brand line looks like a hero. On conversion time you see what drove a new customer versus what stood in the doorway taking credit for a sale that was already yours.

Every morning the agents read the money on conversion time and split brand from non-brand before they price a thing. That one setting is the gap between a report that flatters you and a report that's true.

[IMAGE-4: hyper-real Google Ads reporting screen, the attribution date dropdown open with "Conversion time" selected above "Click time", a brand campaign row highlighted showing ROAS falling from 8.1x on click time to 2.3x once brand is isolated, real Google Ads blue-and-grey UI]

The check that makes no sound.

At 5am a job opens Merchant Center and reads the diagnostics tab. Disapproved items, GTIN errors, anything that dropped out of the feed overnight.

This one matters more than it sounds, because a feed breaks in silence. A single catalog sync can strip the GTINs off a batch of products and disapprove 183 of them, and Merchant Center never emails you, never throws a banner. Shopping campaigns don't scream when products fall out. They serve less and drift the spend onto whatever's left, and the number looks a little soft for a week before anyone thinks to look. Thirty minutes of feed cleanup once brought back around $6.1k a month in Shopping revenue that was there the whole time, switched off.

Now the disapproved count gets read before breakfast, and a jump becomes a proposal instead of a hole in next month's numbers.

[IMAGE-5: hyper-real Merchant Center Diagnostics tab, a red "183 disapproved" count, a table of products all showing a "Missing GTIN" error down the rows, the real Merchant Center left-nav and blue header]

The rest of what runs, and none of it waits on me:

→ Alerts, in real time. A spend spike pings Slack the Tuesday it happens, not in Friday's report when the money's already gone. The logic is dumb on purpose: compare today's pace against the trailing 7-day average, and if it's 30% over by noon, say something.

→ Reports, drafted over the weekend, sent Monday. The agent pulls the month, fills the template, drops six client reports in a folder while I'm off. Few questions come back, because the numbers were right before anyone read them, and read on conversion time.

→ Replies, triaged in four minutes. The cold-email pipeline runs on Instantly, verified addresses, a real first line for each person, and the good replies book themselves onto my calendar. 16 meetings last month, not one I chased.

→ The creative desk. One product photo goes in, twelve ad variants come out, the YouTube cuts and the Demand Gen images in the same batch. A round that used to cost a designer a week.

Now the line I'll never let a machine cross.

The agents draft. They never decide. Every flag shows up as a proposal with the fix already written, and it sits there until I type yes or no. Turning a budget up, moving real spend between accounts, that gets a human every single time. Not because the agent couldn't do it. Because that call was the one part that was ever my job.

I didn't automate the judgment. I automated everything that was never judgment in the first place. The pulling. The checking. The formatting. The catching. None of it ever needed me. It just used to have me.

Here's what most people get backwards about all of this.

They think running a company on agents means learning to code. It doesn't. I haven't written a line of it, and I haven't opened a CV to hire for it in years. If you can run a clean inbox and write clear instructions for a new assistant, you can run this. It's reading and deciding, nothing more exotic than that.

They also think the AI is the chat window. The chat window is the interview. The thing that earns its keep looks like plumbing, humming at 2am, checking and retrying with the quiet dignity of good infrastructure. Build the employee, not the conversation.

So if you want to start this week, here's the whole move. One task.

Pick the one thing you do every single week that only ever ate your hours and never your judgment. The report you rebuild by hand every Monday. The list you copy out of one tab into another.

Write its steps down like you're handing them to a new hire on day one. Every step, every trigger, every output, every if-this-then-that. Be boring about it. That document is the job. The tool just reads it back.

Here's what one line of mine looks like: "Pull the last 7 days of search terms. Flag any with over $50 spend and zero conversions on conversion time. Write them to the kill list with the dollar total." That's not code. That's a sentence a smart 15-year-old could follow. The agent follows it too, on 107 accounts, at 2am, without once asking to leave early.

Then look at what you wrote and be honest with it. If following those steps top to bottom finishes the job, an agent runs it. If it has a hole only a real call under pressure can fill, that hole is the human part, and it's the only part worth your day.

Time yourself doing it once by hand. That's your before. When it runs itself next week, you'll feel exactly what you bought back.

And don't try to build all of it at once. That's the trap that takes people out in week one. They read a list like this, try to stand up eight things by Friday, break all of them, and quit before one of them works. This stack took two years. The first job took an afternoon. Pick one. Trust it for a month, until you believe it more than you believe yourself half-asleep. Then add the next.

The company changes hands every evening now. The version that runs at 2am doesn't get tired and never skips check 190. It just isn't me, and it was never meant to be.

So what's the one task you'd hand over first? Hit reply and tell me. I read every one.