Zernio
APIFor you
Zernio
APIFor you
API Reference

Insights

List lead conversationsGETGoogle Local Services Ads leadsGETSubmit async insights reportPOSTGet ad analyticsGETPoll an async insights report runGETGoogle Ads search terms reportGETGet campaign analyticsGETPer-creative performance inside TikTok Smart+ adsGETGet historical keyword metricsPOSTGenerate keyword ideasPOSTFlexible live insights queryGET
Dashboard
OverviewPlatformsAPI ReferenceResources
Insights

Get campaign analytics

Returns a campaign's performance summary and daily timeline, with optional breakdowns by age, gender and other audience dimensions.

Returns performance analytics for a whole campaign in one call: summary metrics, a daily timeline over the requested date range (summed across the campaign's ads), and optional demographic breakdowns. Breakdowns are fetched live from Meta, TikTok or LinkedIn at the campaign level (one call per dimension, no per-ad fan-out), so an agency dashboard gets campaign-level age/gender/placement/etc. without summing thousands of per-ad reads. campaignId is the platform campaign id; pass platform when a campaign id could be ambiguous across platforms. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max.

History: when an ad account connects, Zernio imports its last 90 days of metrics. summary and daily come from those synced metrics, so they hold no data for days before that. Breakdowns and Google's impression share are read live from the platform over the requested range, so they are not limited by the import. When the campaign belongs to a Meta ad account, a range reaching further back answers 202 with backfillPending: true and the covered part while the older days (up to 730 days back) are imported in the background; repeat the request until it returns 200. Other platforms never return 202.

Google adds searchImpressionShare, searchBudgetLostImpressionShare, searchRankLostImpressionShare, searchTopImpressionShare and searchAbsoluteTopImpressionShare under analytics.summary for the requested inclusive range. These ratios are queried together without daily segmentation and cached for 10 minutes. Unavailable values are null. analytics.impressionShareCache reports cachedAt and stale independently of synced metrics.


PlatformsMetaGoogleTikTokLinkedInPinterestX
GET
/v1/ads/campaigns/{campaignId}/analytics

Authorization

bearerAuth
AuthorizationBearer <token>

API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.

In: header

Path Parameters

campaignId*string

Platform campaign id (platformCampaignId).

Query Parameters

platform?string

Disambiguate when the campaign id exists across platforms (e.g. facebook, instagram).

fromDate?string

Start of date range (YYYY-MM-DD). Defaults to 90 days ago.

Formatdate
toDate?string

End of date range (YYYY-MM-DD). Defaults to today. Max 730-day range.

Formatdate
breakdowns?string

Comma-separated breakdown dimensions.

Meta: age, gender, country, publisher_platform, device_platform, region, platform_position, impression_device, video_asset, image_asset, body_asset, title_asset.

TikTok: gender, age, country (or country_code), publisher_platform (or platform), ac, language, placement. TikTok serves at most 365 days per breakdown, so a longer range is read over its last 365 days and analytics.breakdownsRange says which window.

LinkedIn (firmographics): job_title, job_function, seniority, industry, company, company_size, country, region. Rows carry the raw pivot value plus a resolved name. LinkedIn serves these aggregated over the whole range, delays the data 12-24h, and omits segments with fewer than 3 events.

A known dimension the platform cannot break down by is listed in analytics.unsupportedBreakdowns instead of being dropped (with guidance in analytics.breakdownHints where there is an alternative); the rest of the response is unchanged. An unknown name returns 400. A TikTok dimension that fails is listed in analytics.breakdownErrors and the response stays 200. Metrics TikTok refuses for a dimension are listed in analytics.breakdownDroppedMetrics, and the row values derived from them are null.

Response Body

application/json

application/json

application/json

application/json

application/json

import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.adinsights.getCampaignAnalytics({  path: {    campaignId: 'campaign_abc123',  },});console.log(data);
{  "campaign": {    "id": "123456789",    "platform": "google"  },  "analytics": {    "summary": {      "searchImpressionShare": 0.42,      "searchBudgetLostImpressionShare": 0.13,      "searchRankLostImpressionShare": 0.45,      "searchTopImpressionShare": 0.31,      "searchAbsoluteTopImpressionShare": null    },    "impressionShareCache": {      "cachedAt": "2026-09-09T10:00:00Z",      "stale": false    },    "daily": []  }}
Was this page helpful?

Google Ads search terms report

Shows the actual Google searches that triggered your ads, with spend and results, so you can spot wasted spend and add negative keywords. The actual search queries that triggered your ads, with matched-keyword status and spend metrics, the raw material for wasted-spend analysis and negative-keyword lists. Reads Google's `search_term_view`, cached for the quota window; defaults to the last 30 days. Rows are ordered by cost, descending. Draws on the shared Google Ads operations budget. The response carries `cachedAt` and `stale`, set when a quota-exhausted call falls back to the last-good copy instead of a live read.

Per-creative performance inside TikTok Smart+ ads

Breaks a Smart+ ad (or ad group) down by creative material, one row per Spark post, video or image, from TikTok's Smart+ material report. For a Spark post `tiktokItemId` is the TikTok post id. Conversion metrics are TikTok web (pixel) events. `purchases`, `purchaseValue` and `roas` come from Complete Payment, or from Place an Order (legacy ON_WEB_ORDER pixels) when that reports more; the two are never summed. TikTok allows two dimensions per report, so rows are keyed by the Smart+ ad (`level=ad`) or by the ad group (`level=adGroup`), not both. A row is identified by `smartPlusAdId` + `materialId` at `level=ad` and by `adGroupId` + `materialId` at `level=adGroup`; each appears once across all pages. Rows are sorted by `spend` descending, then the Smart+ ad or ad group id, then `materialId`, and the full result is cached for 10 minutes per account, advertiser and query, so pages read within that window are consistent and `totalRows` counts distinct rows. The result can hold more rows than TikTok's unfiltered report declares, because the per-ad reads also return listed Smart+ ads that report leaves out. When the slices come back with fewer rows than TikTok declares on two reads, the call answers 502 instead of a short result. Metrics TikTok returns empty come back as null.