Commit graph

30 commits

Author SHA1 Message Date
19004d0cc5 feat: automação autônoma do engine (n8n) — métricas de compra, persistência e alertas
Torna o engine de automação realmente autônomo e seguro:

- métricas: lê COMPRA de verdade (actions/purchase_roas) e calcula CPA;
  novas métricas 'cpa' e 'purchases'; regras padrão afinadas p/ low-ticket
- orçamento: ações de budget agora agem no CONJUNTO (não na campanha, que
  lançava erro); usa listAdSets + updateAdSetBudget
- segurança: "substituir via IA" desativado (criava campanha com page_id/
  link inválidos) — agora só pausa e recomenda
- modo de autonomia 'mixed': pausar/notificar executa; orçamento/IA viram
  só recomendação (com cooldown que evita re-notificar)
- persistência (Supabase): regras, logs e token (app_config) — store.ts
  com fallback gracioso; SQL em docs/automation.sql
- endpoint /api/engine/cron p/ o n8n acionar (CRON_SECRET), avalia, grava
  logs e dispara webhook (N8N_WEBHOOK_URL); modo summary p/ resumo diário
- token de login persistido no callback p/ rodar sem cookie
- aba Atividade agora lê logs reais via /api/engine/logs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 15:43:45 -03:00
59773aa2c4 feat: modal Adicionar Anúncio em 2 colunas + diagnóstico do IG actor
Modal: tamanho 'xl' (920px) e layout em 2 colunas (inputs | criativo),
pra não precisar dar zoom out na tela.

IG: a resolução do instagram_actor_id agora tenta duas fontes (conta de
anúncios E página) e loga o que encontrou ([IGResolve]) — pra diagnosticar
por que o @festamagicaia não está casando e o app cai no Facebook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 15:24:46 -03:00
77f4dba1b2 fix: resolver instagram_actor_id válido p/ Ads + modal largo com scroll
IG: o id que vem da Página (instagram_business_account) é recusado pela
API de Ads (1815199) mesmo com a conta autorizada. Agora resolvemos o
"ator" correto via /act_X/instagram_accounts, casando pelo @username, nos
fluxos de criar campanha e adicionar anúncio.

Modal: .modal-content ganha max-height 90vh + overflow para não quebrar a
tela ao gerar copy/imagem, e tamanho 'lg' (680px) usado no Adicionar
Anúncio, que estava estreito demais.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 15:04:27 -03:00
aebf5bd919 feat: gerar só 1 imagem (quadrada) no criativo por IA
Em vez de gerar 3 imagens por posicionamento (mais caro e dependente da
customização que a Meta vinha recusando), gera só a 1:1 — a Meta adapta
para os demais posicionamentos. Mais barato e usa o caminho de imagem
única + Instagram, que é estável. A customização por posicionamento fica
dormente (só ligaria com 2+ imagens).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 14:35:21 -03:00
8ebbe079ec diag: revelar o motivo de a customização por posicionamento falhar
As 3 imagens sobem, mas a Meta recusa montar o criativo com elas e o app
cai pra 1 imagem silenciosamente. Agora o erro real da Meta é logado
([Placement]) e devolvido na resposta (placement_error), aparecendo na
tela final — pra diagnosticar e corrigir a estrutura do asset_feed_spec.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 14:21:28 -03:00
adc6580848 fix: priorizar imagem única + Instagram sobre as 3 imagens (1772103)
A cascata anterior, ao falhar a customização por posicionamento, podia
derrubar o Instagram e deixar criativo sem IG num ad set que mira IG —
gerando 1772103. Agora: se a customização (asset_feed_spec) falhar, cai
para imagem única MANTENDO o Instagram (caminho comprovado). O IG só é
removido se o próprio criativo de imagem única falhar com erro de IG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 13:08:04 -03:00
58d9825fa5 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>
2026-06-16 13:03:01 -03:00
5dd4c675c4 fix: republicar do histórico mantém público, lance, página e pixel
Ao republicar um rascunho, o retry perdia configurações: público virava
Brasil amplo, Cost/Bid Cap virava Volume Máximo e a página/IG caíam na
primeira da conta.

- rascunho passa a salvar page_id, instagram_actor_id e conversion_event
- retry envia bid_strategy cru (suporta COST_CAP) + bid_amount em centavos
- retry resolve o targeting_template para o objeto de público real
- retry repassa page_id/instagram_actor_id/conversion_event/pixel

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:51:55 -03:00
349203b761 feat: opção de subir a campanha já ativa (no ar)
Antes tudo subia PAUSED por padrão. Agora o pipeline propaga um status
comum para campanha, conjunto e anúncio (os 3 precisam estar ACTIVE para
entregar). A rota aceita activate=true e o Preview ganha um toggle
"Iniciar a campanha já ativa" (default desmarcado = pausada para revisão).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:47:18 -03:00
6068f77b09 feat: usar as 3 imagens por posicionamento (placement customization)
Antes o criativo usava só a imagem quadrada. Agora, quando há >=2 imagens
geradas, monta o criativo com Placement Asset Customization: 1:1 no feed,
9:16 em stories/reels e 1.91:1 na coluna direita — em ad set normal
(não-dinâmico), com object_story_spec mantendo page_id/IG.

Cascata de fallback segura: se a Meta recusar a customização, refaz com a
imagem única (comportamento antigo estável); se recusar o IG, refaz só
com Facebook. Publicação nunca quebra por causa disso.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:40:29 -03:00
87fdacfb3d fix: fallback p/ Facebook quando instagram_actor_id é inválido
O fallback que refaz o criativo só com Facebook só pegava o erro de
permissão (1815199). Agora também cobre "instagram_actor_id must be a
valid Instagram account id", evitando que um IG incompatível (ex: conta
do fluxo de login do Instagram) bloqueie a publicação inteira.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:19:27 -03:00
921eb97483 fix: enviar is_adset_budget_sharing_enabled ao criar campanha
A Meta passou a exigir esse campo explícito quando o orçamento está no
conjunto (sem CBO), senão a criação falha com erro 100/4834011. Default
false: cada conjunto gasta o próprio orçamento.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:44:46 -03:00
6a97012058 fix: revelar erro real do Supabase no histórico de campanhas
Erros do Supabase (PostgrestError) não são Error, então o catch caía no
fallback genérico "Erro ao listar campanhas salvas" e escondia a causa
(tabela ausente, projeto pausado, key inválida). Agora extrai
message/code/details/hint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 11:07:02 -03:00
8bd7377706 feat: melhorar qualidade da copy (modelo full + regras anti-genérico)
- copy passa de gpt-5.4-mini para gpt-5.4 (full), sobrescrevível por
  OPENAI_COPY_MODEL; temperatura 0.9 para texto menos engessado
- prompt ganha bloco "proibido ser genérico": exige detalhe concreto por
  frase, pattern interrupt na 1a linha, variações realmente distintas
- skin festa_infantil: copy_rules descrevem o fluxo self-service real
  (foto -> avatar 3D grátis -> escolher e gerar entre 33 artes; R$9,99 =
  10 créditos) e proíbem "receba/kit pronto", forçando verbos de criação

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 10:32:21 -03:00
0fbae80622 fix: remover instagram_basic dos escopos (login quebrava)
O app na Meta ainda não tem o produto/uso de Instagram habilitado, então
pedir instagram_basic dispara "Invalid Scopes" e impede o login. Volta a
lista de escopos para a que funciona; reincluir após ativar no painel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 09:57:03 -03:00
8dade26695 fix: pedir escopo instagram_basic no login da Meta
Sem instagram_basic, o campo instagram_business_account de /me/accounts
volta vazio e o app mostra "sem Instagram vinculado" mesmo quando há um
IG profissional conectado à página. Requer relogin para aplicar.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 09:41:10 -03:00
a995424725 feat: otimizar app para campanhas de conversão low-ticket
Refina o pipeline de criação de campanhas para produtos de entrada
(ticket baixo, Pix/cartão) com foco em otimização por compra e controle
de custo, evitando prejuízo.

- scraper: lê sites SPA/JS (og tags, JSON-LD com preço/oferta, fallback
  de renderização via r.jina.ai) — antes só lia o <title>
- skins: nova skin "Festa Infantil / Produto de Entrada" com copy-rules
  de tripwire (Pix = acesso imediato, preço-âncora) e default em Vendas
- create: campanha de Vendas exige Pixel/Dataset e otimiza por
  OFFSITE_CONVERSIONS (antes caía para LINK_CLICKS), evento de conversão
  selecionável e estratégia Cost Cap (teto de custo por compra)
- corrige bid_strategy pré-mapeado errado no cliente que anulava o Bid Cap
- settings: persiste Pixel/Dataset ID e pré-preenche no formulário
- copy/analyzer: usam oferta, preço e formas de pagamento; variações A/B
  (preço / benefício / dor) para resposta direta
- creative: opção de estampar preço/oferta no criativo

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 09:27:58 -03:00
9bda154730 style: tighten campaign table spacing so the actions column fits on screen
The duplicate buttons pushed the Ações column past the viewport edge.
Reduce horizontal cell padding (16px -> 10px across all 10 columns) and
tighten the campaign-row action button gap so the full row fits without
horizontal cutoff.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:47:36 -03:00
38f5dc444f feat: duplicate campaigns, ad sets and ads like the Meta Ads Manager
Adds a "Duplicar" button on every campaign, ad set and ad row, mirroring
the native Duplicate in Ads Manager. Uses Meta's /copies endpoint with
deep_copy for campaigns/ad sets (children come along) and always creates
the copy as PAUSED with a " - Cópia" suffix so it's safe to review before
activating. This lets users grow a campaign by cloning: duplicate an ad
for a new creative, duplicate an ad set for a new "subcampanha", or
duplicate a whole campaign.

Backend: copy_campaign/copy_adset/copy_ad tools in the Graph wrapper,
duplicateEntity() helper, and a single POST /api/meta/duplicate route.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:33:24 -03:00
a88e96adf5 fix: fall back to Facebook-only when ad account can't use the page's Instagram
Meta rejects the whole ad creative with error 200/1815199 when the ad
account isn't authorized (in Business Manager) to use the Instagram
account linked to the chosen page. Picking a different page in the new
selector doesn't help if that page's IG is also unshared. Now, when the
creative fails for that specific reason, we retry without
instagram_actor_id so the ad still publishes on Facebook, and the modal
explains why Instagram was dropped and how to enable it.

createFullCampaign gets the same fallback for free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:21:18 -03:00
dcaf7959ac feat: let users pick the Page/Instagram account when adding ads to a campaign
Some ad accounts aren't authorized to use the Instagram account that's
auto-detected from the existing ad set, causing Meta error 200/1815199
on publish. The new selector lists all of the user's connected Pages
(with linked Instagram accounts) so they can choose a valid combination
themselves, falling back to the auto-detected default. Also paginate
/me/accounts so accounts beyond the first page show up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 14:10:06 -03:00
b4ad2e0585 feat: pre-preenche contexto do modal de novo anuncio com a copy existente
A geracao de copy/imagem por IA exigia que o usuario descrevesse o
anuncio do zero. Agora getAdSetDefaultCreative tambem extrai o texto
do criativo de um anuncio ja existente no ad set (headline, mensagem
e descricao) e o AddAdModal usa isso para preencher automaticamente
o campo de contexto, permitindo gerar variacoes no mesmo tom sem
digitar nada.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 13:18:41 -03:00
d2406f0152 feat: permite adicionar novos anuncios a campanhas ja ativas
Adiciona modal "+ Anuncio" na tabela de campanhas que reaproveita o
fluxo de geracao de copy/imagem por IA para publicar novos criativos
no mesmo ad set existente, mantendo orcamento e segmentacao.

- Extrai pipeline de upload+criativo+anuncio (addAdToAdSet) do
  createFullCampaign para reuso
- Adiciona get_adset_default_creative para pre-preencher pagina,
  link, instagram e CTA com base em anuncio ja existente no ad set
- Novas rotas POST /api/adsets/[id]/ads e
  GET /api/adsets/[id]/creative-defaults
- Novo componente AddAdModal com geracao de copy/imagem via IA ou
  upload manual

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 12:54:00 -03:00
f47c9e58ce fix: resolve OAuth redirects dynamically using client-facing headers 2026-06-07 22:01:52 -03:00
568fb16a89 Atualizar src/app/api/auth/callback/route.ts 2026-06-08 00:49:23 +00:00
348723f39f Atualizar src/app/api/auth/meta/route.ts 2026-06-08 00:48:16 +00:00
61b5303ee5 Atualizar src/app/api/auth/meta/route.ts 2026-06-08 00:41:22 +00:00
d5997bb0d8 Atualizar src/lib/engine/monitor.ts 2026-06-07 23:58:51 +00:00
Marcio Bevervanso
234314d1c6 Publish MetaAds Pro: AI-driven Meta Ads campaign management dashboard
Full app with AI campaign creation/copy/creative generation, dashboard,
campaign automation engine, Meta OAuth login, and a redesigned landing page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 19:30:33 -03:00
Marcio Bevervanso
b955aee644 Initial commit from Create Next App 2026-05-07 17:04:31 -03:00