Skip to content
adscapi

Reporting (spend / ROAS)

getReport pulls spend, impressions, conversions, and ROAS from one platform so you can see what the conversions you fired actually produced.

Why

Firing events is half the loop. An agent that can also read spend and ROAS can decide whether a campaign is working. One platform per call. Dates are YYYY-MM-DD.

ts
import { getReport } from 'adscapi';

const rows = await getReport('meta', secrets, {
  since: '2026-04-01',
  until: '2026-04-08',
});

for (const row of rows) {
  console.log(row.campaignName, row.spend, row.roas);
}

level defaults to 'campaign'. Pass 'account' for an account rollup (Meta honors it; TikTok always returns auction-campaign rows). Inject fetchImpl in tests.

ReportRow

Google cost_micros is divided by 1e6. Meta spend is already major units. When Google gives conversion value but no native ROAS, adscapi sets roas = conversionValue / spend.

ts
type ReportRow = {
  platform: 'meta' | 'google' | 'tiktok';
  campaignId?: string;
  campaignName?: string;
  spend: number;          // major units, platform currency
  impressions: number;
  conversions?: number;
  conversionValue?: number;
  roas?: number;
  currency?: string;
};

Secrets

PlatformRequired
MetaMETA_AD_ACCOUNT_ID, META_CAPI_TOKEN
Google AdsGOOGLE_ADS_CUSTOMER_ID, GOOGLE_ADS_ACCESS_TOKEN, GOOGLE_ADS_DEVELOPER_TOKEN
TikTokTIKTOK_ADVERTISER_ID, TIKTOK_ACCESS_TOKEN

Google also reads optional GOOGLE_ADS_LOGIN_CUSTOMER_ID (MCC login customer). A missing required secret throws missing required secret <NAME>. A non-2xx from the platform throws PlatformHttpError.

CLI and MCP

shell
adscapi report --platform meta --since 2026-04-01 --until 2026-04-08
adscapi report --platform google --since 2026-04-01 --until 2026-04-08 --level account

The CLI reads secrets from the environment. MCP tool adscapi_report takes the same args: { platform, since, until, level? }.

Notes

  • TikTok ROAS uses complete_payment_roas. That metric name is unverified against TikTok’s supported-metrics list. Spend, impressions, and conversion are confirmed. If the field is absent, roas is omitted — the call still succeeds.
  • One platform per call. Fan out yourself if you want Meta + Google + TikTok.
  • Numbers come back as strings from the platforms; adscapi coerces them with Number().

Related