campaign.js•3.75 kB
/**
* Campaign model
* Stores information about Facebook ad campaigns
*/
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const campaignSchema = new Schema({
// Facebook campaign ID
campaignId: {
type: String,
required: true,
unique: true,
index: true
},
// Campaign name
name: {
type: String,
required: true
},
// Ad account this campaign belongs to
adAccountId: {
type: String,
required: true,
index: true
},
// User who owns this campaign
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
index: true
},
// Campaign objective
objective: {
type: String,
enum: [
'BRAND_AWARENESS',
'REACH',
'TRAFFIC',
'APP_INSTALLS',
'VIDEO_VIEWS',
'LEAD_GENERATION',
'MESSAGES',
'CONVERSIONS',
'CATALOG_SALES',
'STORE_TRAFFIC',
'ENGAGEMENT'
],
required: true
},
// Campaign status
status: {
type: String,
enum: ['ACTIVE', 'PAUSED', 'DELETED', 'ARCHIVED'],
default: 'PAUSED'
},
// Campaign budget
spendCap: {
type: Number,
min: 0
},
dailyBudget: {
type: Number,
min: 0
},
lifetimeBudget: {
type: Number,
min: 0
},
// Campaign schedule
startTime: {
type: Date
},
endTime: {
type: Date
},
// Campaign performance metrics (cached)
metrics: {
impressions: {
type: Number,
default: 0
},
clicks: {
type: Number,
default: 0
},
spend: {
type: Number,
default: 0
},
conversions: {
type: Number,
default: 0
},
ctr: {
type: Number,
default: 0
},
cpc: {
type: Number,
default: 0
},
cpm: {
type: Number,
default: 0
},
reach: {
type: Number,
default: 0
},
frequency: {
type: Number,
default: 0
},
costPerConversion: {
type: Number,
default: 0
},
conversionRate: {
type: Number,
default: 0
},
roas: {
type: Number,
default: 0
}
},
// Campaign metadata
specialAdCategories: {
type: [String],
default: []
},
// Timestamps
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
},
// Last sync with Facebook
lastSyncedAt: {
type: Date,
default: Date.now
}
}, {
timestamps: true
});
// Indexes for faster queries
campaignSchema.index({ campaignId: 1 });
campaignSchema.index({ adAccountId: 1 });
campaignSchema.index({ userId: 1 });
campaignSchema.index({ status: 1 });
campaignSchema.index({ objective: 1 });
campaignSchema.index({ createdAt: -1 });
/**
* Find campaigns by user ID
*/
campaignSchema.statics.findByUserId = function(userId) {
return this.find({ userId });
};
/**
* Find campaigns by ad account ID
*/
campaignSchema.statics.findByAdAccountId = function(adAccountId) {
return this.find({ adAccountId });
};
/**
* Find active campaigns
*/
campaignSchema.statics.findActive = function() {
return this.find({ status: 'ACTIVE' });
};
/**
* Find campaign by Facebook campaign ID
*/
campaignSchema.statics.findByCampaignId = function(campaignId) {
return this.findOne({ campaignId });
};
/**
* Update campaign metrics
*/
campaignSchema.methods.updateMetrics = function(metrics) {
this.metrics = { ...this.metrics, ...metrics };
return this.save();
};
/**
* Update last synced timestamp
*/
campaignSchema.methods.updateLastSynced = function() {
this.lastSyncedAt = Date.now();
return this.save();
};
const Campaign = mongoose.model('Campaign', campaignSchema);
module.exports = Campaign;