Skip to content

Fix live reports: Graph adapter + selectable backend (graph | social-cli)#8

Open
TheMattBerman wants to merge 2 commits into
mainfrom
live-insights-adapter
Open

Fix live reports: Graph adapter + selectable backend (graph | social-cli)#8
TheMattBerman wants to merge 2 commits into
mainfrom
live-insights-adapter

Conversation

@TheMattBerman

Copy link
Copy Markdown
Owner

Problem

Every report worked in mock mode but errored against the live API. The report layer's jq targets an internal schema (account_summary, campaign_insights[], ad_insights[], ad_daily[], today_campaign_spend[]) that only the mock fixtures produced; the non-mock path piped raw API responses straight through. Root cause: the official Ads CLI's insights get is account-level only (no --level), so it can't return per-campaign/per-ad rows — and the kit's earlier migration to that CLI is what dropped the --level support its reports depend on.

Fix

1. Graph API insights adapter (scripts/lib/live-adapter.sh)

  • Pure, unit-tested transform (mk_assemble_insights) from raw API responses → the kit's internal schema.
  • Thin fetch layer using level=campaign / level=ad (one call each — scales past hundreds of ads). Memoized per run, paginated, rounds ctr/cpc/freq.
  • Campaign list still uses the official meta CLI, normalized to {data:[...]}.

2. Selectable backend (META_KIT_BACKEND)

  • graph (default) — direct Marketing API via curl. Fast, zero extra deps.
  • social-cli@vishalgojha/social-cli, the kit's original engine: native --level insights, mutations, OAuth. Slower (async report jobs).
  • Both feed the same pure transform, so report output is identical. scripts/lib/backend-social.sh strips social-cli's stdout preamble and uses --export for clean JSON.

3. Env precedence fix (scripts/lib/config.sh)

  • .env no longer clobbers variables already set on the command line, so META_KIT_MODE=mock ./run.sh … reliably forces mock (the documented override was previously silently broken when .env existed).

Tests

  • scripts/test/test_live_adapter.sh — 23 offline assertions (transform → schema, rounding, report render).
  • scripts/test/test_social_backend.sh — 10 offline assertions (preamble strip, normalize, social arrays → shared transform).
  • Synthetic fixtures only — no account data, no network.

Notes

  • social-cli backend is slower (~50s, async report jobs) vs. graph (~2s).
  • Pacing target: graph sums campaign + ad-set budgets (account-level ad-sets edge); social-cli has no such edge, so its target is campaign(CBO)-budget-based and under-reports ad-set-budget accounts. Spend/winners/bleeders/fatigue are identical across backends.
  • Verified live (read-only) on a real ad account with both backends.

🤖 Generated with Claude Code

TheMattBerman and others added 2 commits June 10, 2026 12:20
…k mode

The report layer's jq targets an internal schema (account_summary,
campaign_insights[], ad_insights[], ad_daily[], today_campaign_spend[]) that
only the mock fixtures produced. The non-mock path piped raw responses straight
through, so every report (pacing, overview, winners, bleeders, fatigue) errored
against the live API — the kit effectively only ran in mock.

- scripts/lib/live-adapter.sh: pure transform (mk_assemble_insights) from raw
  Graph responses -> internal schema, plus a thin fetch layer (mk_build_live_insights)
  and campaign-list normalizer. Uses the Marketing API for level=campaign/level=ad
  breakdowns because the official Ads CLI `insights get` is account-level only.
  Memoized per process; rounds ctr/cpc/freq to 2dp; follows paging.
- scripts/lib/meta-cli.sh: route insights ops through the adapter; normalize the
  CLI campaign list into {data:[{id,name,status}]}.
- scripts/lib/config.sh: .env no longer clobbers variables already set on the
  command line, so `META_KIT_MODE=mock ./run.sh` reliably forces mock.
- scripts/test/: offline unit tests for the transform (23 assertions, synthetic
  raw-shape fixtures — no client data, no network).
- docs: README/SETUP/.env.example document the Graph API insights path,
  GRAPH_API_VERSION, the env-precedence rule, and the multi-brand patterns.

Verified live (read-only) against two real accounts; mock mode unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…l-cli)

social-cli (@vishalgojha/social-cli) was the kit's ORIGINAL engine and natively
supports `marketing insights --level campaign|ad --time-increment` plus mutations
and OAuth. The migration to the official Ads CLI is what dropped --level and broke
live reports. This brings the richer engine back as an opt-in, alongside the
zero-dependency Graph backend.

- scripts/lib/config.sh: mk_backend() reads META_KIT_BACKEND (default graph).
- scripts/lib/backend-social.sh: social-cli fetch layer — preamble stripper,
  --export-based insights (clean JSON), flat-array -> {data:[...]} wrapping so it
  reuses the SAME pure transform (mk_assemble_insights) as graph. Campaign-list
  + status + level insights wired; pacing target is campaign-budget-based
  (social has no account-level adsets edge — documented).
- scripts/lib/live-adapter.sh: mk_build_live_insights dispatches by backend;
  graph fetch extracted to mk_fetch_bundle_graph.
- scripts/lib/meta-cli.sh: campaign-list routes by backend; doctor reports
  backend + social-cli presence/version.
- scripts/test/test_social_backend.sh: 10 offline assertions (preamble strip,
  normalize, social arrays -> shared transform). Graph suite still 23/23.
- docs: README/SETUP/.env.example document both backends, the install/auth for
  social-cli, the speed trade-off, and the pacing-target caveat.

Verified live (read-only) on a real ad account: both backends produce identical
spend/winners/bleeders/fatigue. Fixed a recurrence of the "${var:-{}}" brace bug
in the social account-meta path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant