Trying to build a Node.js app to gather campaign data from Facebook campaigns and storing them into a local database.
I've been successful in getting all the ads for a specific campaign via the /ads endpoint. Then using the /insights endpoint to collect the metrics and statistics for the specific ad.
Successful code for getting ads and their metrics for a specific campaign:
async function getMetaAdsForCampaign(campaignId, campaignName) {
try {
const adsResponse = await axios.get(`${GRAPH_API}/${campaignId}/ads`, {
params: {
fields: 'id,name,status,effective_status',
access_token: process.env.FB_ACCESS_TOKEN,
},
});
let ads = adsResponse.data?.data || [];
ads = ads.slice(0, 5);
if (ads.length === 0) {
console.log(`Inga annonser hittades för kampanj ${campaignId}`);
return [];
}
const batchRequests = ads.map(ad => ({
method: 'GET',
relative_url: `${ad.id}/insights?fields=spend,impressions,clicks,video_continuous_2_sec_watched_actions,outbound_clicks&date_preset=maximum`,
}));
const batchResponse = await axios.post(`${GRAPH_API}`, {
access_token: process.env.FB_ACCESS_TOKEN,
batch: batchRequests,
});
const insightsData = batchResponse.data;
return ads.map((ad, index) => {
const insightsResponse = insightsData[index];
if (insightsResponse.code === 200 && insightsResponse.body) {
const insights = JSON.parse(insightsResponse.body).data[0] || {};
const spend = parseFloat(insights.spend || 0);
const impressions = parseInt(insights.impressions || 0, 10);
const link_clicks = parseInt(insights.outbound_clicks?.[0]?.value || 0, 10);
const video_views = parseInt(insights.video_continuous_2_sec_watched_actions?.[0]?.value || 0, 10);
const cpm = impressions > 0 ? Math.round((spend / impressions) * 1000 * 100) / 100 : 0;
const link_cpc = link_clicks > 0 ? Math.round((spend / link_clicks) * 100) / 100 : 0;
const cpv = video_views > 0 ? Math.round((spend / video_views) * 100) / 100 : 0;
return {
ad_id: ad.id,
campaign_id: campaignId,
campaign_name: campaignName,
ad_name: ad.name,
spend,
impressions,
cpm,
link_clicks,
link_cpc,
video_views,
cpv,
};
} else {
console.error(`Misslyckades att hämta insikter för annons ${ad.id}:`, insightsResponse.body);
return {
ad_id: ad.id,
campaign_id: campaignId,
campaign_name: campaignName,
ad_name: ad.name,
spend: 0,
impressions: 0,
cpm: 0,
link_clicks: 0,
link_cpc: 0,
video_views: 0,
cpv: 0,
};
}
});
} catch (error) {
console.error("Ett fel uppstod vid hämtning av annonser:", error.response?.data || error.message);
return [];
}
}
The problem I have is gathering fields from the ad creatives, such as title, body, image_url or link_url.
After reading the existing documentation, I've succeded to gather this via the /adcreatives endpoint. The problem I'm facing here is that the only time I'm successful in this, is when using the endpoint with a campaign id, which results in a lot of creatives, and not for a specific ad.
Code that successfully returns the ad creative data I'm after (but only based on campaign_id, and not for specific ads):
async function getAdCreativeFromCampaign() {
const testCampaignId = 'act_123123123123123';
try {
const adsResponse = await axios.get(`${GRAPH_API}/${testCampaignId}/adcreatives`, {
params: {
fields: 'id,status,title,description,body,image_url,link_url',
access_token: process.env.FB_ACCESS_TOKEN,
limit: '1',
},
});
console.log('Resultat:', JSON.stringify(adsResponse.data, null, 2));
} catch (error) {
if (error.response) {
// Fel från servern
console.error('Serverfel:', error.response.status, error.response.statusText);
console.error('Detaljer:', error.response.data);
} else if (error.request) {
// Ingen respons från servern
console.error('Ingen respons från servern:', error.request);
} else {
// Något gick fel vid anropet
console.error('Fel vid begäran:', error.message);
}
}
}
Questions I'm not finding answers to:
Is it any way to gather these fields from /adcreatives for a specific ad, and not for a whole campaign, that I could use instead?
Tried getting results from /adcreatives endpoint using different URLs for specific ads with no luck and only blank results.
Also been trying to gettings fields such as creative.id from an ad, to then connect it to a creative_id, if using this method of first getting all ads, and then all creatives from an ad account. But this method seems really like a detour, and that it should be a better way?
Thank you in advance if you have any ideas that might help me!