Skip to content
tech

I Never Ran an Ad in My Life. My First One Was Through the Terminal.

·8 min read·4 views

I had never run a paid ad in my life.

That is not an exaggeration. Never opened Meta Ads Manager to create a campaign. Never configured a target audience. Never uploaded a creative. Never set a budget. Everything I knew about ads came from reading articles and hearing founders complain about Meta's panel.

In February 2026, I needed to run ads for two projects — a church management SaaS and an AI-powered news platform. So I did what any dev would do: opened the terminal and asked Claude Code to help.

My first ever Meta Ads campaign was created entirely through conversation. And it worked.

The only thing I did in a browser

I created a Meta App in the developer portal. Called it llmAds. That was literally the only thing I did in a GUI. Everything else — absolutely everything — happened in the terminal.

Claude walked me through the OAuth flow to generate a long-lived token with the right permissions (ads_management, ads_read, business_management, pages_manage_ads). I copied it, pasted it in my .bashrc, and never needed a browser to manage ads again.

The tools: Pipeboard MCP + Graph API + Nano Banana

I connected three things to Claude Code:

Pipeboard MCP — an MCP server for Meta Ads. With it, Claude can list campaigns, create adsets, pause ads, pull metrics. All via MCP, the open protocol that lets you connect external tools to Claude Code.

Graph API directly — for things Pipeboard doesn't cover, Claude uses curl directly on Meta's API. Hashed custom audiences, server-side CAPI, pixel configurations. Meta's API is massive and no single MCP server covers everything.

Nano Banana — a Gemini CLI integration that generates images via AI. My ad creatives were generated this way. Claude described what was needed, Gemini generated the image, Claude uploaded it via API and linked it to the ad. No Canva, no Photoshop, no designer.

Three tools, zero GUIs. Everything through conversation in the terminal.

"Create a leads campaign for HubNews"

That's how it started. One sentence in the terminal.

Claude created the campaign with OUTCOME_LEADS objective, R$15/day budget (~$3 USD), two adsets (Advantage+ and Interest-based), Meta's native lead form, creatives with copy and CTA, UTMs configured. All in one conversation.

I didn't need to know where the "create campaign" button is. Didn't need to navigate between tabs. Didn't need to understand the campaign-adset-ad hierarchy in Ads Manager. Claude already knew the API structure and created everything in the right order.

For Sistema Reino, I asked for the same thing — but with a different strategy. Instead of a native form, I wanted to send people to an external landing page. Claude created the campaign with CompleteRegistration tracking via pixel, 5 ads with different angles, and two adsets (Broad and Interest-based targeting pastors).

The numbers: ~$100 USD, two funnels, 140 conversions

After 4 weeks running both campaigns, here are the results:

MetricHubNewsSistema Reino
SpentR$262.63 (~$50)R$238.41 (~$45)
Impressions17,16413,950
Clicks771378
CTR4.49%2.71%
CPCR$0.34 (~$0.06)R$0.63 (~$0.12)
Reach12,1237,254
Conversions98 leads42 registrations
Cost/conversionR$2.68 (~$0.50)R$5.68 (~$1.08)
Checkouts3 (R$1,028 / ~$196)

~$100 USD invested total. 140 conversions. Zero minutes in Ads Manager.

Two opposite funnels — and why both are right

The most interesting part isn't the numbers. It's that the two projects use completely opposite conversion strategies, and Claude helped me pick the right one for each.

HubNews:        Ad  Native Meta Form  Lead
                (never leaves Instagram, auto-fill)
                98 leads x R$2.68 = R$262

Sistema Reino:  Ad  Landing Page  Form  14-day Trial  Emails  Paywall
                (high friction, qualified leads)
                42 registrations x R$5.68 = R$238  3 checkouts (R$1,028)

On HubNews, the person never leaves Instagram. The campaign uses Meta's Instant Form — a native lead form. The person sees the ad, taps, and Meta auto-fills name and email from their profile. One tap to subscribe to the newsletter. Zero friction.

For a newsletter, this is perfect. "Cold" leads don't matter — you warm them up with content over time.

On Sistema Reino, the person has to actually want it. The ad sends them to sistemareino.com.br/cadastrar. There, they need to read the pitch, fill in name, email, church name, create an account, and start a 14-day trial. A lot of friction.

But those 42 are hot leads. They gave real data, they're using the product. Three already initiated checkout — R$1,028 (~$196 USD) in potential revenue from R$238 invested.

I wouldn't have known how to choose between these two approaches on my own. Claude suggested the native form for HubNews and the landing page for Sistema Reino. Opposite strategies — and both right for their context.

Optimizations through conversation

None of this was "set and forget." Claude kept showing me what was working and what wasn't, and I decided the next step.

Dead audiences. On Sistema Reino, the Broad adset ran 3 days, spent R$8 (~$1.50), zero conversions. Claude paused it and concentrated 100% on Interest-based — which already had 15 registrations at R$5.40 per reg. No drama, no panel to open.

Bad placements. On HubNews, Audience Network consumed 57% of the budget with zero leads. Claude identified it, removed it via API, and cost per lead dropped immediately.

Creative testing. I tested 11 variations for HubNews — fake Reddit thread, Wojak/Chad meme, terminal screenshot, quote card. Creatives were generated with Nano Banana (Gemini), Claude uploaded them via API and later analyzed performance. V10-Reddit won with a CPL of R$0.80 (~$0.15).

Custom Audiences. I exported 433 subscriber emails from HubNews, and Claude created a hashed Custom Audience + 1% Lookalike for Brazil. All via API.

Each optimization was a conversation. "Analyze the last 7 days." "Which adset is doing better?" "Pause Broad." Response, confirmation, execution.

CAPI: server-side tracking that Claude built

Claude doesn't just manage the ads — it helped me build Meta's Conversions API on the backend.

Anyone on iOS 14+ or using an ad blocker doesn't fire Meta's browser pixel. You lose 20-40% of conversions in your reports. Claude created MetaConversionsService.php in Laravel — a service that fires a Lead event server-side when someone subscribes.

// MetaConversionsService.php — Lead via CAPI
$payload = [
    'event_name' => 'Lead',
    'user_data' => [
        'em' => hash('sha256', strtolower($email)),
        'fbc' => $fbClickId,
        'fbp' => $fbBrowserId,
        'client_ip_address' => $request->ip(),
    ],
    'custom_data' => [
        'value' => 5.00,
        'currency' => 'BRL',
    ],
];

This closed the attribution loop. Meta now knows exactly how many leads came from ads, the optimization algorithm became more accurate, and cost per lead dropped.

The dashboard that didn't exist

Since I never open Ads Manager, I needed a way to see the numbers. Claude built a Meta Ads dashboard inside Sistema Reino's admin panel — route /admin/meta-ads-9f3ad7. It pulls data via Graph API, caches for 1 hour, has a button to force refresh.

It's not the Ads Manager. It's better — because it shows only what I need to see.

What I didn't know I didn't know

I'll be honest: when I started, I didn't know the difference between a traffic campaign and a leads campaign. Didn't know what Advantage+ Audience was. Didn't know Audience Network was a separate placement that ate budget without converting.

Claude knew. And more importantly: it didn't give me a theoretical lecture on ads. It created the campaign, ran it, and when data came in, it showed me what was working and what wasn't. I learned ads by doing, not by reading.

This is fundamentally different from watching a Meta Ads course. In a course, you learn theory and then try to apply it. With Claude, I applied first and understood the theory through results. The feedback loop is immediate — and with real money on the line, you pay attention.

My ads routine now

  1. Open the terminal
  2. Ask: "how are the HubNews and Reino campaigns doing?"
  3. Claude pulls insights from both accounts and gives me a summary
  4. If I need to adjust — budget, targeting, pause an ad — I ask in the same conversation
  5. It applies via API and confirms

No Ads Manager. No switching between accounts. No rebuilding mental context. No fear of clicking the wrong button — because there is no button.

The best part: Claude accumulates context. It knows Audience Network doesn't work for my campaigns. It knows Interest-based outperforms Broad on Reino. It knows V10-Reddit is the HubNews winner. This accumulated context is something no dashboard will ever have.

The takeaway

I didn't ditch the Ads Manager. I never used the Ads Manager.

My first ever ad campaign was created through the terminal, managed by conversation, optimized by data, with creatives generated by AI. ~$100 USD invested, 140 conversions, CAPI implemented, dashboard built, two funnels running.

If you already use Claude Code and run Meta Ads, Pipeboard MCP takes 5 minutes to set up. If you've never used MCP, maybe it's time.

And if you've never run an ad in your life — maybe the terminal is a better place to start than the Ads Manager.

Want to apply this to your project?

Career, code & digital product consulting.

Work with Billy
Billy

Billy

Full Stack Dev & Empreendedor Solo

Building products with code and AI. Creator of HubNews and Sistema Reino.