---
title: query_insights
description: Aggregate spend / impressions / clicks / conversions over a date range, by entity.
---

Ask what an ad account spent and what it returned, for the full ad account or for each campaign, ad set or ad. The agent adds up the metrics that AdCrunch stores for the dates that you name.

> How much did each Meta campaign spend last week, and what was the ROAS?

The agent reads the metrics of that week, with one row for each campaign. You see the spend and the return on ad spend of each campaign. [Read your accounts](/mcp/tools/read-your-accounts) shows the full job.

## Reference

**Available on:** [![Meta](/providers/meta.svg)](https://docs.adcrunch.dev/connect/providers) [![TikTok](/providers/tiktok.svg)](https://docs.adcrunch.dev/connect/providers) [![Google Ads](/providers/gads.svg)](https://docs.adcrunch.dev/connect/providers)

Query advertising insights/metrics for an advertiser. Supports breakdown by provider, advertiser, or any native entity type (campaign, adset, ad_group, line_item, ad, …), time intervals (day/week/month), date ranges (since/until or a relative window like last_7_days), and metric selection (spend, impressions, clicks, ctr, cpm, roas, etc.). Defaults to spend + impressions over the last 15 days when no date range is provided. The rows come in order of the period, then the entity. The answer holds at most `limit` rows (default 100, maximum 500). When it carries `nextCursor`, more rows exist: call this tool again with the same arguments and `cursor` set to that value. When it carries no `nextCursor`, you have every row.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `advertiserId` | string | yes | Advertiser account ID (format: `acc_<id>`). Must belong to the active organization. Use list_advertisers to discover IDs. |
| `breakdown` | one of `provider`, `advertiser`, `campaign`, `adset`, `adgroup`, `ad_group`, `ad_group_ad`, `insertion_order`, `line_item`, `asset_group`, `keyword`, `audience`, `listing_group`, `ad`, `creative` | no | Group results by entity level. Allowed values are native provider entity types (campaign, adset, ad_group, line_item, ad, …) plus provider and advertiser. Omit to return a single fully aggregated row. |
| `currency` | string, 3 characters | no | Display currency (ISO 4217, e.g. `USD`). Converts monetary metrics (spend, conversion values, cpc, cpm, cpa) from each row’s account currency using the ECB reference rate of the row’s own date, before aggregation. Omit for unconverted account-currency values — rows are then annotated with their `currency`. Pass it whenever the organization has advertisers in more than one currency, otherwise totals silently mix currencies. |
| `entityId` | string | no | Filter to a single entity by its bare provider-native id, or combine with an entity-type `breakdown` to scope the breakdown to that entity's subtree. |
| `entityType` | string | no | Filter rows to a single provider-native entity type (campaign, adset, ad_group, line_item, ad, …). IGNORED when `breakdown` is itself an entity type — in that case the breakdown defines the row grain. Applies only when there is no entity-type breakdown. |
| `interval` | one of `day`, `week`, `month` | no | Time bucket for time-series results: day, week, or month. Omit for an all-time aggregate over the date range. |
| `cursor` | string, at least 1 character | no | The `nextCursor` of the previous page. Omit it to get the first page. Send it with no change, and with the same filters as the request that answered it: a cursor from a different query gets a 400 `invalid_cursor`. Do not build or change a cursor. |
| `limit` | integer, 1 to 500 | no | The greatest number of rows on the page, from 1 to 500. The default is 100. A greater value gets a 400, with `error` of `invalid_request`. Default: `100`. |
| `provider` | one of `meta`, `gads`, `tiktok`, `snapchat`, `dv360` | no | Filter results to a single ad provider (meta, gads, tiktok, snapchat, dv360). |
| `relative` | one of `last_15_days`, `last_month`, `last_7_days` | no | Relative date window. Allowed values: last_7_days, last_15_days, last_month. Takes precedence over `since`/`until`. Defaults to last_15_days when no date range is provided. |
| `select` | array of (one of `spend`, `clicks`, `impressions`, `ctr`, `cpc`, `cpm`, `cpp`, `cpa`, `roas`, `reach`, `frequency`, `conversions`, `conversion_value`, `action_add_to_cart`, `action_add_to_cart_value`, `action_purchase`, `action_purchase_value`, `action_initiate_checkout`, `action_initiate_checkout_value`) | no | Metrics to compute. Defaults to ["spend", "impressions"]. Allowed values: spend, clicks, impressions, ctr, cpc, cpm, cpp, cpa, roas, reach, frequency, conversions, conversion_value, action_add_to_cart, action_add_to_cart_value, action_purchase, action_purchase_value, action_initiate_checkout, action_initiate_checkout_value. Coverage differs by provider: the action_* funnel is Meta-only, and Google Ads reports no reach — so reach, cpp and frequency read 0 there. Do not compare those across providers. |
| `since` | string | no | Inclusive start date in YYYY-MM-DD format. Used together with `until` for a fixed range. Ignored when `relative` is set. |
| `until` | string | no | Inclusive end date in YYYY-MM-DD format. Used together with `since`. Ignored when `relative` is set. |

### Output

A successful call returns this object in `structuredContent`.

| Field | Type | Always present | Description |
| --- | --- | --- | --- |
| `insights` | array of object | yes | One row for each group, in the order of the period, then of the entity. An empty array means that no data matches, or that the organization does not own the advertiser. |
| `insights[].advertiserId` | string | no | The advertiser of the row, prefixed `acc_`. Present when `breakdown` is `advertiser` or an entity type. |
| `insights[].currency` | string or null | yes | The ISO 4217 currency of the money in the row. With the `currency` argument, it is that currency on each row. With no `currency` argument, it is the currency of the ad account, and null when the rows of the group have two or more currencies. |
| `insights[].date` | string | no | The first day of the period, `YYYY-MM-DD`. Present only with `interval`. A week starts on its Monday, and a month on its first day. |
| `insights[].entityId` | string | no | The entity of the row, as the id that its provider gives it. Present when `breakdown` is an entity type. |
| `insights[].provider` | one of `meta`, `tiktok`, `snapchat`, `gads`, `dv360`, `x`, `openai` | no | The provider of the row: `meta`, `tiktok` or `gads`. Present when you send `breakdown`. |
| `insights[].type` | string | no | The provider type of `entityId`, such as `campaign`, `adset`, `adgroup` or `ad_group`. Present when `breakdown` is an entity type. |
| `insights[].action_add_to_cart` | number | no | Add-to-cart actions. Meta only: the other providers answer 0. |
| `insights[].action_add_to_cart_value` | number | no | The value of those add-to-cart actions, as money. Meta only. |
| `insights[].action_initiate_checkout` | number | no | Checkouts that started. Meta only: the other providers answer 0. |
| `insights[].action_initiate_checkout_value` | number | no | The value of those checkouts, as money. Meta only. |
| `insights[].action_purchase` | number | no | Purchases. Meta only: the other providers answer 0. |
| `insights[].action_purchase_value` | number | no | The value of those purchases, as money. Meta only. |
| `insights[].clicks` | number | no | Clicks. |
| `insights[].conversion_value` | number | no | The value of the conversions, as money. |
| `insights[].conversions` | number | no | Conversions, as the provider counts them. |
| `insights[].cpa` | number | no | Cost per conversion: spend ÷ conversions. |
| `insights[].cpc` | number | no | Cost per click: spend ÷ clicks. |
| `insights[].cpm` | number | no | Cost per thousand impressions: spend ÷ impressions × 1000. |
| `insights[].cpp` | number | no | Cost per thousand people reached: spend ÷ reach × 1000. Google Ads reports no reach, so it answers 0. |
| `insights[].ctr` | number | no | Click-through rate, **as a percentage**: clicks ÷ impressions × 100. A `ctr` of 1.5 is 1.5%. |
| `insights[].frequency` | number | no | Impressions ÷ reach. Google Ads reports no reach, so it answers 0. |
| `insights[].impressions` | number | no | Impressions. |
| `insights[].reach` | number | no | People reached. Google Ads does not report it, so it answers 0. |
| `insights[].roas` | number | no | Return on ad spend: conversion value ÷ spend. |
| `insights[].spend` | number | no | The money spent, in whole units of `currency`. |
| `nextCursor` | string | no | Send this value as `cursor` to get the next page. It is absent on the last page. |

### Failure codes

A failed call has `isError` set, and `structuredContent.error` holds one of these codes. [Errors](/mcp/errors) describes the shape of a failed call.

- `invalid_cursor`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `observe:read`. [Auth & scopes](/mcp/auth) lists each scope.

### Annotations

A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.

- **Read-only.** The tool changes nothing.
- **Closed world.** The tool reads and writes the data of AdCrunch only.

### Example

The arguments:

```json
{
  "advertiserId": "acc_1203456789012345",
  "breakdown": "campaign",
  "relative": "last_7_days",
  "select": [
    "spend",
    "impressions",
    "clicks",
    "roas"
  ]
}
```

The result, in `structuredContent`:

```json
{
  "insights": [
    {
      "advertiserId": "acc_1203456789012345",
      "clicks": 3180,
      "currency": "EUR",
      "entityId": "120210000000000001",
      "impressions": 212400,
      "provider": "meta",
      "roas": 3.42,
      "spend": 1284.5,
      "type": "campaign"
    },
    {
      "advertiserId": "acc_1203456789012345",
      "clicks": 1045,
      "currency": "EUR",
      "entityId": "120210000000000002",
      "impressions": 58900,
      "provider": "meta",
      "roas": 5.18,
      "spend": 612.75,
      "type": "campaign"
    }
  ]
}
```
