self-replicating/packages/orchestrator/src/workflows/04-paid-ads.ts

184 lines
5.5 KiB
TypeScript

import { WorkflowBase, WorkflowContext, WorkflowResult } from './workflow-base';
import { WorkflowType } from '@prisma/client';
import { FacebookAdsExpert } from '../integrations/claude/skills/facebook-ads-expert';
import { GoogleAdsExpert } from '../integrations/claude/skills/google-ads-expert';
import { FacebookAdsAPI } from '../integrations/ads/facebook-ads';
import { GoogleAdsAPI } from '../integrations/ads/google-ads';
import { log } from '../monitoring/logger';
import { integrations } from '../utils/config';
export class PaidAdsWorkflow extends WorkflowBase {
protected type: WorkflowType = 'PAID_ADS';
private fbExpert: FacebookAdsExpert;
private googleExpert: GoogleAdsExpert;
private fbAds: FacebookAdsAPI;
private googleAds: GoogleAdsAPI;
constructor(db: any, alerts: any) {
super(db, alerts);
this.fbExpert = new FacebookAdsExpert();
this.googleExpert = new GoogleAdsExpert();
this.fbAds = new FacebookAdsAPI();
this.googleAds = new GoogleAdsAPI();
}
protected async execute(context: WorkflowContext): Promise<WorkflowResult> {
const business = await this.getBusiness(context.businessId);
log.info('Starting paid ads campaigns', { businessId: context.businessId });
const results: any = {
facebook: null,
google: null,
};
try {
// Step 1: Create Facebook Ads campaign
if (integrations.hasFacebookAds()) {
results.facebook = await this.createFacebookCampaign(business);
log.info('Facebook campaign created', { businessId: context.businessId });
} else {
log.warn('Facebook Ads not configured - skipping', {
businessId: context.businessId,
});
}
// Step 2: Create Google Ads campaign
if (integrations.hasGoogleAds()) {
results.google = await this.createGoogleCampaign(business);
log.info('Google Ads campaign created', { businessId: context.businessId });
} else {
log.warn('Google Ads not configured - skipping', {
businessId: context.businessId,
});
}
// Step 3: Update business status
await this.db.business.update({
where: { id: context.businessId },
data: {
adsActive: true,
status: 'RUNNING_ADS',
},
});
return {
success: true,
data: results,
};
} catch (error) {
log.error('Paid ads workflow failed', error, { businessId: context.businessId });
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
private async createFacebookCampaign(business: any): Promise<any> {
try {
// Get campaign strategy from Claude
const strategy = await this.fbExpert.generateCampaignStrategy({
businessName: business.name,
businessIdea: business.idea,
budget: business.budget || 500,
targetAudience: business.targetAudience || 'general',
goal: 'CONVERSIONS',
});
// Create campaign via Facebook Ads API
const campaign = await this.fbAds.createCampaign({
name: `${business.name} - Conversions`,
objective: 'CONVERSIONS',
budget: business.budget || 500,
targeting: {
age_min: 25,
age_max: 65,
interests: [],
},
});
// Save campaign to database
await this.db.campaign.create({
data: {
businessId: business.id,
platform: 'FACEBOOK',
campaignId: campaign.id,
name: campaign.name,
budget: business.budget || 500,
dailyBudget: (business.budget || 500) / 30,
active: true,
targeting: campaign.targeting || {},
},
});
return {
success: true,
campaignId: campaign.id,
strategy: strategy.output,
};
} catch (error) {
log.error('Facebook campaign creation failed', error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
private async createGoogleCampaign(business: any): Promise<any> {
try {
// Get campaign strategy from Claude
const strategy = await this.googleExpert.generateCampaignStrategy({
businessName: business.name,
businessIdea: business.idea,
budget: business.budget || 500,
targetKeywords: this.extractKeywords(business.idea),
campaignType: 'SEARCH',
});
// Create campaign via Google Ads API
const campaign = await this.googleAds.createCampaign({
name: `${business.name} - Search`,
type: 'SEARCH',
budget: business.budget || 500,
keywords: this.extractKeywords(business.idea),
});
// Save campaign to database
await this.db.campaign.create({
data: {
businessId: business.id,
platform: 'GOOGLE',
campaignId: campaign.id,
name: campaign.name,
budget: business.budget || 500,
dailyBudget: (business.budget || 500) / 30,
active: true,
},
});
return {
success: true,
campaignId: campaign.id,
strategy: strategy.output,
};
} catch (error) {
log.error('Google Ads campaign creation failed', error);
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
}
private extractKeywords(text: string): string[] {
return text
.toLowerCase()
.replace(/[^a-z0-9\s]/g, '')
.split(/\s+/)
.filter((w) => w.length > 3)
.slice(0, 20);
}
}