Análise integrada do Telegram
O Telegram oferece ferramentas para analisar os resultados de posicionamentos de anúncios por meio de links únicos. Você pode criar um link separado para cada posicionamento. Para canais e grupos, as estatísticas de entradas estão disponíveis diretamente no Telegram; já para bots e Mini Apps, é necessário configurar adicionalmente o salvamento dos parâmetros dos links e a coleta de dados do lado do seu projeto.
ATENÇÃO
Um posicionamento de anúncio = um link único. Se o mesmo link for usado em vários anúncios, as fontes de tráfego vão se misturar e não será possível separá-las depois.
Este tipo de análise é independente das estatísticas de campanha e do rastreamento de conversões do AdsGram.
Parte 1. Para gerentes de campanha do lado do anunciante
1. Qual link usar?
Para comparar os resultados de diferentes posicionamentos, use um link único para cada um.
Por exemplo, se você promove um projeto em três canais do Telegram, crie três links separados. Isso permitirá identificar quais posicionamentos atraem mais usuários.
O tipo de link depende do destino do anúncio:
| Destino do anúncio | Formato do link | Onde acompanhar os resultados |
|---|---|---|
| Canal ou grupo do Telegram | Um link de convite separado | Telegram: configurações do canal ou grupo → Invite links |
| Bot | t.me/YourBot?start=ad_sep_anna | Seu bot, se ele salvar o parâmetro |
| Mini App | t.me/YourBot?startapp=ad_sep_anna | O servidor do seu app, se ele salvar o parâmetro |
Substitua YourBot pelo nome de usuário do seu bot e ad_sep_anna por um parâmetro único para o posicionamento.
2. Canais e grupos: links de convite
Crie um link de convite separado para cada posicionamento de anúncio.
- Abra o canal ou grupo e toque no nome dele.
- Abra as configurações de edição ou gerenciamento. Na versão desktop, use ⋮ →
Manage channel/Manage group. - Abra
Invite linkse selecione a opção para criar um novo link. - Dê ao link o nome do posicionamento, por exemplo
ad_sep_anna. O nome é visível apenas para administradores, não para os usuários que abrem o link. - Se necessário, defina uma data de expiração, um limite de usuários ou a exigência de aprovação por um administrador.
- Use o link em apenas um posicionamento de anúncio.
Onde ver as estatísticas: a tela Invite links do Telegram mostra quantos usuários entraram por cada link. Abra um link específico para ver a lista de usuários.
Um link público comum, como t.me/yourchannel, não permite separar as entradas por posicionamento. Canais públicos também podem criar links de convite, então use links de convite separados nos seus anúncios.
3. Bots: links com o parâmetro start
Use o seguinte formato de link:
https://t.me/<bot>?start=<parameter>Por exemplo:
https://t.me/YourBot?start=ad_sep_annaQuando um usuário abre o link e toca em Start, o bot recebe um comando com o parâmetro:
/start ad_sep_annaO Telegram não registra automaticamente a atribuição de anúncios para essas inicializações do bot. O bot deve salvar o parâmetro quando o registro do usuário é criado pela primeira vez.
Conte apenas os novos usuários se a sua métrica for aquisição de novos usuários. Um usuário existente que abre um link de anúncio não se torna um novo usuário.
4. Mini Apps: links com o parâmetro startapp
Para o Mini App principal de um bot, use:
https://t.me/<bot>?startapp=<parameter>Para um Mini App criado com /newapp no @BotFather, você pode usar:
https://t.me/<bot>/<app>?startapp=<parameter>Por exemplo:
https://t.me/YourBot?startapp=ad_sep_annaSe necessário, adicione um parâmetro de modo de exibição:
&mode=compact— modo compacto.&mode=fullscreen— modo tela cheia.
O Mini App recebe o parâmetro no campo start_param. O servidor do seu app deve salvá-lo quando o usuário abre o app pela primeira vez.
Se um usuário abrir o Mini App sem um link de anúncio — por exemplo, pelo botão de menu ou pelo perfil do bot —, o parâmetro de anúncio pode estar ausente. Considere essa inicialização como orgânica, a menos que haja outra fonte de atribuição confiável.
5. Regras dos parâmetros
Comprimento máximo:
- Parâmetro
start— 64 caracteres - Parâmetro
startapp— 512 caracteres
- Parâmetro
Caracteres permitidos:
A-Z,a-z,0-9,_,-- Não use espaços, caracteres cirílicos ou pontos. Para evitar problemas de compatibilidade, use apenas o conjunto de caracteres permitido.
Não inclua dados pessoais dos usuários nos parâmetros.
Padrão de nomenclatura recomendado. Use um formato consistente para que os posicionamentos sejam fáceis de identificar nos relatórios:
ad_<month>_<source>_<creative>Exemplos:
ad_sep_tgads_video1ad_sep_blogger_anna
6. Links de campanha não são links de indicação
Um link de indicação permite que um usuário convide outras pessoas e receba uma recompensa.
Um link de anúncio mede o tráfego de um posicionamento de anúncio. Por si só, ele não deve gerar uma recompensa de indicação.
Separe os dois tipos usando prefixos:
ref_…— links de indicação de usuários.ad_…— links de posicionamentos de anúncios.
Criar um link de indicação separado para cada campanha publicitária é apenas uma solução temporária. Isso pode levar ao pagamento de recompensas de indicação por tráfego de anúncios e misturar as estatísticas.
7. Como contar cliques
O Telegram não fornece estatísticas de cliques para links t.me.
Se você precisa contar cliques, envie os usuários primeiro por um redirecionamento próprio e depois para o Telegram.
Exemplo:
https://yourdomain.com/go/ad_sep_anna → https://t.me/YourBot?start=ad_sep_annaSeu servidor registra o clique e redireciona o usuário para o link de destino. Isso exige uma implementação própria e não substitui a contagem de inicializações, novos usuários ou entradas no canal.
8. Planilha de resultados
Crie uma planilha com uma linha para cada link único.
Colunas recomendadas:
| Campo | O que registrar |
|---|---|
| Parâmetro do link | Por exemplo, ad_sep_anna |
| Posicionamento | Nome do canal, post, influenciador ou anúncio |
| Datas | Período do posicionamento |
| Gasto | Custo do anúncio |
| Novos usuários | Número de novos usuários atribuídos ao link |
| Custo por usuário | Gasto ÷ número de novos usuários |
9. Checklist antes do lançamento
Antes de publicar um anúncio, verifique se:
- Cada posicionamento tem seu próprio link; os links não são reutilizados em outros posicionamentos.
- O parâmetro não excede o comprimento máximo e contém apenas caracteres permitidos.
- O link foi testado com uma segunda conta: a entrada é contabilizada ou o parâmetro é salvo pelo bot ou Mini App.
- O link, o nome do posicionamento e o gasto foram adicionados à planilha.
Parte 2. Implementação para desenvolvedores
Os exemplos abaixo usam Python, SQL e aiogram 3 para o bot. Os mesmos princípios podem ser implementados com outras tecnologias.
O código é uma base, e não uma integração completa pronta para uso. As funções de acesso ao banco de dados e alguns detalhes da integração devem ser adaptados à sua aplicação.
10. Quais dados armazenar
A atribuição exige três entidades:
- Um cadastro de links de anúncios e campanhas.
- A fonte de aquisição do usuário, salva quando o registro do usuário é criado.
- Um histórico de visitas aos links de campanha, incluindo visitas de usuários existentes.
Exemplo de esquema SQL:
-- Uma linha por link de anúncio.
-- Por exemplo, o parâmetro "ad_sep_anna" corresponde ao código "sep_anna".
CREATE TABLE campaigns (
code text PRIMARY KEY,
name text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
-- A fonte de aquisição do usuário é definida na criação.
-- NULL significa orgânico.
ALTER TABLE users
ADD COLUMN campaign text REFERENCES campaigns (code);
-- Todos os usuários que abriram links de campanha,
-- incluindo usuários novos e existentes.
CREATE TABLE campaign_visits (
code text REFERENCES campaigns (code),
user_id bigint,
first_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (code, user_id)
);O campo code deve conter um código curto da campanha, como sep_anna. O campo name descreve o posicionamento, por exemplo, Canal da Anna, post de setembro.
A tabela campaign_visits registra as visitas separadamente da fonte de aquisição original do usuário. A fonte original não deve ser sobrescrita sempre que o usuário abrir outro link.
11. Processar parâmetros: um único parser para o bot e o Mini App
Use um único parser para parâmetros de anúncio e de indicação.
import re
AD = re.compile(r"ad_([A-Za-z0-9_-]{1,61})")
REF = re.compile(r"ref_([A-Za-z0-9]{4,32})")
def parse_start(param: str | None) -> tuple[str, str] | None:
"""("ad", code), ("ref", code) ou None em qualquer outro caso."""
if not param:
return None
if m := AD.fullmatch(param):
return "ad", m[1]
if m := REF.fullmatch(param):
return "ref", m[1]
return NoneApós o processamento, verifique se o código obtido existe na tabela campaigns.
- Não atribua um código desconhecido a uma campanha existente. Considere essa visita como orgânica ou não atribuída.
- Não armazene valores brutos de parâmetros sem validação.
- Aplique as mesmas regras de processamento aos parâmetros recebidos pelo bot e pelo Mini App.
12. Bot: tratamento do /start
Quando um usuário inicia um bot, o Telegram passa o parâmetro nos argumentos do comando /start.
Exemplo com aiogram 3:
@router.message(CommandStart())
async def start(message: Message, command: CommandObject):
source = parse_start(command.args)
# "/start ad_sep_anna" -> ("ad", "sep_anna")
async with db.transaction():
await create_user_if_new(message.from_user, source)
if source and source[0] == "ad":
await record_visit(source[1], message.from_user.id)A função create_user_if_new deve criar um registro de usuário somente se o usuário ainda não existir.
Para evitar registros duplicados, use uma operação atômica, por exemplo:
-- create_user_if_new: atômico, seguro quando o bot e o Mini App consultam ao mesmo tempo
INSERT INTO users (id, campaign, referrer_id)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING
RETURNING id; -- uma linha retornada = usuário novo; nada = usuário existente, mantido como estáSe a consulta retornar uma linha, o usuário foi criado. Se não retornar nenhuma, o usuário já existe e sua fonte de aquisição original deve permanecer inalterada.
Para registrar uma visita a um link de campanha, use:
-- record_visit
INSERT INTO campaign_visits (code, user_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING;Se um usuário existente abrir outro link e receber /start ad_…, registre a visita, mas não sobrescreva o campo campaign dele.
Para atribuição de indicações, defina referrer_id apenas para novos usuários. Não permita que usuários indiquem a si mesmos.
13. Mini App: tratamento da primeira inicialização
Um Mini App pode receber o parâmetro start_param como parte dos dados de inicialização do Telegram Web App.
No frontend, envie ao seu servidor os dados assinados pelo Telegram:
// Frontend: cada requisição carrega os dados de inicialização assinados pelo Telegram
fetch("/api/me", { headers: { Authorization: `tma ${Telegram.WebApp.initData}` } })No servidor, valide a autenticidade de initData e sua idade antes de usar o ID do usuário ou o start_param.
Exemplo de função de validação em Python:
import hashlib, hmac, json, time
from urllib.parse import parse_qsl
def check_init_data(
raw: str,
bot_token: str,
max_age: int = 86400
) -> dict:
fields = dict(
parse_qsl(
raw,
keep_blank_values=True,
strict_parsing=True
)
)
received = fields.pop("hash", "")
# todos os campos exceto hash, incluindo "signature", ordenados, um par key=value por linha
data = "\n".join(
f"{k}={v}" for k, v in sorted(fields.items())
)
secret = hmac.new(
b"WebAppData",
bot_token.encode(),
hashlib.sha256
).digest()
expected = hmac.new(
secret,
data.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, received):
raise PermissionError("bad signature")
if time.time() - int(fields["auth_date"]) > max_age:
raise PermissionError("expired")
return {
"user": json.loads(fields["user"]),
"start_param": fields.get("start_param")
}Após uma validação bem-sucedida, siga o mesmo processo do bot (create_user_if_new e record_visit):
- Obtenha
userestart_paramdos dados validados. - Processe o parâmetro com
parse_start. - Crie o usuário apenas se ele ainda não existir.
- Registre a visita ao link de campanha se o parâmetro corresponder a uma campanha publicitária conhecida.
Segurança: use apenas initData validado. Não confie em initDataUnsafe nem em parâmetros de URL como fontes de identidade do usuário ou de atribuição, pois eles podem ser falsificados.
O parâmetro start_param é fornecido quando o app é aberto pelo link correspondente. Ele pode estar ausente nas inicializações seguintes pelo menu. Por isso, defina a fonte de aquisição original quando o usuário for criado, e não a cada inicialização do app.
14. Um usuário, dois pontos de entrada
O bot e o Mini App podem compartilhar uma única tabela users, em que cada usuário é identificado pelo seu Telegram user ID.
Por exemplo, um usuário pode iniciar o bot primeiro e depois abrir o Mini App, ou o contrário.
Regras de atribuição:
- O primeiro handler que cria o registro do usuário define a fonte de aquisição original.
- O segundo handler não deve sobrescrever essa fonte.
- As visitas seguintes podem ser registradas separadamente em
campaign_visits.
Use uma inserção atômica, como INSERT … ON CONFLICT DO NOTHING. Isso ajuda a evitar erros se as requisições do bot e do Mini App chegarem quase ao mesmo tempo.
15. Canais: rastreamento de entradas por link de convite
Se você precisa de um rastreamento próprio de entradas, em vez de depender apenas da interface do Telegram, crie um link de convite separado para cada campanha e salve-o junto com o código da campanha.
Exemplo de criação de link em Python:
# Criar um link por campanha e guardá-lo junto com o código
link = await bot.create_chat_invite_link(
CHANNEL_ID,
name="ad_sep_anna"
) # nome: 1–32 caracteres
save_channel_link("ad_sep_anna", link.invite_link)Neste exemplo, o nome do link de convite é limitado a 1–32 caracteres.
Para receber eventos de entrada, o bot precisa ser administrador do canal e receber as atualizações chat_member correspondentes. Se as solicitações de entrada exigirem aprovação, ele também precisa receber as atualizações chat_join_request.
Exemplo de configuração de polling:
# As entradas chegam como atualizações chat_member: o bot precisa ser administrador e solicitá-las
await dp.start_polling(
bot,
allowed_updates=[
"message",
"chat_member",
"chat_join_request"
]
)Exemplo de handler de entradas:
@router.chat_member()
async def member(update: ChatMemberUpdated):
joined = (
update.old_chat_member.status in ("left", "kicked")
and update.new_chat_member.status == "member"
)
if joined and update.invite_link:
save_channel_join(
update.invite_link.name,
update.new_chat_member.user.id
)Se um link exigir aprovação de um administrador, trate chat_join_request. O link de convite está disponível em update.invite_link; após verificar a solicitação, você pode chamar approve_chat_join_request.
Você também pode registrar as saídas de usuários do canal para entender quem permaneceu.
O Telegram já mostra aos administradores o número de entradas por link de convite. Um banco de dados próprio é útil se você quiser combinar os dados de entradas no canal com informações dos usuários do bot ou outras análises.
16. Opcional: contar cliques com um redirecionamento
Para contar cliques antes que os usuários cheguem ao Telegram, crie seu próprio endpoint de redirecionamento.
Exemplo em Python para Mini App:
@app.get("/go/{code}")
async def go(code: str, request: Request):
agent = request.headers.get("user-agent", "")
if code_exists(code) and "TelegramBot" not in agent: # ignorar o rastreador de pré-visualização de links do Telegram
record_click(code)
return RedirectResponse(
f"https://t.me/{BOT}?startapp=ad_{code}",
status_code=302
)Este exemplo valida o código e exclui as requisições cujo User-Agent contém TelegramBot, para não contar as requisições de pré-visualização de links do Telegram como cliques comuns de usuários.
Adapte a implementação à sua infraestrutura e teste-a com links reais. O redirecionamento deve levar ao link correto do bot ou do Mini App com o parâmetro adequado.
17. Exemplo de relatório
A consulta a seguir mostra, para cada campanha, o número de visitantes únicos dos links de campanha, novos usuários e usuários ativados.
SELECT
c.code,
c.name,
(
SELECT count(*)
FROM campaign_visits v
WHERE v.code = c.code
) AS visitors,
(
SELECT count(*)
FROM users u
WHERE u.campaign = c.code
) AS new_users,
(
SELECT count(*)
FROM users u
WHERE u.campaign = c.code
AND u.first_action_at IS NOT NULL
) AS active
FROM campaigns c
ORDER BY new_users DESC;
-- first_action_at: quando o usuário fez pela primeira vez a ação pela qual a campanha paga (uma tarefa, uma compra)Neste exemplo, first_action_at é o momento em que um usuário conclui pela primeira vez a ação-alvo pela qual o anunciante paga, como concluir uma tarefa ou fazer uma compra.
A métrica visitors representa os usuários com uma visita registrada à campanha correspondente em campaign_visits. Ela não é igual ao número de cliques no link, a menos que os cliques sejam registrados separadamente por meio de um redirecionamento.
18. Erros comuns e limitações
- O bot recebe o parâmetro apenas quando o usuário toca em
Start. Nem todos que clicam no link iniciam o bot, por isso o número de inicializações pode ser menor que o número de cliques. - Reiniciar não significa um novo usuário. Se um usuário apagar o chat e iniciar o bot novamente, o parâmetro pode ser enviado de novo, mas o usuário não é novo.
- Não sobrescreva a fonte de aquisição original. Use uma tabela de visitas separada, com registros de data e hora, para analisar as visitas seguintes.
- Separe contas novas e existentes. Se o objetivo é aquisição, visitas repetidas não devem aumentar o número de novos usuários.
- Exclua bots e autoindicações. Verifique
is_bote não permita que usuários indiquem a si mesmos. - Respeite os limites dos parâmetros. O comprimento total do parâmetro
startnão deve passar de 64 caracteres. Use códigos curtos, comosep_anna, para deixar espaço para o prefixoad_ouref_. - Mantenha separadas a atribuição de indicações e a de anúncios. Prefixos e regras de processamento diferentes ajudam a evitar recompensas e relatórios incorretos.