Facebook Time-Based Breakdowns
The breakdowns endpoints provide monthly aggregated performance data for campaigns, ad sets, and ads, enabling time-series analysis and trend identification.
Endpoints Overview
| Endpoint | Method | Purpose |
|---|---|---|
/v1/e/facebook/breakdowns/:account_id/campaigns | GET | Get campaign monthly breakdown |
/v1/e/facebook/breakdowns/:account_id/adsets | GET | Get ad set monthly breakdown |
/v1/e/facebook/breakdowns/:account_id/ads | GET | Get ad monthly breakdown |
Campaign Breakdown
Get Campaign Monthly Performance
Retrieves monthly aggregated metrics for all campaigns in an ad account.
Endpoint: GET /v1/e/facebook/breakdowns/:account_id/campaigns
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | String | Yes | Facebook Ad Account ID (e.g., act_123456789) |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
since | String | Yes | Start date (YYYY-MM-DD) |
until | String | Yes | End date (YYYY-MM-DD) |
status | String | No | Filter by status (e.g., ACTIVE,PAUSED) |
search | String | No | Search campaign name (partial match) |
sort | String | No | Sort field (e.g., spend) |
order | String | No | Sort order: ascending or descending |
account_id | String | No | DashClicks sub-account ID |
Example Request:
GET /v1/e/facebook/breakdowns/act_123456789/campaigns?since=2024-01-01&until=2024-12-31&status=ACTIVE
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": {
"23851234567890123": {
"campaign_name": "Summer Sale Campaign",
"January": {
"impressions": 15000,
"cpm": 12.5,
"clicks": 450,
"cpc": 0.42,
"cpa": 15,
"spend": 187.5
},
"February": {
"impressions": 18000,
"cpm": 11.8,
"clicks": 540,
"cpc": 0.39,
"cpa": 22,
"spend": 210.6
},
"March": {
"impressions": 22000,
"cpm": 10.9,
"clicks": 680,
"cpc": 0.35,
"spend": 239.8,
"cpa": 28
},
"April": {
"impressions": 0,
"cpm": 0,
"clicks": 0,
"cpc": 0,
"cpa": 0,
"spend": 0
},
"May": {
"impressions": 0,
"cpm": 0,
"clicks": 0,
"cpc": 0,
"cpa": 0,
"spend": 0
}
},
"23851234567890456": {
"campaign_name": "Spring Collection",
"January": {
"impressions": 8500,
"cpm": 15.2,
"clicks": 220,
"cpc": 0.58,
"cpa": 8,
"spend": 129.2
}
}
}
}
Data Structure:
const breakdownStructure = {
[campaign_id]: {
campaign_name: 'Campaign name',
January: { impressions, cpm, clicks, cpc, cpa, spend },
February: { impressions, cpm, clicks, cpc, cpa, spend },
March: { impressions, cpm, clicks, cpc, cpa, spend },
April: { impressions, cpm, clicks, cpc, cpa, spend },
May: { impressions, cpm, clicks, cpc, cpa, spend },
June: { impressions, cpm, clicks, cpc, cpa, spend },
July: { impressions, cpm, clicks, cpc, cpa, spend },
August: { impressions, cpm, clicks, cpc, cpa, spend },
September: { impressions, cpm, clicks, cpc, cpa, spend },
October: { impressions, cpm, clicks, cpc, cpa, spend },
November: { impressions, cpm, clicks, cpc, cpa, spend },
December: { impressions, cpm, clicks, cpc, cpa, spend },
},
};
Month Metrics Explained:
const monthMetrics = {
impressions: 'Total impressions for the month',
cpm: 'Cost per 1000 impressions',
clicks: 'Total clicks for the month',
cpc: 'Cost per click',
cpa: 'Number of purchase actions',
spend: 'Total spend for the month',
};
Implementation Details:
exports.getCampaignBreakDown = async (req, res, next) => {
try {
let fbAccountId = req.params.account_id;
let filterParams = req.query;
filterParams.level = 'campaign';
filterParams.time_increment = 'monthly';
let accountId = await checkAccountAccess(req);
const existKeys = await facebookModel.find({
accountID: accountId,
source: 'meta-ads',
});
let accessToken = await facebookModel.checkAccessTokenValidity({
req: req,
expirationTime: existKeys.token.expires_in,
accessToken: existKeys.token.access_token,
docId: existKeys.docId,
source: 'meta-ads',
});
// Transform date parameters
if (filterParams.since && filterParams.until) {
filterParams.time_range = {
since: moment(filterParams.since).startOf('day').format('YYYY-MM-DD'),
until: moment(filterParams.until).startOf('day').format('YYYY-MM-DD'),
};
delete filterParams.since;
delete filterParams.until;
}
// Build filtering
filterParams.filtering = [];
if (filterParams.search) {
filterParams.filtering.push({
field: 'campaign.name',
operator: 'CONTAIN',
value: filterParams.search,
});
delete filterParams.search;
}
if (filterParams.status) {
filterParams.filtering.push({
field: 'campaign.effective_status',
operator: 'IN',
value: filterParams.status.split(','),
});
delete filterParams.status;
}
// Fetch insights with monthly breakdown
let accountInsights = await fbProvider.getBreakDown(fbAccountId, accessToken, filterParams);
// Initialize month structure
const monthsArray = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
let months = {};
// Create structure for each campaign
if (accountInsights) {
for (let dataInsight of accountInsights) {
months[dataInsight.campaign_id] = {};
months[dataInsight.campaign_id]['campaign_name'] = dataInsight.campaign_name;
// Initialize all months to 0
for (let i = 0; i < 12; i++) {
months[dataInsight.campaign_id][monthsArray[i]] = {
impressions: 0,
cpm: 0,
clicks: 0,
cpc: 0,
cpa: 0,
spend: 0,
};
}
}
}
// Aggregate data by month
if (accountInsights) {
for (let dataInsight of accountInsights) {
let month = new Date(dataInsight.date_start).getMonth();
let monthName = monthsArray[month];
let campaign = months[dataInsight.campaign_id];
campaign[monthName]['impressions'] += parseInt(dataInsight.impressions || 0);
campaign[monthName]['cpm'] += parseInt(dataInsight.cpm || 0);
campaign[monthName]['clicks'] += parseInt(dataInsight.clicks || 0);
campaign[monthName]['cpc'] += parseInt(dataInsight.cpc || 0);
campaign[monthName]['spend'] += parseFloat(dataInsight.spend || 0);
// Extract purchase actions for CPA
if (dataInsight.actions) {
const resultPurchase = dataInsight.actions.find(
({ action_type }) => action_type === 'purchase',
);
if (resultPurchase && resultPurchase.value) {
campaign[monthName]['cpa'] += parseInt(resultPurchase.value);
}
}
}
}
return res.status(200).json({
success: true,
message: 'SUCCESS',
data: months,
});
} catch (error) {
next(error);
}
};
Filtering Logic:
// Status filtering
{
field: 'campaign.effective_status',
operator: 'IN',
value: ['ACTIVE', 'PAUSED']
}
// Name search (partial match)
{
field: 'campaign.name',
operator: 'CONTAIN',
value: 'Summer'
}
Ad Set Breakdown
Get Ad Set Monthly Performance
Retrieves monthly aggregated metrics for ad sets.
Endpoint: GET /v1/e/facebook/breakdowns/:account_id/adsets
Query Parameters: Same as campaigns plus:
| Parameter | Type | Required | Description |
|---|---|---|---|
campaignids | String | No | Filter by campaign IDs (comma-separated) |
Example Request:
GET /v1/e/facebook/breakdowns/act_123456789/adsets?since=2024-01-01&until=2024-12-31&campaignids=123,456
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": {
"23851234567890456": {
"adset_name": "Desktop Users - US",
"January": {
"impressions": 8000,
"cpm": 12.5,
"clicks": 240,
"cpc": 0.42,
"cpa": 8,
"spend": 100.0
},
"February": {
"impressions": 9500,
"cpm": 11.8,
"clicks": 285,
"cpc": 0.39,
"cpa": 11,
"spend": 112.1
}
}
}
}
Implementation Differences:
// Set level to adset
filterParams.level = 'adset';
// Campaign filtering
if (filterParams.campaignids) {
filterParams.filtering.push({
field: 'campaign.id',
operator: 'IN',
value: filterParams.campaignids.split(','),
});
delete filterParams.campaignids;
}
// Name search
if (filterParams.search) {
filterParams.filtering.push({
field: 'adset.name',
operator: 'CONTAIN',
value: filterParams.search,
});
delete filterParams.search;
}
// Status filtering
if (filterParams.status) {
filterParams.filtering.push({
field: 'adset.effective_status',
operator: 'IN',
value: filterParams.status.split(','),
});
delete filterParams.status;
}
Ad Breakdown
Get Ad Monthly Performance
Retrieves monthly aggregated metrics for individual ads.
Endpoint: GET /v1/e/facebook/breakdowns/:account_id/ads
Query Parameters: Same as ad sets plus:
| Parameter | Type | Required | Description |
|---|---|---|---|
adsetids | String | No | Filter by ad set IDs (comma-separated) |
Example Request:
GET /v1/e/facebook/breakdowns/act_123456789/ads?since=2024-01-01&until=2024-12-31&campaignids=123&adsetids=456,789
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": {
"23851234567890789": {
"ad_name": "Summer Sale - Image Ad 1",
"January": {
"impressions": 4000,
"cpm": 12.5,
"clicks": 120,
"cpc": 0.42,
"cpa": 4,
"spend": 50.0
},
"February": {
"impressions": 4750,
"cpm": 11.8,
"clicks": 143,
"cpc": 0.39,
"cpa": 6,
"spend": 56.1
}
}
}
}
Implementation Differences:
// Set level to ad
filterParams.level = 'ad';
// Ad set filtering
if (filterParams.adsetids) {
filterParams.filtering.push({
field: 'adset.id',
operator: 'IN',
value: filterParams.adsetids.split(','),
});
delete filterParams.adsetids;
}
// Name search
if (filterParams.search) {
filterParams.filtering.push({
field: 'ad.name',
operator: 'CONTAIN',
value: filterParams.search,
});
delete filterParams.search;
}
// Status filtering
if (filterParams.status) {
filterParams.filtering.push({
field: 'ad.effective_status',
operator: 'IN',
value: filterParams.status.split(','),
});
delete filterParams.status;
}
Time Increment
All breakdown endpoints use time_increment: 'monthly' which groups data by calendar month:
filterParams.time_increment = 'monthly';
Available Time Increments:
const timeIncrements = {
1: 'Daily breakdown',
7: 'Weekly breakdown',
monthly: 'Monthly breakdown (used by breakdowns)',
all_days: 'Total for entire range',
};
Data Aggregation
Month Initialization
All 12 months are initialized to zero values, even if no data exists:
const monthsArray = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
for (let i = 0; i < 12; i++) {
months[id][monthsArray[i]] = {
impressions: 0,
cpm: 0,
clicks: 0,
cpc: 0,
cpa: 0,
spend: 0,
};
}
Metric Aggregation
Metrics are summed across all days within each month:
let month = new Date(dataInsight.date_start).getMonth();
let monthName = monthsArray[month];
// Aggregate metrics
campaign[monthName]['impressions'] += parseInt(dataInsight.impressions || 0);
campaign[monthName]['cpm'] += parseInt(dataInsight.cpm || 0);
campaign[monthName]['clicks'] += parseInt(dataInsight.clicks || 0);
campaign[monthName]['cpc'] += parseInt(dataInsight.cpc || 0);
campaign[monthName]['spend'] += parseFloat(dataInsight.spend || 0);
Purchase Action Extraction
The cpa metric specifically tracks purchase actions:
if (dataInsight.actions) {
const resultPurchase = dataInsight.actions.find(({ action_type }) => action_type === 'purchase');
if (resultPurchase && resultPurchase.value) {
campaign[monthName]['cpa'] += parseInt(resultPurchase.value);
}
}
Use Cases
Year-over-Year Comparison
Compare performance across months for trend analysis:
// Request full year
GET /breakdowns/act_123/campaigns?since=2024-01-01&until=2024-12-31
// Response includes all 12 months
{
"23851234567890123": {
"campaign_name": "Brand Campaign",
"January": { "spend": 1000, "impressions": 50000 },
"February": { "spend": 1200, "impressions": 60000 },
// ... rest of months
}
}
Seasonal Analysis
Identify seasonal trends by comparing months:
// Q1 (Jan-Mar) vs Q2 (Apr-Jun) vs Q3 (Jul-Sep) vs Q4 (Oct-Dec)
const q1Spend = data.January.spend + data.February.spend + data.March.spend;
const q2Spend = data.April.spend + data.May.spend + data.June.spend;
Campaign Lifecycle
Track campaign performance from launch to completion:
// Campaign launched in March, ended in August
// Response shows:
// - Zeros for Jan-Feb (before launch)
// - Performance data for Mar-Aug
// - Zeros for Sep-Dec (after end)
Performance Considerations
Date Range Limits
- Recommended: Up to 12 months (1 year)
- Maximum: No hard limit, but larger ranges impact performance
Data Volume
Breakdown endpoints aggregate at the monthly level, reducing data volume compared to daily breakdowns:
// Daily breakdown: 365 data points per campaign
// Monthly breakdown: 12 data points per campaign
Caching Strategy
const cachingStrategy = {
'Historical months': "Cache indefinitely (won't change)",
'Current month': 'Cache for 1 hour (updates frequently)',
'Future months': 'Always return zeros (no caching needed)',
};
Error Handling
Common Errors
// No token found
{
"success": false,
"errno": 400,
"message": "Record Not found!"
}
// Invalid account
{
"success": false,
"errno": 400,
"message": "Invalid Account Id"
}
// No data in date range (still returns structure)
{
"success": true,
"data": {
"23851234567890123": {
"campaign_name": "Campaign",
"January": { "impressions": 0, "clicks": 0, "spend": 0, ... },
// All months with zero values
}
}
}
Integration Checklist
Breakdown Implementation
- Connect Facebook with
meta-adssource - Test campaign monthly breakdown
- Test ad set monthly breakdown
- Test ad monthly breakdown
- Verify date range handling
- Test filtering (status, search, IDs)
- Verify month initialization (all 12 months)
- Test zero-value months
- Verify purchase action extraction
Data Visualization
- Create month-over-month comparison charts
- Build seasonal trend analysis
- Implement year-over-year comparison
- Add quarter aggregation
- Create performance heatmaps
Related Documentation
- Facebook Index - Integration overview
- Analytics & Insights - Performance metrics
- Campaigns - Campaign operations
- Authentication - OAuth flow