Dashboard e Pages Functions¶
Frontend React (Vite) publicado no Cloudflare Pages, protegido por Cloudflare Access. Não tem banco próprio: lê o KV VEGGI_DATA que o robô preencheu.
| Item | Valor |
|---|---|
| Projeto Pages | veggi-meta |
| Domínio oficial | https://dashmeta.grupoveggi.com.br |
| Build | npm run build (Vite) → pasta dist/ |
| Login | Cloudflare Access — team veggidocs.cloudflareaccess.com |
| Dependências | react, react-dom, recharts — só três |
A porta dos fundos está fechada¶
functions/_middleware.js só deixa passar o host dashmeta.grupoveggi.com.br. Qualquer acesso por veggi-meta.pages.dev ou por URL de preview recebe 403.
Nunca remova o _middleware.js
É ele que impede os dados de vazarem pela URL pública do Pages, que não tem login. Sem ele, os números da operação ficam abertos na internet.
Pages Functions¶
| Arquivo | Rota | O que faz | Secret |
|---|---|---|---|
_middleware.js |
(todas) | Porteiro: só o domínio oficial passa | — |
api/data.js |
GET /api/data |
Serve o KV latest |
— |
api/ad-toggle.js |
POST /api/ad-toggle |
Liga/desliga anúncio, conjunto ou campanha na Meta. Body {id, status}. Exige o header Cf-Access-Jwt-Assertion |
META_TOKEN |
api/refresh.js |
POST /api/refresh |
Botão "🔄 Atualizar agora" — dispara o robô sem esperar o cron | UPDATE_KEY |
O app chama /api/data na mesma origem, então a chamada passa pelo Access. Fallback local: /data.json.
O UPDATE_KEY do Pages é outro cofre
Existe um secret de mesmo nome no Worker robô. São dois cofres distintos e precisam do mesmo valor. Se o botão "Atualizar agora" responder erro, é este que falta:
Atalho: definir-chave-dashboard.bat.
As telas¶
| Arquivo | Tela | Régua |
|---|---|---|
src/App.jsx (1.179 linhas) |
Abas B2B: Resumo · Gráficos · Campanhas · Anúncios · Recomendações | Negociação no CRM |
src/B2C.jsx (1.852 linhas) |
Mundo B2C completo, independente | Pedido faturado na VTEX |
src/diario.jsx |
Aba Diário — o que mudou nos últimos 7 dias | Degradação, não retorno |
src/Saldo.jsx |
Cartão de saldo da conta + projeção de duração | Usado pelos dois mundos |
src/ui-perf.jsx |
Peças compartilhadas (gráficos, sparkline, leitura de público) | — |
src/lib/analytics.js |
Normalização e classificação — usada também pelo robô | — |
src/lib/diario.js |
Régua do Diário: fadiga, público, estrutura (lógica pura) | — |
A aba Anúncios tem sub-abas: 🌳 Estrutura (árvore campanha→conjunto→anúncio com botões pausar/ativar), 🎯 Por conjunto, 📊 Por anúncio (ranking com semáforo ciente do objetivo) e 📈 Gráficos. Filtros globais: Conta, Campanha, Status, Período. Tema claro/escuro.
A aba Diário tem régua própria¶
O Diário não olha dinheiro
Com ciclo de venda de 15 a 20 dias, uma semana não tem tempo de mostrar venda. O Diário existe para ver degradação (criativo, público, estrutura). Retorno é a aba Anúncios.
Decisões de projeto que parecem estranhas e não são:
- Janela fixa de 7 dias contra os 7 anteriores, terminando ontem. Não usa o filtro de período do topo. Hoje está incompleto, e a Meta reajusta os números de um dia por até ~72h.
- Frequência só existe em janela fechada. Pedir
frequencycomtime_increment: 1devolve impressões÷alcance de um dia — quase sempre ~1,0, ou seja, inútil. Por isso são duas chamadas separadas,DAILY_FIELDSeJANELA_FIELDS. Não juntar as duas. - Abaixo do piso de volume, o painel diz "não dá pra concluir" em vez de mostrar variação percentual bonita e falsa. Cada mexida relevante num conjunto reinicia o aprendizado da Meta.
- Frequência ≥ 3 vale sozinha. Nesse patamar a Meta já ficou sem gente nova. Vira "Público saturado", e a ação é ampliar o público, não trocar criativo.
As quatro hipóteses do Diário¶
As ações são opostas entre si, por isso a distinção importa:
| Hipótese | Sinais | Ação |
|---|---|---|
| Criativo reprovado | Não converte, mas os irmãos do mesmo conjunto convertem | Troca a peça |
| Público ruim | Não converte e os irmãos também não | Mexe na segmentação ou pausa |
| Criativo fadigando | Converte, frequência subiu e CTR caiu | Peça nova com a mesma promessa |
| Público pra renovar | Converte, frequência subiu e CTR firme | Amplia o público, não troca o criativo |
As duas primeiras só se distinguem olhando os vizinhos — nenhuma métrica do próprio anúncio separa. Anúncio sozinho no conjunto: o painel admite que não sabe e ensina o teste, em vez de chutar.
Deploy¶
cd "C:\Projetos\veggi-ads-dashboard"
npm run build
npx wrangler pages deploy dist --project-name=veggi-meta --branch=main --commit-dirty=true
Atalho: publicar-online.bat. Depois, F5 com Ctrl+Shift+R no domínio oficial.
Diagnóstico¶
| Sintoma | Causa provável e ação |
|---|---|
| Dashboard abre mas sem dados | O robô não rodou ou falhou. Ver Robô updater e conferir a chave latest no KV |
| Erro 403 ao abrir | Acesso por veggi-meta.pages.dev ou URL de preview. Use o domínio oficial — é o _middleware.js funcionando |
| Botão "Atualizar agora" dá erro | Falta o secret UPDATE_KEY no Pages (cofre diferente do Worker). Rodar definir-chave-dashboard.bat |
| Pausar/ativar anúncio não funciona | META_TOKEN do Pages inválido ou sem escopo ads_management |
| Aba Diário vazia, resto OK | A série diária roda em bloco try próprio de propósito: se a Meta falhar ali, só o Diário fica sem dado |
| Mudança publicada não aparece | Cache do navegador. Ctrl+Shift+R. Se persistir, conferir Implantações no painel do Pages |
| Aba B2C sem pedidos, mas com gasto | Anúncios criados à mão no Gerenciador nascem sem UTM. Só os criados pelo Consultor já vêm etiquetados |