Files
dashboard/examples DO NOT USE OR EDIT/EXAMPLE ONLY metaAdsService.js

177 lines
5.1 KiB
JavaScript

import axios from "axios";
class MetaAdsService {
constructor() {
this.client = axios.create({
baseURL: "/api/meta-ads",
headers: {
"Content-Type": "application/json",
},
});
}
// metaAdsService.js
processMetrics(campaign) {
const insights = campaign.insights?.data?.[0] || {};
const spend = parseFloat(insights.spend || 0);
const impressions = parseInt(insights.impressions || 0);
const clicks = parseInt(insights.clicks || 0);
const reach = parseInt(insights.reach || 0);
const cpc = parseFloat(insights.cpc || 0);
const ctr = parseFloat(insights.ctr || 0);
const cpm = parseFloat(insights.cpm || 0);
const frequency = parseFloat(insights.frequency || 0);
// Purchase value and total purchases
const purchaseValue = (insights.action_values || [])
.filter(({ action_type }) => action_type === "purchase")
.reduce((sum, { value }) => sum + parseFloat(value || 0), 0);
const totalPurchases = (insights.actions || [])
.filter(({ action_type }) => action_type === "purchase")
.reduce((sum, { value }) => sum + parseInt(value || 0), 0);
// Aggregate unique actions
const actionMap = new Map();
(insights.actions || []).forEach(({ action_type, value }) => {
const currentValue = actionMap.get(action_type) || 0;
actionMap.set(action_type, currentValue + parseInt(value || 0));
});
const actions = Array.from(actionMap.entries()).map(
([action_type, value]) => ({
action_type,
value,
})
);
// Map of cost per action
const costPerActionMap = new Map();
(insights.cost_per_action_type || []).forEach(({ action_type, value }) => {
costPerActionMap.set(action_type, parseFloat(value || 0));
});
// Total post engagements
const totalPostEngagements = actionMap.get("post_engagement") || 0;
return {
spend,
impressions,
clicks,
reach,
frequency,
ctr,
cpm,
cpc,
actions,
costPerActionMap, // Include cost per action map
purchaseValue,
totalPurchases,
totalPostEngagements, // Include total post engagements
};
}
getObjectiveAction(campaignObjective) {
const objectiveMap = {
OUTCOME_AWARENESS: { action_type: "impressions", label: "Impressions" },
OUTCOME_ENGAGEMENT: {
action_type: "post_engagement",
label: "Post Engagements",
},
OUTCOME_TRAFFIC: { action_type: "link_click", label: "Link Clicks" },
OUTCOME_LEADS: { action_type: "lead", label: "Leads" },
OUTCOME_SALES: { action_type: "purchase", label: "Purchases" },
MESSAGES: { action_type: "messages", label: "Messages" },
// Add other objectives as needed
};
return (
objectiveMap[campaignObjective] || {
action_type: "link_click",
label: "Link Clicks",
}
);
}
calculateBudget(campaign) {
if (campaign.daily_budget) {
return { value: campaign.daily_budget / 100, type: "day" };
}
if (campaign.lifetime_budget) {
return { value: campaign.lifetime_budget / 100, type: "lifetime" };
}
const adsets = campaign.adsets?.data || [];
const dailyTotal = adsets.reduce(
(sum, adset) => sum + (adset.daily_budget || 0),
0
);
const lifetimeTotal = adsets.reduce(
(sum, adset) => sum + (adset.lifetime_budget || 0),
0
);
if (dailyTotal > 0) return { value: dailyTotal / 100, type: "day" };
if (lifetimeTotal > 0)
return { value: lifetimeTotal / 100, type: "lifetime" };
return { value: 0, type: "day" };
}
processCampaignData(campaign) {
const metrics = this.processMetrics(campaign);
const budget = this.calculateBudget(campaign);
const { action_type, label } = this.getObjectiveAction(campaign.objective);
// Get cost per result from costPerActionMap
const costPerResult = metrics.costPerActionMap.get(action_type) || 0;
return {
id: campaign.id,
name: campaign.name,
status: campaign.status,
objective: label, // User-friendly objective label
objectiveActionType: action_type, // Action type for metrics
budget: budget.value,
budgetType: budget.type,
metrics: {
...metrics,
costPerResult,
},
};
}
async getCampaigns({ since, until }) {
try {
const response = await this.client.get("/campaigns", {
params: { since, until },
});
return response.data.map((campaign) =>
this.processCampaignData(campaign)
);
} catch (error) {
console.error(
"Error fetching campaigns:",
error.response?.data || error.message
);
throw error;
}
}
async getAccountInsights({ since, until }) {
try {
const response = await this.client.get("/account_insights", {
params: { since, until },
});
return response.data; // This will be an object with reach and other fields
} catch (error) {
console.error(
"Error fetching account insights:",
error.response?.data || error.message
);
throw error;
}
}
}
export const metaAdsService = new MetaAdsService();