adSet.js•3.8 kB
/**
* Ad Set model
* Stores information about Facebook ad sets
*/
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const adSetSchema = new Schema({
// Facebook ad set ID
adSetId: {
type: String,
required: true,
unique: true,
index: true
},
// Ad set name
name: {
type: String,
required: true
},
// Campaign this ad set belongs to
campaignId: {
type: String,
required: true,
index: true
},
// User who owns this ad set
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
index: true
},
// Ad set status
status: {
type: String,
enum: ['ACTIVE', 'PAUSED', 'DELETED', 'ARCHIVED'],
default: 'PAUSED'
},
// Targeting configuration
targeting: {
type: Schema.Types.Mixed,
required: true
},
// Optimization and bidding
optimization: {
type: String,
required: true
},
bidStrategy: {
type: String,
required: true
},
bidAmount: {
type: Number
},
// Budget
budget: {
type: Number,
required: true,
min: 0
},
budgetType: {
type: String,
enum: ['DAILY', 'LIFETIME'],
default: 'DAILY'
},
// Schedule
startTime: {
type: Date
},
endTime: {
type: Date
},
// Placement configuration
placements: {
type: Schema.Types.Mixed
},
// Ad set 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
}
},
// Audience insights (cached)
audienceInsights: {
type: Schema.Types.Mixed
},
// 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
adSetSchema.index({ adSetId: 1 });
adSetSchema.index({ campaignId: 1 });
adSetSchema.index({ userId: 1 });
adSetSchema.index({ status: 1 });
adSetSchema.index({ createdAt: -1 });
/**
* Find ad sets by user ID
*/
adSetSchema.statics.findByUserId = function(userId) {
return this.find({ userId });
};
/**
* Find ad sets by campaign ID
*/
adSetSchema.statics.findByCampaignId = function(campaignId) {
return this.find({ campaignId });
};
/**
* Find active ad sets
*/
adSetSchema.statics.findActive = function() {
return this.find({ status: 'ACTIVE' });
};
/**
* Find ad set by Facebook ad set ID
*/
adSetSchema.statics.findByAdSetId = function(adSetId) {
return this.findOne({ adSetId });
};
/**
* Update ad set metrics
*/
adSetSchema.methods.updateMetrics = function(metrics) {
this.metrics = { ...this.metrics, ...metrics };
return this.save();
};
/**
* Update audience insights
*/
adSetSchema.methods.updateAudienceInsights = function(insights) {
this.audienceInsights = insights;
return this.save();
};
/**
* Update last synced timestamp
*/
adSetSchema.methods.updateLastSynced = function() {
this.lastSyncedAt = Date.now();
return this.save();
};
const AdSet = mongoose.model('AdSet', adSetSchema);
module.exports = AdSet;