Flexible live insights query
Changed onRuns a custom performance query against Meta, Google Ads or TikTok and returns the platform's rows as is, for reports the fixed endpoints don't cover.
The account's platform picks the contract:
Meta (facebook/instagram): forwards caller-chosen fields, breakdowns and filtering to any Meta insights node and returns Meta's rows verbatim. objectId (required) selects the node; level sets row granularity. Semantic validation is Meta's: an unknown field or invalid breakdown combination returns a 400 carrying Meta's message. For long ranges or agency-scale accounts prefer the async variant (POST /v1/ads/insights/reports).
Google Ads (googleads): raw GAQL passthrough. Send any read-only GAQL SELECT via query (campaign/keyword/search-term/geo/demographic/asset/shopping resources, change_event, any segments.*) and rows come back verbatim (camelCase, counters as strings). Results are paged at a fixed 10,000 rows; follow paging.nextPageToken with pageToken. adAccountId (alias customerId) is only needed when the connection has several Google Ads accounts. Semantic validation is Google's: an invalid query returns a 400 carrying Google's message (note: selecting segments.date requires a finite date filter).
Queries run against Google Ads API v25, so write GAQL against the v25 field reference. One exception is translated for backward compatibility: the legacy campaign.start_date / campaign.end_date (removed by Google in v23) are rewritten to campaign.start_date_time / campaign.end_date_time, and rows still carry campaign.startDate / campaign.endDate as YYYY-MM-DD. In WHERE, =, <, <=, >, >=, BETWEEN and IS [NOT] NULL against a 'YYYY-MM-DD' literal are translated; any other form returns Google's 400. New code should select the _date_time fields directly.
TikTok (tiktok/tiktokads): passthrough of TikTok's synchronous report (/report/integrated/get/). Send adAccountId, dataLevel, dimensions, metrics, fromDate/toDate (TikTok caps the span at 365 days) and optionally filtering in the same [{"field", "operator", "value"}] shape as Meta (operator is TikTok's filter_type, e.g. IN; array values are JSON-encoded for TikTok). Rows come back verbatim as { dimensions, metrics } with page-number paging.
De-duplicated reach across a set of campaigns, ad groups or ads: filter the set and group by country_code instead of the entity id. TikTok then counts each person once across the whole set and range, per country. Example, two campaigns for a month: dataLevel=AUCTION_CAMPAIGN&dimensions=country_code&metrics=reach,impressions,frequency&fromDate=2026-09-01&toDate=2026-09-30&filtering=[{"field":"campaign_ids","operator":"IN","value":["1876574798182050","1876575504573650"]}]. For a set of ads use dataLevel=AUCTION_AD with ad_ids. A filter on a finer entity than dataLevel (e.g. ad_ids at AUCTION_CAMPAIGN) returns 400: TikTok would otherwise widen it to every parent entity containing those ids. When the set delivers in several countries, reach is per country; summing the rows counts a person reached in two countries twice. AUCTION_ADVERTISER rejects entity filters.
Request
- Base URL: https://zernio.com/api
- URL: https://zernio.com/api/v1/ads/insights
- Auth: HTTP bearer
Query parameters
Zernio SocialAccount id (posting or ads variant); its platform selects the Meta, Google or TikTok contract.
Meta only (required there): insights node (act_<n>, campaign id, ad set id or ad id).
Google only (required there): the GAQL SELECT statement to run.
Google: platform ad account ID (Google customer ID, digits only) when the connection has several Google Ads accounts. TikTok (required there): the advertiser id.
TikTok only: report_type.
TikTok only (required there): data_level.
TikTok only (required there): 1-4 comma-separated TikTok dimensions (e.g. country_code, campaign_id, stat_time_day).
TikTok only (required there): comma-separated TikTok metrics (e.g. reach,impressions,frequency,spend).
TikTok only: page number.
TikTok only: rows per page.
Alias of adAccountId, kept for existing callers
Google only: cursor from paging.nextPageToken of the previous page.
Row granularity
Comma-separated Graph insights fields (e.g. spend,impressions,frequency,website_purchase_roas). Omitted = Meta's default set.
Meta only: comma-separated Graph breakdowns (e.g. age,gender or publisher_platform). Returns 400 on TikTok (add the breakdown to dimensions with reportType=AUDIENCE, e.g. dimensions=campaign_id,placement) and on Google (select segments.* in the query).
Comma-separated Graph action breakdowns; segments the actions[] arrays in each row. Pass none to clear Meta's default action_type breakdown, required to combine some non-action breakdowns such as instagram_ads_follow_type (otherwise Meta returns a (#100) invalid-combination error).
Comma-separated Meta attribution windows. Action values are returned keyed per window.
When actions are counted: impression, conversion or mixed.
Use the ad sets' own attribution settings for action counting.
JSON array of filter objects: [{"field", "operator", "value"}]. Applied server-side by Meta or TikTok (TikTok fields e.g. campaign_ids, adgroup_ids, ad_ids).
Meta date_preset (e.g. last_7d, last_30d, this_month). Mutually exclusive with fromDate/toDate.
Start of range (YYYY-MM-DD); requires toDate. Required on TikTok.
End of range (YYYY-MM-DD); requires fromDate.
Days per row (1-90), monthly, or all_days.
Rows per page
Cursor from paging.after of the previous page.
Response
Insight rows (raw platform shape)
Changes
- warning
added the new
accountenum value to the/response property for the response status - warning
added the new
accountenum value to the/response property for the response status - warning
added the new
accountenum value to the/response property for the response status - info
added the media type
application/jsonfor the response with the status
- warning
- info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status
- info