Insights & GAQL
Rolled-up metrics and raw GAQL queries
Insights
| You want | Use | Notes |
|---|---|---|
| A dashboard: spend, CPC, CPM per campaign / ad group / ad | GET /v1/ads/tree, GET /v1/ads, GET /v1/ads/{adId} | Served from Zernio's synced metrics, no Google call on the request path. |
| One dimension split out | GET /v1/ads/{adId}/analytics, GET /v1/ads/campaigns/{campaignId}/analytics | The cross-platform breakdowns endpoint. |
| Anything Google's reporting can answer | GET /v1/ads/insights | Raw GAQL passthrough. |
Discovered campaigns of every type sync into the tree with metrics, including Performance Max, Shopping and Video, even though /v1/ads/create only builds Search and Display.
Raw GAQL queries
GET /v1/ads/insights with a googleads account runs any read-only GAQL SELECT and returns Google's rows verbatim:
const { data } = await zernio.adinsights.queryAdInsights({
query: {
accountId: 'GOOGLEADS_ACCOUNT_ID',
query: `SELECT campaign.name, metrics.clicks, metrics.cost_micros, segments.date
FROM campaign
WHERE segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC`,
},
});
// data.rows: camelCase objects, verbatim; data.paging.nextPageToken -> pass back as pageTokendata = client.ad_insights.query_ad_insights(
account_id="GOOGLEADS_ACCOUNT_ID",
query="""SELECT campaign.name, metrics.clicks, metrics.cost_micros, segments.date
FROM campaign
WHERE segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC""",
)curl -G "https://zernio.com/api/v1/ads/insights" \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-urlencode "accountId=GOOGLEADS_ACCOUNT_ID" \
--data-urlencode "query=SELECT campaign.name, metrics.clicks, metrics.cost_micros, segments.date FROM campaign WHERE segments.date DURING LAST_30_DAYS ORDER BY metrics.cost_micros DESC"This is the same endpoint that serves Meta's flexible insights: the account's platform picks the contract. For Meta you pass objectId + fields; for Google you pass query.
What you can query: campaign / keyword / search-term / geo / demographic / asset / shopping resources, change_event, any segments.*. That covers the reports the synced metrics don't model, search terms, quality score, auction insights adjacents, per-segment splits.
| Rule | Detail |
|---|---|
| Read-only | SELECT statements only. |
| Paging | Fixed at 10,000 rows per page; follow paging.nextPageToken with pageToken. |
customerId | Only needed when the connection has several Google Ads accounts. |
| Validation | Google's, verbatim: an invalid query returns a 400 carrying Google's message. |
| Numbers | Counters are int64s encoded as strings; monetary fields are micros of the account currency. |
Selecting segments.date requires a finite date filter (DURING LAST_30_DAYS, an explicit BETWEEN, ...). Google rejects an unbounded date-segmented query, and its message says exactly that; it surfaces verbatim.
GAQL queries run live against Google and count toward the per-user ops budget, see quotas.