alles andere
This commit is contained in:
183
packages/orchestrator/src/workflows/04-paid-ads.ts
Normal file
183
packages/orchestrator/src/workflows/04-paid-ads.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user