Skip to main content
Glama

Facebook Ads Management Control Panel

by codprocess
campaigns.js14.1 kB
/** * Campaigns routes * Handles operations related to Facebook ad campaigns */ const express = require('express'); const router = express.Router(); const { protect, checkFacebookToken } = require('../middleware/auth'); const { validate, schemas } = require('../middleware/validator'); const { sendSuccess, sendError, sendPaginated } = require('../utils/responseFormatter'); const { NotFoundError, ValidationError } = require('../utils/errorTypes'); const Campaign = require('../models/campaign'); const AdAccount = require('../models/adAccount'); const facebookApiService = require('../services/facebookApiService'); const analyticsService = require('../services/analyticsService'); const logger = require('../utils/logger'); /** * @route GET /api/campaigns * @desc Get all campaigns for the current user * @access Private */ router.get('/', protect, async (req, res, next) => { try { // Get pagination parameters const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 20; const skip = (page - 1) * limit; // Build query const query = { userId: req.user._id }; // Filter by ad account if provided if (req.query.adAccountId) { query.adAccountId = req.query.adAccountId; } // Filter by status if provided if (req.query.status) { query.status = req.query.status; } // Get campaigns from database const campaigns = await Campaign.find(query) .sort({ createdAt: -1 }) .skip(skip) .limit(limit); // Get total count const total = await Campaign.countDocuments(query); return sendPaginated(res, campaigns, page, limit, total, 'Campaigns retrieved successfully'); } catch (error) { logger.error(`Error retrieving campaigns: ${error.message}`); return next(error); } }); /** * @route GET /api/campaigns/sync * @desc Sync campaigns from Facebook * @access Private */ router.get('/sync', protect, checkFacebookToken, async (req, res, next) => { try { // Get ad account ID from query params const { adAccountId } = req.query; if (!adAccountId) { return next(new ValidationError('Ad account ID is required')); } // Check if ad account exists const adAccount = await AdAccount.findOne({ accountId: adAccountId, userId: req.user._id }); if (!adAccount) { return next(new NotFoundError('Ad account not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Get campaigns from Facebook const fbCampaigns = await fbApi.getCampaigns(adAccountId); // Process and save campaigns const savedCampaigns = []; for (const fbCampaign of fbCampaigns) { // Find existing campaign or create new one let campaign = await Campaign.findOne({ campaignId: fbCampaign.id, userId: req.user._id }); if (!campaign) { campaign = new Campaign({ campaignId: fbCampaign.id, adAccountId: adAccountId, userId: req.user._id }); } // Update campaign details campaign.name = fbCampaign.name; campaign.objective = fbCampaign.objective; campaign.status = fbCampaign.status; campaign.specialAdCategories = fbCampaign.special_ad_categories || []; campaign.spendCap = fbCampaign.spend_cap; campaign.dailyBudget = fbCampaign.daily_budget; campaign.lifetimeBudget = fbCampaign.lifetime_budget; campaign.startTime = fbCampaign.start_time ? new Date(fbCampaign.start_time) : null; campaign.endTime = fbCampaign.stop_time ? new Date(fbCampaign.stop_time) : null; campaign.lastSyncedAt = new Date(); // Save campaign await campaign.save(); savedCampaigns.push(campaign); } return sendSuccess(res, savedCampaigns, 'Campaigns synced successfully'); } catch (error) { logger.error(`Error syncing campaigns: ${error.message}`); return next(error); } }); /** * @route POST /api/campaigns * @desc Create a new campaign * @access Private */ router.post('/', protect, checkFacebookToken, validate(schemas.campaign.create), async (req, res, next) => { try { // Check if ad account exists const adAccount = await AdAccount.findOne({ accountId: req.body.adAccountId, userId: req.user._id }); if (!adAccount) { return next(new NotFoundError('Ad account not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Prepare campaign data for Facebook const campaignData = { name: req.body.name, objective: req.body.objective, status: req.body.status || 'PAUSED', special_ad_categories: req.body.specialAdCategories || [], spend_cap: req.body.spendCap, daily_budget: req.body.dailyBudget, lifetime_budget: req.body.lifetimeBudget, start_time: req.body.startTime, end_time: req.body.endTime }; // Create campaign on Facebook const fbResponse = await fbApi.createCampaign(req.body.adAccountId, campaignData); // Create campaign in database const campaign = new Campaign({ campaignId: fbResponse.id, name: req.body.name, adAccountId: req.body.adAccountId, userId: req.user._id, objective: req.body.objective, status: req.body.status || 'PAUSED', specialAdCategories: req.body.specialAdCategories || [], spendCap: req.body.spendCap, dailyBudget: req.body.dailyBudget, lifetimeBudget: req.body.lifetimeBudget, startTime: req.body.startTime, endTime: req.body.endTime, lastSyncedAt: new Date() }); // Save campaign await campaign.save(); return sendSuccess(res, campaign, 'Campaign created successfully', 201); } catch (error) { logger.error(`Error creating campaign: ${error.message}`); return next(error); } }); /** * @route GET /api/campaigns/:id * @desc Get campaign by ID * @access Private */ router.get('/:id', protect, validate(schemas.idParam, 'params'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } return sendSuccess(res, campaign, 'Campaign retrieved successfully'); } catch (error) { logger.error(`Error retrieving campaign: ${error.message}`); return next(error); } }); /** * @route PUT /api/campaigns/:id * @desc Update campaign * @access Private */ router.put('/:id', protect, checkFacebookToken, validate(schemas.idParam, 'params'), validate(schemas.campaign.update), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Prepare campaign data for Facebook const campaignData = {}; if (req.body.name) campaignData.name = req.body.name; if (req.body.status) campaignData.status = req.body.status; if (req.body.spendCap !== undefined) campaignData.spend_cap = req.body.spendCap; if (req.body.dailyBudget !== undefined) campaignData.daily_budget = req.body.dailyBudget; if (req.body.lifetimeBudget !== undefined) campaignData.lifetime_budget = req.body.lifetimeBudget; if (req.body.startTime) campaignData.start_time = req.body.startTime; if (req.body.endTime) campaignData.end_time = req.body.endTime; // Update campaign on Facebook await fbApi.updateCampaign(req.params.id, campaignData); // Update campaign in database if (req.body.name) campaign.name = req.body.name; if (req.body.status) campaign.status = req.body.status; if (req.body.spendCap !== undefined) campaign.spendCap = req.body.spendCap; if (req.body.dailyBudget !== undefined) campaign.dailyBudget = req.body.dailyBudget; if (req.body.lifetimeBudget !== undefined) campaign.lifetimeBudget = req.body.lifetimeBudget; if (req.body.startTime) campaign.startTime = req.body.startTime; if (req.body.endTime) campaign.endTime = req.body.endTime; campaign.lastSyncedAt = new Date(); // Save campaign await campaign.save(); return sendSuccess(res, campaign, 'Campaign updated successfully'); } catch (error) { logger.error(`Error updating campaign: ${error.message}`); return next(error); } }); /** * @route DELETE /api/campaigns/:id * @desc Delete campaign * @access Private */ router.delete('/:id', protect, checkFacebookToken, validate(schemas.idParam, 'params'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Delete campaign on Facebook (actually sets status to DELETED) await fbApi.updateCampaign(req.params.id, { status: 'DELETED' }); // Update campaign status in database campaign.status = 'DELETED'; await campaign.save(); return sendSuccess(res, { id: req.params.id }, 'Campaign deleted successfully'); } catch (error) { logger.error(`Error deleting campaign: ${error.message}`); return next(error); } }); /** * @route GET /api/campaigns/:id/insights * @desc Get insights for a campaign * @access Private */ router.get('/:id/insights', protect, checkFacebookToken, validate(schemas.idParam, 'params'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Get time range from query params const timeRange = req.query.timeRange || 'last_30_days'; // Get insights from Facebook const insights = await fbApi.getInsights(req.params.id, timeRange, [], { level: 'campaign' }); return sendSuccess(res, insights, 'Campaign insights retrieved successfully'); } catch (error) { logger.error(`Error retrieving campaign insights: ${error.message}`); return next(error); } }); /** * @route GET /api/campaigns/:id/adsets * @desc Get ad sets for a campaign * @access Private */ router.get('/:id/adsets', protect, checkFacebookToken, validate(schemas.idParam, 'params'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create Facebook API service const fbApi = await facebookApiService.createForUser(req.user); // Get ad sets from Facebook const adSets = await fbApi.getAdSets(req.params.id); return sendSuccess(res, adSets, 'Campaign ad sets retrieved successfully'); } catch (error) { logger.error(`Error retrieving campaign ad sets: ${error.message}`); return next(error); } }); /** * @route GET /api/campaigns/:id/analytics * @desc Get analytics for a campaign * @access Private */ router.get('/:id/analytics', protect, validate(schemas.idParam, 'params'), validate(schemas.analytics.query, 'query'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create analytics service const analytics = analyticsService.createForUser(req.user); // Get start and end dates from query params const startDate = new Date(req.query.startDate); const endDate = new Date(req.query.endDate); // Get analytics data const analyticsData = await analytics.getCampaignAnalytics(req.params.id, startDate, endDate); return sendSuccess(res, analyticsData, 'Campaign analytics retrieved successfully'); } catch (error) { logger.error(`Error retrieving campaign analytics: ${error.message}`); return next(error); } }); /** * @route POST /api/campaigns/:id/fetch-analytics * @desc Fetch and store analytics for a campaign * @access Private */ router.post('/:id/fetch-analytics', protect, checkFacebookToken, validate(schemas.idParam, 'params'), async (req, res, next) => { try { // Get campaign from database const campaign = await Campaign.findOne({ campaignId: req.params.id, userId: req.user._id }); if (!campaign) { return next(new NotFoundError('Campaign not found')); } // Create analytics service const analytics = analyticsService.createForUser(req.user); // Get time range from query params const timeRange = req.query.timeRange || 'last_30_days'; // Fetch and store analytics data const analyticsData = await analytics.fetchCampaignAnalytics(req.params.id, timeRange); return sendSuccess(res, analyticsData, 'Campaign analytics fetched successfully'); } catch (error) { logger.error(`Error fetching campaign analytics: ${error.message}`); return next(error); } }); module.exports = router;

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/codprocess/facebook-ads-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server