# Analytics

Read the daily impressions, clicks, spend and conversions Zernio syncs from Microsoft Ads for an ad, with CTR, CPC and CPM.

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

Zernio syncs impressions, clicks, spend, conversions and revenue per ad and day from Microsoft's ad performance report, and derives CTR, CPC and CPM from them.

## Read ad analytics

Call `GET /v1/ads/{adId}/analytics` with the ad's `id` ([Get ad analytics](/ad-insights/get-ad-analytics)).

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
const { data: insights } = await zernio.adinsights.getAdAnalytics({
  path: { adId: '6ae0968fa23091cc35b72121' },
  query: { fromDate: '2027-01-04', toDate: '2027-01-11' }
});

console.log(insights.analytics.summary.spend);
```
</Tab>
<Tab value="Python">
```python
insights = client.ad_insights.get_ad_analytics(
    ad_id="6ae0968fa23091cc35b72121",
    from_date="2027-01-04",
    to_date="2027-01-11",
)

print(insights["analytics"]["summary"]["spend"])
```
</Tab>
<Tab value="curl">
```bash
curl "https://zernio.com/api/v1/ads/6ae0968fa23091cc35b72121/analytics?fromDate=2027-01-04&toDate=2027-01-11" \
  -H "Authorization: Bearer $ZERNIO_API_KEY"
```
</Tab>
</Tabs>

Response (`200`), trimmed:

```json
{
  "ad": { "id": "6ae0968fa23091cc35b72121", "name": "Planner launch", "platform": "microsoft", "status": "active", "currency": "USD" },
  "analytics": {
    "summary": { "spend": 31.8, "impressions": 4260, "clicks": 187, "ctr": 4.39, "cpc": 0.17, "cpm": 7.46 },
    "daily": [ { "date": "2027-01-04", "spend": 4.5, "impressions": 610, "clicks": 26 } ]
  }
}
```

`GET /v1/ads/tree` rolls the same metrics up per campaign and ad group ([Get campaign tree](/ad-campaigns/get-ad-tree)).

## How it behaves

- Metrics come from Microsoft's report, which Zernio requests and reads back for each sync, so a new day appears after the next sync rather than in real time.
- Microsoft closes its reporting day on Pacific time, so the current Pacific day is the last one a sync can read.
- An ad that never served, such as a paused one, returns an empty `daily` list.

## If it fails

| Error | Cause | Fix |
|-------|-------|-----|
| `404` | The `adId` is not a Zernio ad id | Use the `id` from `GET /v1/ads`, not the Microsoft ad id. |
| Empty `daily` | The ad had no impressions in the range | Widen the date range, or check the ad is running. |

## Related

- [Get ad analytics](/ad-insights/get-ad-analytics): metrics, date ranges and rollups.
- [Get campaign tree](/ad-campaigns/get-ad-tree): metrics per campaign and ad group.
- [Manage ads](/platforms/microsoft-ads/manage-ads): pause, resume and rebudget.