Section 3 — The Advertiser API · Last verified: MAY 2026

Insights and Reporting

Chapter 19 — Insights and Reporting

Insights are exposed at four scopes, all with the same response envelope:

  • GET /ad_account/insights
  • GET /campaigns/{campaign_id}/insights
  • GET /ad_groups/{ad_group_id}/insights
  • GET /ads/{ad_id}/insights

Pick the scope that matches the question. Account-level for portfolio overview, campaign-level for budget pacing, ad-group level for bid analysis, ad-level for creative performance.

Query parameters

ParameterTypeNotes
time_granularitystringdaily (one row per day) or none (one aggregated row over the time range).
aggregation_levelstringad_account, campaign, ad_group, or ad. Lets you query an account-level endpoint and group results by ad.
limitinteger1–10000.
beforestringPagination cursor.
afterstringPagination cursor.
time_rangesstring[]Filter by time. Format: {"type":"date_range","since":"2026-04-25","until":"2026-05-01"}.
filtersstring[]One or more filter expressions.
fieldsstring[]Which columns to return per row.
sortstring[]Sort expressions, e.g. {"field":"clicks","direction":"desc"}.

Available row fields (non-exhaustive)

FieldNotes
idRow identifier (encodes scope + time bucket).
start_time, end_timeBucket bounds (Unix seconds).
readable_timeHuman-readable bucket label, e.g. 2026-04-02.
timezoneBucket timezone (matches Ad Account timezone).
impressionsDelivered impressions.
clicksClicks.
spendSpend in account currency (decimal in responses, e.g. 42.75).
ctrClick-through rate.
cpcCost per click.
cpmCost per thousand impressions.
ad_id, ad_nameAd scope.
ad_group_id, ad_group_nameAd group scope.
campaign_id, campaign_nameCampaign scope.

Pass the fields you actually need in fields[]. Don’t pull every field by default — large queries with all fields can hit pagination quickly.

Example: best-performing ad in a campaign over a week

Find the top ad first.

curl -sS -G "https://api.ads.openai.com/v1/campaigns/cmpn_101/insights" 
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" 
  --data-urlencode 'time_granularity=none' 
  --data-urlencode 'aggregation_level=ad' 
  --data-urlencode 'limit=1' 
  --data-urlencode 'fields[]=ad_id' 
  --data-urlencode 'fields[]=ad_name' 
  --data-urlencode 'fields[]=clicks' 
  --data-urlencode 'fields[]=impressions' 
  --data-urlencode 'time_ranges[]={"type":"date_range","since":"2026-04-25","until":"2026-05-01"}' 
  --data-urlencode 'sort[]={"field":"clicks","direction":"desc"}'

Then pull a daily breakdown for that ad.

curl -sS -G "https://api.ads.openai.com/v1/ads/$AD_ID/insights" 
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" 
  --data-urlencode 'time_granularity=daily' 
  --data-urlencode 'fields[]=readable_time' 
  --data-urlencode 'fields[]=clicks' 
  --data-urlencode 'fields[]=impressions' 
  --data-urlencode 'fields[]=ctr' 
  --data-urlencode 'time_ranges[]={"type":"date_range","since":"2026-04-25","until":"2026-05-01"}'

Example: last 7 days of campaign performance

curl -sS -G "https://api.ads.openai.com/v1/campaigns/cmpn_101/insights" 
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" 
  --data-urlencode 'time_granularity=daily' 
  --data-urlencode 'fields[]=readable_time' 
  --data-urlencode 'fields[]=clicks' 
  --data-urlencode 'fields[]=impressions' 
  --data-urlencode 'fields[]=spend' 
  --data-urlencode 'time_ranges[]={"type":"date_range","since":"2026-04-25","until":"2026-05-01"}'

Sample response

{
  "object": "list",
  "count": 1,
  "data": [
    {
      "id": "start=1775088000:end=1775174400:entity_id=ad_501",
      "readable_time": "2026-04-02",
      "timezone": "UTC",
      "impressions": 15548,
      "clicks": 312,
      "spend": 42.75,
      "start_time": 1775088000,
      "end_time": 1775174400
    }
  ],
  "first_id": "start=1775088000:end=1775174400:entity_id=ad_501",
  "last_id": "start=1775088000:end=1775174400:entity_id=ad_501",
  "has_more": false
}

Closing the attribution loop

For accurate revenue reporting on a Shopify store, three things must be true at once:

  1. The Insights API is delivering delivery and cost metrics (this chapter).
  2. The pixel is firing on every relevant page (Chapter 8): page_viewed, contents_viewed, items_added, checkout_started, order_created.
  3. The Conversions API is dual-shipping the same conversion events from the Shopify backend with shared event_id values (Chapter 12), and oppref is captured at landing and forwarded.

Without all three, attribution drifts — and a percentage-of-revenue commercial model becomes undefendable.

The Insights endpoint tells you what you spent. The pixel + CAPI tell you what came back. Together they let you compute an honest CPA and ROAS. Either one alone gives you a partial picture that breaks under audit.

Reading the data into a warehouse

Every Insights response is paginated (first_id, last_id, has_more). For warehouse pulls — Looker Studio, BigQuery, Snowflake, etc. — paginate until has_more is false, store rows keyed by id, and run incrementally on start_time to avoid re-pulling history. This is the same pattern the Advertiser API supports for every list endpoint, so the warehouse pipeline shape is uniform across resources.