Ir para o conteúdo

Radar

O Radar de Oportunidades é um scorer de oportunidades multivariado, sincronizado com a nuvem, para produtos descobertos em um marketplace (ClickBank Marketplace). Ingere snapshots de marketplace continuamente e pontua cada produto num único Opportunity Score entre 0 e 100, para que operadores ranqueiem o que vale receber tráfego.

Não existe API de afiliado para listagem automática. O ClickBank não expõe GET /products/list para afiliados — products-v2.json é seller-only. O feed automatizado server-side (online_feed via MARKETPLACE_FEED_URL) é um stub que registra skipped_no_source até que o ClickBank exponha arquivo autenticado. O caminho oficial para inteligência real é o agente de captura no servidor do operador (Chrome logado, diário, ~1,2k ofertas — docs/operations/capture-agent-linux.md), com o browser scraper assistido e o import CSV/JSON manual como alternativas. Ver docs/integrations/clickbank.md § Fontes (verificado 2026-08-20/23).


O que faz

  • Cloud sync — sincroniza o marketplace online em background, mantendo o radar sempre atualizado sem refresh manual.
  • Opportunity Score multivariado — combina vários sinais num único score 0–100:
  • Gravity — o indicador de demanda do marketplace.
  • Payout inicial — quanto se pode ganhar por conversão.
  • Quality tier — classificação de confiança do produto pela plataforma.
  • Marcos de payout — elegibilidade e progressão em limiares de payout.
  • Gravity sweet spot — produtos são destacados quando a gravity cai na faixa 20–180, equilibrando tração e administrabilidade.

Fórmula do Opportunity Score (v3, determinística)

radar-opportunity-v3.0.0 (packages/integrations/src/clickbank/opportunity-score.ts). A IA nunca calcula este score; tudo é função pura das evidências:

Componente Pontos Fontes (sem dupla contagem)
Economia 0–22 Payout primário = inicial (ou médio quando inicial ausente); payout médio só adiciona bônus fixo de upside (+2) quando corrobora valor superior
Recorrência/rebill 0–5 recurring_payout > 0
Gravity fit 0–15 Bandas: sweet_spot 20–180 → 15; competitive 181–350 → 9; developing 10–19 → 7; unvalidated 1–9 → 2; hipercompetitiva >350 → 3; gravity 0/ausente → 0 (GRAVITY_ZERO_NO_EVIDENCE)
Qualidade do funil (+JV tools) 0–15 vsl/tsl/checkout_direct/hybrid + bônus por affiliate tools
Adequação ao canal 0–15 traffic_fit weak/moderate/strong
Potencial criativo 0–10 creative_potential
Compliance −10 a 10 LOW 10 · MEDIUM 5 · HIGH/UNKNOWN 0 · VERY_HIGH −10
Tendência 0–8 up/stable/down
Busca Tier-1 0–7 tier1_search_share

score, completeness e confidence são conceitos separados: completude = evidências conhecidas ÷ 14; confiança = peso ponderado ÷ 123. Dados ausentes reduzem completude/confiança — nunca viram zero saudável. Cada score carrega reason codes determinísticos (ex.: INITIAL_PAYOUT_HIGH, GRAVITY_SWEET_SPOT, AVG_PAYOUT_UPSIDE_BONUS) exibidos na linha expandida do Radar.

Canal recomendado (reason codes)

classifyRecommendedChannel é uma regra ordenada e pura sobre GOOGLE_SEARCH · META · YOUTUBE · NATIVE:

  1. Compliance HIGH/VERY_HIGH → NATIVE (CHANNEL_NATIVE_COMPLIANCE_RISK);
  2. Funil VSL/TSL com payout primário ≥ 40 → YOUTUBE;
  3. Checkout direto com evidência de intenção de busca → GOOGLE_SEARCH fundo de funil;
  4. Evidência de intenção de busca sem funil de vídeo → GOOGLE_SEARCH;
  5. Potencial criativo forte → META;
  6. Default conservador → META.

O canal fica persistido em score_breakdown.recommendedChannel com os reason codes em channelReasonCodes. Compliance é detectado deterministicamente (detectComplianceRisk: categoria/subcategoria + termos sensíveis no nome — termos elevam um nível, nunca reduzem).


KPIs de resumo (determinísticos)

KPI Definição
Produtos no Radar Total de snapshots trackeados no workspace.
Média Opportunity Score Média dos opportunity_score, arredondada a inteiro, /100.
No Sweet Spot (20-180) Contagem de snapshots com 20 ≤ gravity ≤ 180.
Maior Payout Inicial Máximo dos initial_payout (USD).

O HopLink de afiliado é reconstruído deterministicamente a partir do par (nickname do workspace, vendor da oportunidade) — nunca reaproveitado de URLs importadas. O nickname fica em bv_affiliate_network_settings (rede clickbank, 5–10 caracteres alfanuméricos) e pode ser configurado em:

  • Conexões (primeiro item do checklist, card "Redes de Afiliados");
  • Radar — o chip de status no topo mostra Afiliado ClickBank: "nick" ou abre o modal rápido ao clicar. Clicar em Copiar HopLink sem nickname configurado abre o mesmo modal e, após salvar, copia o link imediatamente.

Layout da página Ofertas (Radar)

A página (menu Ofertas) prioriza escolher e lançar:

  1. Header compacto + KPIs;
  2. Status do agente de captura (último sinal, completa/parcial, nº de ofertas, ou a ação necessária — ex.: "Sessão do ClickBank expirou");
  3. Banner da última sincronização: ignora runs skipped_no_source, marca capturas parciais e mostra erros de leitura e linhas inválidas (nunca some com dados em silêncio);
  4. Tabela com filtros e paginação. Primeira ação de cada linha: Lançar (ou Continuar quando já existe uma preparação aberta para a oferta); Copiar HopLink e Espionar ficam ao lado. A linha expandida (Card de Inteligência) tem o mesmo botão único;
  5. Abaixo da tabela, recolhidos: Histórico de capturas e Motor de Decisão (SHADOW).

A leitura pagina em lotes de 1.000 (.range(), ordem opportunity_score desc, id asc) — o catálogo inteiro aparece, sem o corte de 1.000 linhas do PostgREST (apps/web/src/lib/radar/load-radar-data.ts).


Captura do Marketplace

Caminhos de entrada

Caminho Rota Autenticação
Agente diário (servidor Linux/Mac) POST /api/agent/capture/import (+ /report, /ping) token bvcap_… do agente (Conexões)
Agente antigo POST /api/cron/marketplace-capture-import CRON_SECRET (só com um workspace)
Upload pelo navegador (dialogs de captura/import) POST /api/radar/capture-import sessão do operador (sem o limite de 1 MB de Server Action)

Todos usam o mesmo handler (lib/capture-agent/import-handler.ts): recalcula o hash canônico, aplica a política de parcial (aceita com ≥ 100 itens e ≥ 50% da última completa; upload manual sempre aceita), grava o run e registra toda recusa como run failed com motivo (que dispara o aviso no Telegram).

Modos do dialog

O dialog "Capturar do Marketplace" oferece dois modos (repassados ao driver via bridge POST /start {mode,pages} e injetados como window.__bvConfig):

Modo Comportamento
Catálogo completo Varre todas as páginas (~1.250 ofertas) + passada por categorias para enriquecimento. Recomendado 1×/dia.
Top oportunidades (top) Só as primeiras N páginas do ranking (1/2/4/10 ≈ 50–500 itens), sem passada por categorias. Sincronização ultrarrápida.

Checkbox adicional client-side: importar somente Sweet Spot (gravidade 20–180) — filtro determinístico aplicado antes do server action.

Captura resiliente (Fase 1)

  • Normalização testável: strings, números (1,234.56 e 1.234,56), URLs e registros passam pela unidade compartilhada packages/integrations/src/marketplace/normalize.ts — reutilizada pelo dialog, pelo import manual e pelo server action autoritativo; o bloco embutido no scraper é pinado por contrato (scraper-normalize.contract.test.ts). Ausência de evidência permanece null/undefined — nunca zero saudável.
  • Retry & completude: até 3 tentativas por página com backoff exponencial + jitter (no driver, no bridge POST e na paginação DOM). Páginas tentadas, concluídas e perdidas são registradas; capturas com páginas perdidas terminam com status partial, nunca sucesso silencioso.
  • Envelope de captura: expectedPages, completedPages, lostPages, itens recebidos/válidos/inválidos, status complete|partial, URL de origem, timestamp e hash canônico (sha256 sobre itens ordenados por identidade — independente da ordem). O servidor recalcula o hash e rejeita envelope alterado.
  • Proveniência: cada snapshot persiste vendor_domain, source_url, capture_status e capture_meta; a trilha fica em bv_marketplace_sync_runs (status partial para capturas incompletas).
  • UX: o dialog segue a máquina de estados bridge → capturing → review → imported. A fase de revisão mostra percentual real, página atual/total, válidos/ inválidos, páginas perdidas, falhas sanitizadas e hash resumido. Captura parcial exige confirmação explícita antes de habilitar a importação; reimportar não duplica (upsert idempotente por rede+identidade+dia).

Correção de paginação (2026-08): leitura multilíngue do total (results/resultados, formato MUI x-y of/de z) e seletores resilientes de "próxima página" (EN/PT + MUI TablePagination + KeyboardArrowRight). Parser puro testado em packages/integrations/src/clickbank/marketplace-pagination.ts.


Heurísticas de Seleção Cirúrgica de Produtos (5 Minutos)

Para selecionar produtos com alta probabilidade de lucro e menor risco de queima de capital, o Radar adota as seguintes regras de validação:

  1. Curva de Volume vs Tempo (Google Trends & Keyword Planner):
  2. Produtos em Ascensão / Platô Estável: Alta prioridade. Ofertas com buscas crescentes ou consolidadas no topo geram conversões consistentes.
  3. Produtos em Queda / Curva de Morte: Evitar. O leilão de CPC continua caro enquanto o volume de vendas desaba.
  4. Filtro de Tráfego de Compradores vs Ruído de Afiliados:
  5. Descontar buscas originadas no Brasil ou países não-compradores (geralmente afiliados espionando a oferta).
  6. Validar se o volume de buscas está concentrado nos países Tier-1 (EUA, Canadá, Reino Unido, Austrália).
  7. Sweet Spot de Gravidade (20 a 180):
  8. Gravidade < 10 (ou zero/ausente): Sem validação comprovada no marketplace — nunca tratamento saudável.
  9. Gravidade 20 a 180 (Sweet Spot): Validação real de mercado, alta conversão e leilão de CPC acessível.
  10. Gravidade 181 a 350: Concorrida — CPC sobe, exigência de diferenciação maior.
  11. Gravidade > 350: Hiperconcorrência, saturação de criativos e CPC inflacionado.
  12. Unit Economics & Calculadora de Breakeven CPC:
  13. $\text{Breakeven CPC} = \text{Payout Inicial} \times \text{CVR Estimado (1.5\%)}$.
  14. $\text{Lance Alvo (Target CPC Max)} = \text{Breakeven CPC} \times 0.60$ (para garantir 40% de margem de lucro líquido).
  15. Classificação de Funil & Recomendação de Presell:
  16. Identifica se o produtor usa VSL, TSL ou Checkout Direto, e indica automaticamente o template ideal (zero-fuga-popup, product-bundles ou review).

O Opportunity Score Determinístico

Cada snapshot em bv_marketplace_snapshots carrega:

Campo Significado
gravity Demanda e momentum do marketplace (0/ausente = banda unknown).
initial_payout Comissão da primeira compra (USD).
avg_payout Payout médio por venda — evidência distinta, sem dupla contagem com o inicial.
recurring_payout / rebill_rate Potencial de faturamento recorrente.
avg_percent_per_sale Comissão média percentual.
opportunity_score + score_breakdown Score total (0-100), Breakeven CPC, Presell Recomendada, canal recomendado e reason codes.

Conversão Radar → Oferta enriquecida (Fase 3)

Salvar a oferta (automático no Lançar, ou pelo menu da linha) executa em um fluxo:

  1. valida snapshot + workspace no servidor (recarrega a linha — não confia em dados do browser);
  2. cria a oferta de forma determinística e idempotente por produto (offers.marketplace_identity_key = external_offer_id ou vendor, em minúsculas) — capturas diárias geram snapshots novos, mas a oferta é a mesma;
  3. gera HopLink ClickBank ou link rastreável sem expor secrets;
  4. dispara o enriquecimento IA estruturado;
  5. persiste avatar (dores/desejos/obstáculos), mecanismo único, promessa principal, ângulos e restrições de compliance;
  6. registra modelo, auditoria e status.

A falha da IA não desfaz nem corrompe a oferta: ela fica com enrichment_status='failed', erro sanitizado em enrichment_error e botão "Tentar enriquecimento novamente" no card Brief Estruturado da Oferta. Colunas novas: jv_page_url, affiliate_terms_url, official_domain, sales_page_url, tracking_link_template, avatar, core_mechanism, main_promise, angles, compliance_restrictions, enrichment_status, enrichment_model, enriched_at, enrichment_error (migration 20260824010000_brandvelia_offer_enrichment.sql, additive-only, ainda não aplicada ao banco remoto).

CTA principal: Lançar — salva a oferta se preciso, cria ou retoma a preparação aberta da mesma oferta (start_launch, nunca duplica) e abre /app/campaigns/wizard?launch_id=<uuid>. Com preparação aberta o botão vira Continuar. "Espionar" também termina em Lançar, levando os anúncios gerados para o passo 3.


Painel do Motor de Decisão (SHADOW)

O Radar embute o painel Motor de Decisão (SHADOW):

  • Capital materializa o snapshot de capital do workspace (S0/Cp/L/Ca, fórmula capital/v1). Inputs desconhecidos produzem Ca = null + motivo — o painel mostra gate e motivos, nunca um zero falso.
  • Scores v2 calcula o Opportunity Score v2 (opportunity/v2) em shadow: amostra apenas cohorts cuja janela de refund fechou; pesos fixos (50% cobertura de conversão + 50% economia líquida normalizada, saturação USD 1.000). Resultados vão para snapshots imutáveis com hash estável.
  • Alertas determinísticos: alertas replay-safe derivados de fatos (ex. CAPITAL_BLOCKED, ATTRIBUTION_UNKNOWN) com severidade e reason codes.

Todos os números vêm de materializações SQL; a UI nunca calcula dinheiro. Veja Motor de Decisão.