diff --git a/src/app/api/campaigns/create/route.ts b/src/app/api/campaigns/create/route.ts index 1996d09..2940b89 100644 --- a/src/app/api/campaigns/create/route.ts +++ b/src/app/api/campaigns/create/route.ts @@ -247,6 +247,19 @@ export async function POST(req: Request) { // análise/entrega na Meta. const finalStatus = body.activate === true ? 'ACTIVE' : 'PAUSED'; + const baseTargeting = targeting || { geo_locations: { countries: ['BR'] } }; + const finalTargeting: Record = { + ...baseTargeting, + targeting_automation: { advantage_audience: 0 }, + }; + + // Sem identidade de Instagram, o anúncio não pode rodar em posicionamentos + // do Instagram (a Meta recusa com subcode 1772103). Nesse caso restringimos + // aos posicionamentos que não exigem IG (Facebook/Audience Network/Messenger). + if (!instagram_actor_id && !(baseTargeting as any).publisher_platforms) { + finalTargeting.publisher_platforms = ['facebook', 'audience_network', 'messenger']; + } + const result = await createFullCampaign(mcpClient, { campaign_name, objective: finalObjective, @@ -254,16 +267,7 @@ export async function POST(req: Request) { status: finalStatus, bid_strategy: finalBidStrategy, bid_amount: finalBidStrategy === 'LOWEST_COST_WITHOUT_CAP' ? undefined : finalBidAmount, - targeting: { - ...(targeting || { - geo_locations: { - countries: ['BR'], - }, - }), - targeting_automation: { - advantage_audience: 0, - }, - }, + targeting: finalTargeting, page_id: finalPageId, instagram_actor_id: instagram_actor_id || undefined, image_urls, diff --git a/src/lib/mcp/client.ts b/src/lib/mcp/client.ts index cabf97c..24879f4 100644 --- a/src/lib/mcp/client.ts +++ b/src/lib/mcp/client.ts @@ -291,27 +291,32 @@ export async function callMetaTool( // O branch garante que ao menos vertical/horizontal existe. const squareHash = (pi.square || pi.vertical || pi.horizontal) as string; + // Sem IG, não declaramos posicionamentos de Instagram (a Meta exige + // identidade de IG pra eles — subcode 1772103). + const hasIg = !!args.instagram_actor_id; + const defaultPlatforms = hasIg + ? ['facebook', 'instagram', 'audience_network', 'messenger'] + : ['facebook', 'audience_network', 'messenger']; + const images: Array<{ hash: string; adlabels: Array<{ name: string }> }> = [ { hash: squareHash, adlabels: [{ name: 'sq' }] }, ]; const rules: Array> = [ // Regra padrão (mais ampla): cobre todos os posicionamentos. { - customization_spec: { publisher_platforms: ['facebook', 'instagram', 'audience_network', 'messenger'] }, + customization_spec: { publisher_platforms: defaultPlatforms }, image_label: { name: 'sq' }, }, ]; if (pi.vertical && pi.vertical !== squareHash) { images.push({ hash: pi.vertical, adlabels: [{ name: 'vt' }] }); - rules.push({ - customization_spec: { - publisher_platforms: ['facebook', 'instagram'], - facebook_positions: ['story', 'facebook_reels'], - instagram_positions: ['story', 'reels'], - }, - image_label: { name: 'vt' }, - }); + const verticalSpec: Record = { + publisher_platforms: hasIg ? ['facebook', 'instagram'] : ['facebook'], + facebook_positions: ['story', 'facebook_reels'], + }; + if (hasIg) verticalSpec.instagram_positions = ['story', 'reels']; + rules.push({ customization_spec: verticalSpec, image_label: { name: 'vt' } }); } if (pi.horizontal && pi.horizontal !== squareHash) {