fix: sem identidade de Instagram, não usar posicionamentos de IG (1772103)

Quando não há instagram_actor_id (ex: página sem IG vinculado, comum ao
republicar rascunho antigo que cai na 1a página da conta), a Meta recusa
o anúncio com subcode 1772103 ao tentar entregar no Instagram.

- rota: sem IG, restringe publisher_platforms a facebook/audience_network/
  messenger (exclui Instagram)
- placement customization: sem IG, regras não declaram instagram_positions

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marcio Bevervanso 2026-06-16 13:03:01 -03:00
parent 5dd4c675c4
commit 58d9825fa5
2 changed files with 28 additions and 19 deletions

View file

@ -247,6 +247,19 @@ export async function POST(req: Request) {
// análise/entrega na Meta. // análise/entrega na Meta.
const finalStatus = body.activate === true ? 'ACTIVE' : 'PAUSED'; const finalStatus = body.activate === true ? 'ACTIVE' : 'PAUSED';
const baseTargeting = targeting || { geo_locations: { countries: ['BR'] } };
const finalTargeting: Record<string, unknown> = {
...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, { const result = await createFullCampaign(mcpClient, {
campaign_name, campaign_name,
objective: finalObjective, objective: finalObjective,
@ -254,16 +267,7 @@ export async function POST(req: Request) {
status: finalStatus, status: finalStatus,
bid_strategy: finalBidStrategy, bid_strategy: finalBidStrategy,
bid_amount: finalBidStrategy === 'LOWEST_COST_WITHOUT_CAP' ? undefined : finalBidAmount, bid_amount: finalBidStrategy === 'LOWEST_COST_WITHOUT_CAP' ? undefined : finalBidAmount,
targeting: { targeting: finalTargeting,
...(targeting || {
geo_locations: {
countries: ['BR'],
},
}),
targeting_automation: {
advantage_audience: 0,
},
},
page_id: finalPageId, page_id: finalPageId,
instagram_actor_id: instagram_actor_id || undefined, instagram_actor_id: instagram_actor_id || undefined,
image_urls, image_urls,

View file

@ -291,27 +291,32 @@ export async function callMetaTool(
// O branch garante que ao menos vertical/horizontal existe. // O branch garante que ao menos vertical/horizontal existe.
const squareHash = (pi.square || pi.vertical || pi.horizontal) as string; 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 }> }> = [ const images: Array<{ hash: string; adlabels: Array<{ name: string }> }> = [
{ hash: squareHash, adlabels: [{ name: 'sq' }] }, { hash: squareHash, adlabels: [{ name: 'sq' }] },
]; ];
const rules: Array<Record<string, unknown>> = [ const rules: Array<Record<string, unknown>> = [
// Regra padrão (mais ampla): cobre todos os posicionamentos. // 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' }, image_label: { name: 'sq' },
}, },
]; ];
if (pi.vertical && pi.vertical !== squareHash) { if (pi.vertical && pi.vertical !== squareHash) {
images.push({ hash: pi.vertical, adlabels: [{ name: 'vt' }] }); images.push({ hash: pi.vertical, adlabels: [{ name: 'vt' }] });
rules.push({ const verticalSpec: Record<string, unknown> = {
customization_spec: { publisher_platforms: hasIg ? ['facebook', 'instagram'] : ['facebook'],
publisher_platforms: ['facebook', 'instagram'],
facebook_positions: ['story', 'facebook_reels'], facebook_positions: ['story', 'facebook_reels'],
instagram_positions: ['story', 'reels'], };
}, if (hasIg) verticalSpec.instagram_positions = ['story', 'reels'];
image_label: { name: 'vt' }, rules.push({ customization_spec: verticalSpec, image_label: { name: 'vt' } });
});
} }
if (pi.horizontal && pi.horizontal !== squareHash) { if (pi.horizontal && pi.horizontal !== squareHash) {