Postbacks, pixels e image tags: só um deles serve para pagar comissão
Três mecanismos para reportar uma conversão, descritos de um jeito que quem não é engenheiro consegue segurar, mais as seis maneiras como integrações realmente quebram. Escrito para operadores e gerentes de afiliados técnicos que já depuraram isso às onze da noite.

Uma conversão pode ser reportada de três jeitos: uma image tag, um pixel JavaScript ou um postback servidor a servidor. Só o postback se sustenta bem o bastante para pagar comissão em cima dele, porque não depende da cooperação do navegador do jogador. A maior parte das integrações que «não rastreiam» não são postbacks quebrados, são identificadores de clique ausentes no registro do jogador.
A ligação sempre vem numa hora ruim. Um gerente de afiliados tem um parceiro ameaçando cortar o tráfego, o operador jura que a integração está no ar, e o painel diz zero. Alguém manda um print de uma tag no rodapé da página de depósito concluído e pergunta por que não está funcionando.
Não está funcionando porque é uma tag no rodapé de uma página.
Reportar uma conversão é um problema pequeno com muitas maneiras de dar errado, e as maneiras não mudaram muito em dez anos. O que mudou é que dois dos três mecanismos deixaram de ser confiáveis em silêncio enquanto todo mundo continuava entregando os três. Este texto é o que se entrega ao seu engenheiro antes da integração, não depois.
Três maneiras de dizer que um jogador depositou
A image tag. A mais velha. A sua página inclui uma imagem de um pixel cuja origem é uma URL da plataforma de rastreamento. O navegador tenta carregar a imagem, essa requisição chega na plataforma, e a requisição em si é a mensagem. Nenhuma imagem é realmente necessária, a busca é o ponto. Ela não exige nada além de HTML, e é por isso que sobreviveu tanto em sistemas de template onde ninguém queria encostar em JavaScript.
O pixel JavaScript. Mesma ideia com um script no lugar de uma imagem. Um trecho roda na página, junta um pouco de contexto e dispara a chamada. É mais flexível: consegue ler um valor que a página colocou numa variável, consegue esperar uma confirmação renderizar, consegue passar um valor de depósito que só era conhecido em tempo de execução. Também é mais frágil, porque depende de o script carregar, de a variável existir e de a página não ter dado erro acima dele.
O postback servidor a servidor. Sem navegador nenhum. Quando o seu backend registra o evento que importa, ele faz uma requisição HTTP para uma URL, carregando o identificador que recebeu quando o jogador chegou. O seu serviço de pagamentos confirma um depósito, o seu sistema grava a transação, e em algum ponto desse mesmo caminho sai uma requisição dizendo: este jogador, este evento, este valor, esta moeda.
É essa a ideia inteira. Parece menos esperta que as outras duas, e é exatamente por isso que ela se sustenta.
Por que duas das três deixaram de ser confiáveis
Não existe uma causa única. Existe uma pilha delas, e cada uma sozinha seria sobrevivível.
Safari e Firefox bloqueiam cookies de terceiros por padrão, e o Firefox ainda bloqueia requisições para domínios da sua lista de rastreadores. O Chrome continua permitindo cookies de terceiros, então no Chrome o bloqueio vem do bloqueador de anúncios e não do navegador. O Safari ainda limita quanto tempo o armazenamento escrito por script sobrevive, em alguns casos a poucos dias, o que significa que qualquer coisa que dependa de estado escrito na hora do clique e lido na hora do depósito tem validade medida numa fração de uma janela normal de consideração. Bloqueadores de anúncios ficam em cima de tudo isso e são comuns justamente nos públicos que leem conteúdo de comparação antes de se cadastrar. Nada disso se anuncia. O seu operador vê a página renderizar bem e conclui que a integração funciona.
Aí tem a parte que nenhuma configuração de navegador resolve. Um jogador clica no desktop do trabalho, pensa um pouco e deposita à noite pelo celular. Ou se cadastra na web e deposita dentro do app nativo, onde não há navegador, nem página, nem tag para disparar. Em apostas esportivas especialmente, o depósito segue a tabela de jogos em vez do clique, e a segue para dentro do app. Se você quiser ver como essas duas jornadas se comportam de forma diferente, tráfego de cassino e de apostas esportivas divergem exatamente nesse ponto.
Um pixel não consegue disparar de um lugar que o navegador nunca visitou. Nada disso se conserta com posicionamento melhor de tag.
| O que te interessa | Image tag | Pixel JavaScript | Postback servidor a servidor |
|---|---|---|---|
| Dispara de onde | Do navegador do jogador | Do navegador do jogador | Do seu próprio backend |
| Sobrevive a bloqueador de anúncios | Raramente | Raramente | Sim, nem é envolvido |
| Sobrevive a troca de dispositivo | Não | Não | Sim |
| Sobrevive a depósito dentro do app | Não | Não | Sim |
| Lê estado da página em tempo de execução | Não | Sim | Não se aplica |
| Reporta um valor liquidado | Só o que a página souber | Só o que a página souber | Sim, a partir do sistema de registro |
| Quando usar | Sistemas legados que não dá para mudar | Um sinal na mesma sessão, como secundário | Qualquer coisa que decida dinheiro |

Os modos de falha que vale conhecer
Ninguém quebra uma integração de um jeito interessante. Os mesmos seis erros respondem por quase tudo.
Disparar no carregamento da página em vez de no evento. A tag mora na página de confirmação de depósito, então dispara toda vez que aquela página é aberta. O jogador atualiza, volta pelo histórico ou cai ali depois de uma tentativa falha, e cada uma dessas é uma conversão no seu relatório. Isso infla os números na direção que parece boa, e é por isso que sobrevive tanto tempo antes de alguém questionar.
Isso é mesmo server-side? Um framework de backend renderizando um template continua emitindo uma tag que o navegador tem que executar. Se a requisição parte do dispositivo do jogador, é lado navegador, seja qual for o arquivo em que foi escrita. O teste leva um minuto: bloqueie scripts no seu próprio navegador e veja se o evento ainda chega.
Depois tem o identificador de clique, ausente do registro do jogador. Essa é de longe a falha mais comum e ganha uma seção só dela abaixo.
O depósito é reportado antes de liquidar. O pagamento é autorizado, o postback sai, e o pagamento então falha ou é revertido. Agora existe uma comissão amarrada a um dinheiro que nunca chegou. Dispare no estado que o seu time financeiro reconheceria, não no estado que a sua página de checkout mostra.
Idempotência, ou a falta dela. Redes dão timeout. Um remetente bem construído tenta de novo, o que está correto. Se o lado receptor não consegue perceber que a segunda tentativa é o mesmo evento da primeira, a repetição vira uma segunda conversão. Todo evento precisa de uma referência única e estável do seu lado, o mesmo valor em toda tentativa, para que uma duplicata seja reconhecida e descartada em vez de paga duas vezes.
Eventos também chegam fora de ordem. Um depósito aterrissa antes do cadastro a que pertence, porque dois serviços dispararam de forma independente e um foi mais rápido. Ordene os eventos que dependem uns dos outros, ou faça cada um carregar contexto suficiente para se sustentar sozinho.
A única coisa que decide tudo
Toda falha acima é reparável numa tarde. Esta não é.
Quando um jogador chega por um link de rastreamento, o identificador daquele link tem que ser gravado no registro do jogador no cadastro. Não numa sessão. Não num cookie. Na linha do seu banco de dados que representa aquela conta, ao lado do endereço de e-mail, na mesma transação que a cria.
Se isso não acontece, nada depois disso pode ser atribuído. O jogador deposita três semanas depois, o seu backend dispara um postback tecnicamente perfeito, e ele não carrega identificador nenhum, porque não há nada para carregar. Nenhum ajuste de postback resolve. Você não está depurando um problema de reporte, está depurando um problema de cadastro, e a correção fica no fluxo de inscrição.
Dois hábitos relacionados poupam muita discussão. Guarde o identificador mesmo quando o valor parecer estranho, porque você está armazenando um token, não validando um. E guarde pela vida da conta em vez de por trinta dias, porque um CPA que paga em um depósito qualificador precisa que o vínculo ainda exista no momento em que o depósito qualifica, o que pode ser meses depois do clique. Se o vocabulário em torno de depósito qualificado e primeiro depósito estiver nebuloso do seu lado, o glossário de FTD, NGR, CPA, CPL e CPR vale dez minutos antes de você escrever o schema.
Testando antes de rodar tráfego
Um teste de integração correto é entediante e leva cerca de uma hora.
- Clique num link de rastreamento real e conclua o cadastro como um jogador normal faria. Depois olhe o registro do jogador no seu próprio banco de dados e confirme que o identificador está lá. Se não estiver, pare, porque tudo depois disso é teatro.
- Deposite dinheiro real. Um valor pequeno serve, EUR 20 basta. Pagamentos em modo de teste frequentemente pulam exatamente o caminho de código que dispara o evento, que é como integrações passam em staging e falham no dia um.
- Confirme que o evento de depósito chegou uma vez, com o valor certo e a moeda certa, depois de o pagamento liquidar e não quando foi submetido.
- Mande o mesmo evento de novo de propósito. Ele deve ser reconhecido como duplicata e não contado duas vezes.
- Repita tudo num celular, e mais uma vez com o depósito feito no app em vez do navegador, se você tiver um.
Uma hora de um engenheiro e um depósito, contra um mês de reconciliação com um afiliado já convencido de que você está roubando o tráfego dele. O passo a passo de QA de link de rastreamento cobre o lado do afiliado do mesmo teste, e rodar as duas pontas juntas é como se acha o descompasso numa tarde em vez de num trimestre.
O que a AFFILIFY espera de um operador
A referência de integração está em affilify.partners/docs, com o endpoint, os nomes dos parâmetros e os tipos de evento aceitos. Leia por lá, e não por um post de blog, porque aquela página é a que mantemos atualizada.
O formato é pequeno. Um nome de evento, o identificador que você recebeu na hora do clique, um valor e uma moeda, mais a sua chave. Registro, primeiro depósito, depósitos seguintes e eventos de receita são mensagens separadas, porque o modelo de comissão amarrado a um deal decide quais delas importam, e um programa não consegue pagar RevShare sobre dados que nunca recebeu. Se você ainda está escolhendo entre modelos, CPA, RevShare e híbrido explica o que cada um exige do seu lado.
Duas coisas que vale dizer com todas as letras. A atribuição do nosso lado tem camadas de contingência. Elas são seguro, não plano. O identificador gravado no cadastro é a parte que você controla, então mande. E a qualidade do tráfego é avaliada continuamente, o que significa que algumas conversões ficam retidas enquanto são checadas, em vez de creditadas na chegada. Isso não é recusa, e o afiliado vê o estado em vez de um vão silencioso.
Um operador que devolve o identificador, reporta eventos liquidados uma vez e pode ser testado com um depósito real em uma hora nunca vai ter a conversa das onze da noite. É essa a ambição inteira aqui.
Perguntas frequentes
Qual é a diferença entre um postback e um pixel?
Um pixel é disparado pelo navegador do jogador enquanto uma página está aberta. Um postback é disparado pelo seu próprio backend quando o evento é registrado, sem navegador nenhum envolvido. Essa única diferença decide todo o resto: o postback não é afetado por bloqueadores de anúncios nem pela política de cookies do navegador, continua funcionando quando o jogador se cadastra num notebook e deposita pelo celular, e funciona quando o depósito acontece dentro de um app nativo onde nenhuma página carrega. Ele também reporta o valor que o seu sistema de registro guarda, não o valor que uma página por acaso conhecia.
Dá para manter um pixel como backup junto do postback?
Dá, mas tenha clareza sobre o que ele vale. Um pixel só vai confirmar eventos que consegue ver, que são um subconjunto dos eventos que de fato aconteceram, e o tamanho desse subconjunto é invisível para você. Trate como checagem de sanidade na mesma sessão durante o desenvolvimento, e não como segunda fonte de verdade, e nunca reconcilie pagamentos contra ele. Se os dois dispararem para o mesmo evento, a sua plataforma precisa de uma referência única e estável do seu lado para que o par seja reconhecido como uma conversão e não duas.
Nossos postbacks estão disparando, mas nada é atribuído. Por quê?
Quase sempre porque o identificador de clique nunca foi gravado no registro do jogador no cadastro. O postback sai corretamente, na hora, com uma chave válida, e não carrega nada para casar. Cheque primeiro a linha de um jogador real no seu banco de dados. Se o identificador não estiver lá, o bug está no seu fluxo de inscrição e não no código do postback, e nenhuma lógica de retentativa ou ajuste de endpoint muda o resultado.
Como devemos testar uma integração de postback antes de rodar tráfego?
Clique num link de rastreamento real, cadastre-se como jogador e confirme que o identificador aterrissou na linha da conta. Depois deposite dinheiro real, porque pagamentos em modo de teste muitas vezes pulam exatamente o caminho de código que dispara o evento. Confirme que o depósito chegou uma vez, com valor e moeda corretos, depois de o pagamento liquidar. Mande o mesmo evento de novo de propósito e confirme que ele é descartado como duplicata. Depois repita no celular, e no app se você tiver um. Uma hora, e um depósito pequeno.
