How Do I Connect Claude to the Meta Ads CLI? (Setup + Usage Guide)

Build-in-public post — the setup we use to let Claude read Meta ad data and prescribe the next move. Part of our AI workflows pillar.

The customer pain point

The weekly paid-ads ritual at most brands: export Ads Manager to a spreadsheet, eyeball which creative is fading, manually decide what to test next. It's slow, it's inconsistent week to week, and it's exactly the kind of pattern-recognition work a model does well — if it can actually see the data.

The blocker is access. Claude can't log into Ads Manager. So you either keep copy-pasting screenshots (lossy, slow) or you give it a clean pipe to the Meta Marketing API. This is the pipe.

Table of Contents

Key Takeaways

Point Details
The pipe A thin CLI over the Meta Marketing API → Claude reads campaign/ad-set/ad performance as structured data, not screenshots.
Setup Meta system-user token + a CLI wrapper + connect to Claude via MCP or stdout pipe. ~1–2 hrs one-time.
What it does Pulls performance, ranks creative by fatigue/ROAS, drafts the next creative test brief.
Guardrail Read-only token. Claude analyzes and recommends; a human pushes changes to the ad account.

What "Meta Ads CLI" Means Here

"Meta Ads CLI" = a small command-line tool you build that wraps the Meta Marketing API. It exposes a few commands:

  • ads:performance --account <id> --since 30d → JSON of every ad's spend, ROAS, CTR, CPM, frequency
  • ads:creative --account <id> → creative metadata + thumbnails per ad
  • ads:fatigue --account <id> → frequency + declining-CTR flags per ad

Claude calls these, gets clean JSON, and reasons over it. No screenshots, no copy-paste, no lossy context.

Setup: Meta API Access

  1. Create a System User — business.facebook.com/settings/system-users → Add → name it branva-ads-readonly.
  2. Grant asset access — assign the ad account with read/analyze permission only. Do not grant ad-management write access for the analysis pipe (least privilege — see guardrails).
  3. Generate a token — System User → Generate New Token → select your app → scope ads_read only. Set expiry to Never (System User tokens can be permanent).
  4. Store the token — environment variable, never in code. META_ADS_TOKEN=..., META_AD_ACCOUNT_ID=act_....

Setup: The CLI Wrapper

A minimal Node/Python script that hits the Marketing API insights endpoint. The core call:

GET https://graph.facebook.com/v18.0/{ad_account_id}/insights
  ?level=ad
  &fields=ad_name,spend,purchase_roas,ctr,cpm,frequency,impressions,actions
  &date_preset=last_30d
  &access_token={META_ADS_TOKEN}

Wrap that in a command that prints clean JSON to stdout:

node meta-ads.mjs performance --since 30d > /tmp/ads.json

Add a fatigue command that flags ads where frequency > 2.5 AND CTR has declined over the window — that's the creative-fatigue signal Claude will key off.

Connecting Claude (MCP or Pipe)

Option A — MCP server (most integrated). Wrap the CLI commands as MCP tools (ads_performance, ads_creative, ads_fatigue). Claude calls them mid-conversation, reasons, and returns recommendations in one loop. Best for recurring weekly reviews.

Option B — stdout pipe (fastest to start). Run the CLI, pipe the JSON into a Claude prompt. No MCP infra. Good for proving the workflow before investing in the server.

node meta-ads.mjs performance --since 30d | \
  claude -p "$(cat prompts/weekly-ads-review.txt)"

Start with B, graduate to A once the weekly cadence is set.

Usage Prompts

Weekly creative review:

Here is the last 30 days of Meta ad performance (JSON):

{piped ads.json}

Business context: AOV ${X}, target ROAS {Y}x, monthly budget ${Z}.

Do three things:
1. Rank ads into WINNERS (scale), HOLDS (keep), CUT (kill this week)
   based on ROAS vs target AND fatigue (frequency > 2.5 with
   declining CTR). Be decisive — name the cuts.
2. For the top 2 winners, identify what they have in common (hook,
   format, angle) — that's the pattern to make more of.
3. Draft 3 new creative test briefs for next week based on the winning
   pattern. Each brief: hook, format, angle, and what it's testing
   vs the current winner.

Be concrete. This goes straight into the creative pipeline.

Spend efficiency check:

From the same JSON: which ad sets are spending the most with the
worst ROAS? Give me the single reallocation that would most improve
blended ROAS this week — move $X from ad set A to ad set B, with the
reasoning. One recommendation, not five.

What to Watch For

  • Read-only token. Always. The analysis pipe never needs write access. Claude recommends; a human makes the change in Ads Manager. A write-scoped token connected to an LLM is an unacceptable blast radius. (More on AI failure containment: what AI-run means when the AI screws up.)
  • ROAS attribution is Meta's number, not truth. Meta over-attributes to itself. Feed Claude blended/MTA data alongside Meta's if you have it, and prompt it to treat Meta ROAS as relative (compare ads to each other), not absolute. See ecommerce analytics: the 7 KPIs.
  • Frequency + declining CTR = the fatigue signal. Don't let Claude cut an ad purely on a ROAS dip — early-window noise looks like decline. The fatigue flag (frequency threshold + sustained CTR decline) is the reliable trigger.
  • Token cost is trivial here. The JSON for a 30-day account is small (a few thousand tokens). The reasoning call is a few cents. This is a time-saver workflow, not a cost concern — the value is the consistent weekly decision, not compute.
  • Keep a human in the creative loop. Claude drafts test briefs; a human (or our creative pipeline) produces and approves the actual creative. We covered why in what an AI marketing agency actually does.

Talk to Branva

We run weekly AI-assisted creative review + the creative pipeline that acts on it as part of transparent monthly marketing. Book a free call — we'll show you the weekly cadence on your own account.

Frequently Asked Questions

Is there an official "Meta Ads CLI"?

No single official one — "Meta Ads CLI" here means a thin wrapper you build over the official Marketing API. The API is official and documented; the CLI is your convenience layer so Claude gets clean structured data.

Why not just paste Ads Manager screenshots into Claude?

Screenshots are lossy (truncated columns, no exact numbers), not repeatable, and burn vision tokens. A JSON pipe gives Claude exact figures for every ad and makes the weekly review a one-command ritual.

Do I need MCP?

No. Start with the stdout-pipe version (run CLI, pipe JSON into a prompt). MCP makes it a seamless in-conversation loop but it's an optimization, not a requirement.

Should Claude be able to change my ad account?

No. Use a read-only (ads_read) token. The workflow's value is analysis and recommendation; the actual account changes stay with a human. Never connect a write-scoped ads token to an autonomous LLM loop.

What about Google Ads?

Same pattern — wrap the Google Ads API in a CLI, pipe to Claude, use an analogous prompt. The Meta version is documented here because it's where most Shopify brands' spend concentrates.

More from the blog

All posts

Tell me what your store is doing now. I'll tell you what I'd fix first.

A 30-minute call. Bring your ad account and Shopify numbers if you can. You leave with a short list of priorities, whether or not we work together.