Componentes embebidos
Abrir a adPluga dentro da sua aplicação
A sua equipa carrega num botão do seu admin e cria campanhas, anúncios e espaços sem sair de lá. O ecrã é nosso, a moldura é sua, e ninguém faz login dentro da janela.
Como funciona
São dois passos. O seu servidor pede uma sessão com a chave de integração; o browser abre-a num diálogo, já autenticada. O utilizador nunca vê um ecrã de login — e é de propósito: um formulário de login dentro de uma janela de outro site é indistinguível de uma burla, e a sessão do adPluga também não viaja para lá. Por isso a autenticação fica no seu servidor, onde a chave está segura, e a janela só mostra o ecrã já pronto a usar.

- O segredo é de uso único e dura 5 minutos. Peça-o quando a pessoa carregar no botão, não no carregamento da página.
- A página só aceita ser enquadrada pela origem que declarou. Outra origem é recusada pelo browser.
- O ecrã não pode fazer mais do que a chave: os âmbitos dela mandam, e facturação, carteira, pagamentos e a gestão de chaves estão fora de alcance.
Passo 1 — o seu servidor pede a sessão
Do lado do servidor, com a chave de integração. Nunca do browser: a chave não pode sair do seu backend.
curl -X POST https://api.adpluga.com/v1/embed/sessions \
-H 'Authorization: Bearer ak_live_•••' \
-H 'Content-Type: application/json' \
-d '{"component":"campaign_create","origin":"https://admin.YOUR_COMPANY.com"}'
# {
# "client_secret": "cs_•••",
# "url": "https://api.adpluga.com/embed/campanha/?cs=cs_•••&mode=live",
# "expires_at": "2026-01-01T12:05:00Z"
# }Devolva o client_secret e o url ao seu frontend. O url já leva o segredo e o ambiente.
Passo 2 — o browser abre o diálogo
Uma linha de script e uma chamada. O diálogo ajusta-se sozinho à altura do conteúdo e ocupa o ecrã inteiro no telemóvel.
<script src="https://cdn.adpluga.com/v1/embed.js"></script>
<script>
async function abrir(component) {
const r = await fetch("/api/adpluga/session", {
method: "POST",
body: JSON.stringify({ component }),
});
const s = await r.json();
AdPlugaEmbed.open({
url: s.url,
clientSecret: s.client_secret,
onDone: (r) => console.log("created", r),
onClose: () => console.log("closed"),
});
}
</script>Os três componentes
Cada componente pede os âmbitos de que precisa. Uma chave sem eles recebe 403 ao criar a sessão, não a meio do ecrã.
campaign_create — precisa de campaign:write
O formulário completo de campanha: objectivo, modelo de preço, lance e orçamento, calendário, geografia, dispositivos e categorias. No plano gratuito explica que o lance ordena e ainda não gasta.

ad_create — precisa de campaign:read, ad:write, asset:read e asset:write
Escolhe a campanha, o tipo de criativo (imagem, HTML5, nativo, template, vídeo, rewarded, carrossel, áudio) e o formato IAB. O carregamento do ficheiro acontece dentro do diálogo e o anúncio sai para moderação.

slot_create — precisa de property:read e slot:write
O espaço onde o anúncio aparece: a propriedade a que pertence, um nome, o formato e o tamanho IAB. Uma propriedade ainda não verificada é oferecida à mesma — serve em modo de teste até o domínio ser verificado.

Eventos de volta para si
O diálogo fala com a sua página por postMessage. O carregador já trata do resize e do fecho; onDone entrega-lhe o que foi criado.
{ "source": "adpluga", "type": "ready" }
{ "source": "adpluga", "type": "resize", "height": 1240 }
{ "source": "adpluga", "type": "done", "entity": "campaign", "campaign_id": "…", "name": "…" }
{ "source": "adpluga", "type": "done", "entity": "ad", "ad_id": "…", "campaign_id": "…", "status": "in_review" }
{ "source": "adpluga", "type": "done", "entity": "slot", "slot_id": "…", "name": "…" }
{ "source": "adpluga", "type": "close" }Se ligar o listener à mão, compare sempre event.origin com a origem da adPluga antes de acreditar na mensagem.
Teste e produção
O prefixo da chave decide: uma ak_test_ escreve em modo de teste — não cobra, não consome quota, não conta para as métricas — e o diálogo diz isso na cara, com um selo e uma nota. O modo fica gravado no token que a página usa, por isso não há cabeçalho nem parâmetro que o mude.
Mapear um admin de promoções para a adPluga
Quem já gere campanhas do seu lado raramente tem os mesmos nomes. Esta é a correspondência que verificámos contra a API real, campo a campo.
| No seu admin | Na adPluga |
|---|---|
| Nome da campanha | name na campanha (até 120 caracteres) |
| Objectivo | objective: traffic, awareness ou conversions |
| Tipo de campanha (banner) | pricing_model: CPM, CPC, CPA ou CPL, com bid_cents. A moeda é sua: currency aceita AOA. |
| Período da campanha | starts_at e ends_at na campanha. O anúncio não tem janela própria — herda a dela. |
| Audiência alvo (VIP, sem compra há 30 dias…) | Audiências first-party: crie em /v1/audiences, empurre os membros, e refira em targeting.audiences.first_party_include. |
| Posição na app (home topo, categoria…) | Um espaço por posição. A campanha aponta-lhes em targeting.slots, por id ou por nome. |
| Formato (1200×400, 800×400, 600×600) | width e height no anúncio, livres até 8192. Não tem de usar tamanhos IAB. |
| Até 4 imagens no mesmo banner | type: carousel com 2 a 10 slides. Um leilão, uma impressão, um destino — deslizar não gasta decisões. |
| Texto alternativo | alt_text no anúncio. É o que o leitor de ecrã anuncia em vez da imagem. |
| Prioridade de exibição | bid_cents: o leilão ordena por eCPM, portanto um lance maior aparece primeiro. |
| Limite de utilizações | targeting.freq_cap.per_user_per_day limita por pessoa e por dia; budget_total_cents limita o total. |
| Estado (activa, agendada, pausada) | status da campanha mais a janela: agendada é activa com starts_at no futuro. |
O que fica do seu lado: desconto, cashback e pontos são mecânicas da sua promoção, não do servidor de anúncios; push, e-mail e SMS são canais seus — a adPluga entrega o banner. O identificador interno e a descrição também ficam consigo, porque não os guardamos.
O que garantimos
- O segredo é gasto na primeira troca. Uma segunda tentativa com o mesmo segredo devolve 401.
- O token da página vive em memória e nunca é gravado em cookie nem em storage, por isso fechar o diálogo esquece-o.
- A política de enquadramento é construída por sessão: só a origem que indicou consegue mostrar a página.
- O token está preso aos âmbitos da chave. Mesmo sendo um token de sessão, é recusado em qualquer rota que a chave não abrisse.