Skip to main content
Glama

Facebook Ads Management Control Panel

by codprocess
analytics.js5.24 kB
/** * Analytics model * Stores analytics data for Facebook ads */ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const analyticsSchema = new Schema({ // Entity ID (campaign, ad set, or ad) entityId: { type: String, required: true, index: true }, // Entity type entityType: { type: String, enum: ['campaign', 'adset', 'ad'], required: true, index: true }, // User who owns this entity userId: { type: Schema.Types.ObjectId, ref: 'User', required: true, index: true }, // Date of analytics data date: { type: Date, required: true, index: true }, // Performance metrics impressions: { type: Number, default: 0 }, reach: { type: Number, default: 0 }, clicks: { type: Number, default: 0 }, ctr: { type: Number, default: 0 }, cpc: { type: Number, default: 0 }, cpm: { type: Number, default: 0 }, spend: { type: Number, default: 0 }, frequency: { type: Number, default: 0 }, // Conversion metrics conversions: { type: Number, default: 0 }, conversionRate: { type: Number, default: 0 }, costPerConversion: { type: Number, default: 0 }, roas: { type: Number, default: 0 }, // Engagement metrics engagement: { type: Schema.Types.Mixed, default: { postEngagement: 0, pageLikes: 0, postComments: 0, postShares: 0, linkClicks: 0, videoViews: 0, videoWatchTime: 0 } }, // Demographic breakdown demographics: { type: Schema.Types.Mixed }, // Placement breakdown placements: { type: Schema.Types.Mixed }, // Device breakdown devices: { type: Schema.Types.Mixed }, // Region breakdown regions: { type: Schema.Types.Mixed }, // Raw data from Facebook rawData: { type: Schema.Types.Mixed }, // Timestamps createdAt: { type: Date, default: Date.now }, updatedAt: { type: Date, default: Date.now } }, { timestamps: true }); // Compound index for faster queries analyticsSchema.index({ entityId: 1, date: 1 }); analyticsSchema.index({ userId: 1, entityType: 1, date: 1 }); analyticsSchema.index({ entityType: 1, date: 1 }); /** * Find analytics by entity ID */ analyticsSchema.statics.findByEntityId = function(entityId, startDate, endDate) { const query = { entityId }; if (startDate || endDate) { query.date = {}; if (startDate) query.date.$gte = startDate; if (endDate) query.date.$lte = endDate; } return this.find(query).sort({ date: 1 }); }; /** * Find analytics by user ID */ analyticsSchema.statics.findByUserId = function(userId, entityType, startDate, endDate) { const query = { userId }; if (entityType) query.entityType = entityType; if (startDate || endDate) { query.date = {}; if (startDate) query.date.$gte = startDate; if (endDate) query.date.$lte = endDate; } return this.find(query).sort({ date: 1 }); }; /** * Find analytics by date range */ analyticsSchema.statics.findByDateRange = function(startDate, endDate, entityType) { const query = {}; if (entityType) query.entityType = entityType; if (startDate || endDate) { query.date = {}; if (startDate) query.date.$gte = startDate; if (endDate) query.date.$lte = endDate; } return this.find(query).sort({ date: 1 }); }; /** * Calculate aggregate metrics for a specific entity */ analyticsSchema.statics.calculateAggregateMetrics = async function(entityId, startDate, endDate) { const pipeline = [ { $match: { entityId, date: { $gte: startDate, $lte: endDate } } }, { $group: { _id: '$entityId', impressions: { $sum: '$impressions' }, reach: { $sum: '$reach' }, clicks: { $sum: '$clicks' }, spend: { $sum: '$spend' }, conversions: { $sum: '$conversions' }, // Calculate averages ctr: { $avg: '$ctr' }, cpc: { $avg: '$cpc' }, cpm: { $avg: '$cpm' }, frequency: { $avg: '$frequency' }, conversionRate: { $avg: '$conversionRate' }, costPerConversion: { $avg: '$costPerConversion' }, roas: { $avg: '$roas' } } } ]; const results = await this.aggregate(pipeline); return results.length > 0 ? results[0] : null; }; /** * Find or create analytics entry */ analyticsSchema.statics.findOrCreate = async function(entityId, entityType, userId, date, data) { // Format date to start of day const formattedDate = new Date(date); formattedDate.setHours(0, 0, 0, 0); // Find existing entry let analytics = await this.findOne({ entityId, entityType, userId, date: formattedDate }); // Create new entry if not found if (!analytics) { analytics = new this({ entityId, entityType, userId, date: formattedDate, ...data }); } else { // Update existing entry Object.assign(analytics, data); } return analytics.save(); }; const Analytics = mongoose.model('Analytics', analyticsSchema); module.exports = Analytics;

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