Blog · Meta Ads Reporting

Meta ads reporting without the spreadsheet grind

Published July 17, 2026 · 8 min read

Most Meta ads reporting is a weekly ritual: open Ads Manager, set the date range, pick the breakdowns, export, and rebuild the same pivot table you built last Tuesday. This guide shows the alternative: connect Meta Ads once via OAuth, keep the data resident and queryable, and let an AI agent answer the recurring questions — campaign ROAS rankings, ad sets burning money with zero conversions, this week versus last — in seconds of SQL instead of an afternoon of spreadsheet work. At the end, the whole thing gets pinned to a live URL, so next week there is no ritual at all.

The Ads Manager export loop

Ads Manager is a fine place to run campaigns and a frustrating place to answer questions. The loop looks like this:

  • Every question needs a fresh export — columns configured again, date range set again, breakdown re-picked again.
  • The export is a snapshot. By Thursday it's stale; the pivot table built on it is staler.
  • The numbers live alone. Comparing Meta against Google Ads means a second export, a second dialect, and a VLOOKUP with a definitions problem — Meta's purchase value is not the same column, name or concept as Google's conversion value.
  • Sharing means screenshots, and screenshots invite the worst question in reporting: "is this current?"

None of the individual steps is hard. The grind is that they repeat — weekly, per account, per client — and repetition is exactly the work that shouldn't belong to a human anymore.

Meta ads reporting as queries, not exports

The structural fix: stop pulling data out to where the questions are, and move the questions to where the data lives. TableBI is a data backend built for that, designed to be driven by an AI agent — its tagline is "the data backend for your Claude Code," Claude Code being Anthropic's terminal-based coding agent. You don't need to write the SQL below yourself; the agent does, and definition macros keep the arithmetic honest either way. Setup is two commands and one OAuth screen:

terminal
npm i -g @tablebi/cli
tablebi login
tablebi install

# browser opens for OAuth, then the account syncs in
tablebi connect meta_ads

Meta Ads is in beta. The Meta app hasn't cleared App Review yet, so today it only authorizes ad accounts you own (or accounts added as test users). Everything else on this page is live.

From then on the account is resident and current. Data lands in two altitudes: facts, the cross-channel table with unified definitions (date, platform, account, campaign, ad group, ad — with clicks, impressions, cost, conversions, conversion value), and meta_ads_raw, the lossless platform-native rows for when you need exactly what Meta reported. Reporting stops being an export and becomes a query.

The queries that replace the pivot table

Four workhorses cover most weekly Meta reviews. Campaign ranking first — spend and ROAS, using the roas() macro so the formula is applied one way, every time:

claude code → tablebi
# campaign spend + ROAS, last 28 days
tablebi ask "SELECT campaign, SUM(cost) AS spend,
             roas(SUM(conversion_value), SUM(cost)) AS roas
             FROM facts
             WHERE platform = 'meta_ads'
               AND date >= (SELECT MAX(date) FROM facts) - 28
             GROUP BY campaign ORDER BY spend DESC LIMIT 20"

Then the budget-leak check — ad sets that spent money and converted nothing. In Ads Manager this is a sort, a squint and a scroll; here it's a HAVING clause:

claude code → tablebi
# spending with zero conversions, last 14 days
tablebi ask "SELECT campaign, ad_group, SUM(cost) AS spend
             FROM facts
             WHERE platform = 'meta_ads'
               AND date >= (SELECT MAX(date) FROM facts) - 14
             GROUP BY campaign, ad_group
             HAVING SUM(cost) > 0 AND SUM(conversions) = 0
             ORDER BY spend DESC"

Week-over-week movement, without exporting two date ranges and eyeballing them side by side:

claude code → tablebi
# last 7 days vs the 7 before
tablebi ask "SELECT CASE WHEN date >= (SELECT MAX(date) FROM facts) - 7
                    THEN 'last 7d' ELSE 'prior 7d' END AS period,
             SUM(cost) AS spend, SUM(conversions) AS conversions,
             roas(SUM(conversion_value), SUM(cost)) AS roas
             FROM facts
             WHERE platform = 'meta_ads'
               AND date >= (SELECT MAX(date) FROM facts) - 14
             GROUP BY 1 ORDER BY 1"

Note the date idiom: windows anchor on MAX(date) in the data, not on today's calendar date — so a query never silently includes days the platform hasn't reported yet. Every answer also carries a trust block: per-source freshness, applicable caveats, and lineage showing exactly which formula produced each derived metric. That's the difference between an agent's answer you double-check and one you forward.

Meta and Google in the same currency

The fourth workhorse is the one Ads Manager can't run at all. Meta reports purchase value; Google Ads reports conversion value; every platform names and measures its own way. In the facts layer both land in one column — conversion_value — with spend, clicks and conversions normalized the same way. That's the entire point of a unified layer: cross-platform comparison becomes one honest query instead of a spreadsheet reconciliation project:

claude code → tablebi
# Meta vs Google, same definitions, one query
tablebi ask "SELECT platform, SUM(cost) AS spend,
             roas(SUM(conversion_value), SUM(cost)) AS roas,
             cpa(SUM(cost), SUM(conversions)) AS cpa
             FROM facts
             WHERE platform IN ('meta_ads', 'google_ads')
               AND date >= (SELECT MAX(date) FROM facts) - 28
             GROUP BY platform"

One caution the trust block will also give you: unified definitions make numbers comparable, not identical in meaning — each platform still attributes conversions its own way, so treat cross-platform ROAS as a steering signal, not a courtroom exhibit. For the Google side of this workflow — query patterns, account structure, the same macros — see Claude Code for Google Ads.

Pin the weekly report as a live link

The last export you ever do is the one you don't: pin the weekly view once, and share a URL that re-pulls from Meta on access and on schedule:

claude code → tablebi
tablebi pin --title "Meta Ads — weekly" \
  --widget "Spend by day (28d)::line=SELECT date, SUM(cost) AS spend FROM facts WHERE platform = 'meta_ads' AND date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY date ORDER BY date" \
  --widget "Campaigns by spend=SELECT campaign, SUM(cost) AS spend, roas(SUM(conversion_value), SUM(cost)) AS roas FROM facts WHERE platform = 'meta_ads' AND date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY campaign ORDER BY spend DESC LIMIT 10"
✓ published → https://<your-ws>.tablebi.com/d/dsh_…  (public, read-only, self-refreshing)

The URL is public and read-only — a media buyer, a founder or a client can open it any day and see current numbers, and each widget has an "ask" button so their follow-up question routes back to you instead of dying in a thread. If you run this across many accounts or clients, the agency reporting guide covers the multi-workspace version; if you'd rather start from ready-made widget lists, these report templates include a paid-efficiency board you can pin verbatim.

What stays in Ads Manager

To be clear about the boundary: TableBI is read-only. Building campaigns, editing creative, shifting budgets, audience work — all of that stays in Ads Manager, where it belongs. And if what you want is a drag-and-drop Facebook ads reporting tool with a template gallery and white-label PDF exports, this isn't that either — reports here are defined as SQL and published as live links, with a "Powered by TableBI" footer. The trade is deliberate: an agent-driven workflow and a URL that's never stale, in exchange for the GUI.

FAQ

Is this a Facebook ads reporting tool that replaces Ads Manager?

No — it replaces the export-and-pivot loop, not campaign management. TableBI is a read-only reporting and analysis layer: you still build, edit and budget campaigns in Ads Manager. What moves out is answering performance questions and publishing reports.

How does the Meta Ads connection work?

One command — tablebi connect meta_ads — opens a browser OAuth flow. After you authorize, spend, impressions, clicks, conversions and conversion value sync into a queryable backend and stay current. Pinned dashboards then refresh themselves on access and on a schedule.

Can I report Meta and Google Ads together in one place?

Yes. The facts layer normalizes both platforms into one set of definitions — Meta's purchase conversion value and Google's conversion value both land in a single conversion_value column — so one query compares ROAS or CPA across both, and one dashboard shows both.

Do I need to know SQL to use this?

Not really. The workflow assumes an AI agent — Claude Code, Anthropic's terminal-based coding agent — writes the SQL from your plain-English question. Definition macros like roas() and cpa() keep the arithmetic consistent no matter who or what writes the query.

Work the numbers first

If you just want the arithmetic before wiring anything up, the free calculators run in the browser — CPM calculator, per-channel ROAS — each taking a row per channel rather than two boxes, and each showing the query that computes the same figure from live accounts. The full set is on free marketing calculators.

Try it

Give your Claude Code a data backend in five minutes.

terminal
npm i -g @tablebi/cli && tablebi install