4

Pitch: Como construí um ad server em Bun e Cloudflare Workers (<5KB e CLS Zero) para monetização direta no Brasil

Fala, pessoal do TabNews!

Quem mantém um blog técnico, portal regional ou ferramenta web gratuita no Brasil conhece bem o dilema de monetização: ou você enche a página de scripts pesados do AdSense para ganhar centavos de dólar (destruindo o Core Web Vitals e a experiência do leitor), ou tenta vender patrocínio direto.

O problema é que, quando você fecha um patrocinador direto (uma empresa local, uma SaaS do seu nicho ou uma escola tech), a gestão costuma ser no improviso:

  1. Você sobe um .png direto no código ou no WordPress (<img> com link estático).
  2. Se tiver dois patrocinadores dividindo o mesmo espaço, precisa improvisar um sorteio no front-end ou no servidor.
  3. Quando a campanha vence no domingo à meia-noite, você precisa lembrar de remover o banner na mão.
  4. No fim do mês, o anunciante pergunta "Quantas pessoas viram e clicaram no meu banner?" — e você precisa mandar print do Google Analytics (quando o adblocker não bloqueou tudo ou o evento foi configurado direito).

Para resolver essa dor sem precisar subir uma infraestrutura mastodôntica como o Google Ad Manager ou manter uma instância de Revive Adserver, construí o DirectAd.

Quero compartilhar aqui como pensei a arquitetura para manter o custo próximo de zero e a performance no limite do Edge, além de ouvir o feedback técnico de vocês.


A Arquitetura: Bun + Hono no Cloudflare Edge + Web Components

A premissa principal era inegociável: o widget não podia degradar a nota do Lighthouse nem causar Layout Shift (CLS).

Estruturei o projeto como um monorepo em Bun dividido em duas pontas:

1. O Widget (<ds-widget>) com < 5KB e CLS Zero

Em vez de injetar iframes pesados ou dezenas de kilobytes de JS, o embed é um Web Component nativo (<ds-widget>) compilado via esbuild em um único arquivo minificado.

  • Ele usa Shadow DOM para isolar totalmente o estilo do banner do CSS do site hospedeiro.
  • Antes mesmo da imagem baixar, o componente reserva a proporção exata do preset configurado (728x90, 300x250, 970x250, 320x100 ou 320x50), garantindo CLS zero.
  • Renderiza uma tag <picture> nativa com suporte a criativo específico para desktop e mobile (media="(max-width: 639px)"), fazendo fallback inteligente caso o anunciante envie apenas uma peça.

Para colocar no ar em qualquer stack (Next.js, Astro, WordPress, Ghost ou HTML puro), basta colar uma linha:

<script src="https://cdn.directad.com.br/embed.js" async></script>
<ds-widget slot-id="seu-slot-id"></ds-widget>

2. Entrega no Edge com Cloudflare Workers, KV e R2

A rota que decide qual banner exibir não bate no banco relacional em tempo de requisição:

  • Quando o dono do site altera um banner, peso ou agendamento no painel, sincronizamos um snapshot enxuto (SlotSnapshot) direto no Cloudflare KV, e os criativos ficam no Cloudflare R2 servidos com Content-Type estrito + X-Content-Type-Options: nosniff.
  • O Worker (escrito em Hono) lê o snapshot do KV no Edge mais próximo do visitante, filtra campanhas ativas (start_date / end_date) e faz a seleção ponderada (weighted random) em sub-milissegundos. Se você vendeu 70% da voz do topo para o Patrocinador A e 30% para o Patrocinador B, o próprio Edge equilibra a entrega.
  • Segurança no clique e nos uploads: Validamos os magic bytes reais de cada imagem no upload (bloqueando SVGs maliciosos ou extensões falsas), filtramos bots conhecidos via User-Agent para não inflar métricas e blindamos o redirect de clique contra Open Redirect (a targetUrl vem estritamente do snapshot no KV, nunca de query params da requisição).
  • A contabilização de impressões usa navigator.sendBeacon no cliente e ctx.waitUntil no Worker para processar os eventos em background, sem travar a resposta do usuário.

3. Prestação de Contas sem Fricção (Relatório Público)

A parte que mais ajuda a renovar contratos com anunciantes diretos é a transparência. Cada espaço gera um link público protegido por token (report_token de 128+ bits). Você manda esse link no WhatsApp ou e-mail do seu patrocinador e ele acompanha em tempo real as impressões, cliques únicos, CTR médio e o gráfico diário — sem precisar criar login e senha.


Modelo e Teste Gratuito

O projeto já está no ar em directad.com.br.

Deixei um plano Free permanente (com até 2 espaços ativos, criativos ilimitados por slot, rotação por peso, agendamento e link público de relatório, apenas com um selo discreto "Powered by DirectAd" de 16px dentro do Shadow Root). Para quem gerencia portais maiores ou precisa de 100% white-label + até 10 slots e exportação CSV/PDF para faturamento, o plano Pro custa R$ 29/mês (via Pix).

Se você tem um blog, newsletter com versão web, documentação open-source ou portal de conteúdo e quiser testar o <ds-widget> na prática, adoraria saber como foi a experiência de instalação e ouvir críticas sobre a abordagem técnica!

Carregando publicação patrocinada...
2

Sobre o relatório pro anunciante: se a impressão é contada quando o widget renderiza, o banner do rodapé conta igual ao do topo, mesmo que ninguém role até lá. Dá pra disparar o beacon só quando um IntersectionObserver indicar que pelo menos metade do banner ficou visível por 1 segundo, que é o critério de impressão visível da IAB. O número fica menor, mas fica bem mais fácil de defender.

Outro ponto é o KV. Escrita lá pode levar uns 60 segundos ou mais pra aparecer em outras regiões, então tirar do ar um criativo errado não é instantâneo. Vencimento de campanha não sofre com isso porque a data de fim já é checada no Worker.