Skip to content

Statistiques intégrées de Telegram ​

Telegram propose des outils pour analyser les résultats des emplacements publicitaires à l'aide de liens uniques. Vous pouvez créer un lien distinct pour chaque emplacement publicitaire. Pour les chaînes et les groupes, les statistiques d'adhésion sont disponibles directement dans Telegram, tandis que pour les bots et les Mini Apps, vous devez en plus configurer l'enregistrement des paramètres des liens et la collecte des données côté projet.

ATTENTION

Un emplacement publicitaire = un lien unique. Si le même lien est utilisé dans plusieurs annonces, les sources de trafic seront mélangées et ne pourront pas être séparées a posteriori.

Ce type d'analyse fonctionne indépendamment des statistiques de campagne et du suivi des conversions d'AdsGram.

Partie 1. Pour les responsables de campagne côté annonceur ​

1. Quel lien utiliser ? ​

Pour comparer les résultats de différents emplacements publicitaires, utilisez un lien unique pour chacun.

Par exemple, si vous faites la promotion d'un projet dans trois chaînes Telegram, créez trois liens distincts. Vous pourrez ainsi déterminer quels emplacements attirent le plus d'utilisateurs.

Le type de lien dépend de la destination de l'annonce :

Destination de l'annonceFormat du lienOù suivre les résultats
Chaîne ou groupe TelegramUn lien d'invitation distinctTelegram : paramètres de la chaîne ou du groupe → Invite links
Bott.me/YourBot?start=ad_sep_annaVotre bot, s'il enregistre le paramètre
Mini Appt.me/YourBot?startapp=ad_sep_annaLe serveur de votre application, s'il enregistre le paramètre

Remplacez YourBot par le nom d'utilisateur de votre bot et ad_sep_anna par un paramètre unique pour l'emplacement publicitaire.

2. Chaînes et groupes : liens d'invitation ​

Créez un lien d'invitation distinct pour chaque emplacement publicitaire.

  1. Ouvrez la chaîne ou le groupe et appuyez sur son nom.
  2. Ouvrez les paramètres de modification ou de gestion. Dans la version de bureau, utilisez ⋮ → Manage channel / Manage group.
  3. Ouvrez Invite links et sélectionnez l'option de création d'un nouveau lien.
  4. Nommez le lien d'après l'emplacement, par exemple ad_sep_anna. Le nom est visible uniquement par les administrateurs, pas par les utilisateurs qui ouvrent le lien.
  5. Si nécessaire, définissez une date d'expiration, une limite d'utilisateurs ou l'approbation obligatoire par un administrateur.
  6. Utilisez le lien dans un seul emplacement publicitaire.

Où consulter les statistiques : l'écran Invite links de Telegram indique combien d'utilisateurs ont rejoint via chaque lien. Ouvrez un lien précis pour voir la liste des utilisateurs.

Un lien public classique comme t.me/yourchannel ne permet pas de séparer les adhésions par emplacement publicitaire. Les chaînes publiques peuvent aussi créer des liens d'invitation : utilisez donc des liens d'invitation distincts dans vos annonces.

3. Bots : liens avec le paramètre start ​

Utilisez le format de lien suivant :

https://t.me/<bot>?start=<parameter>

Par exemple :

https://t.me/YourBot?start=ad_sep_anna

Lorsqu'un utilisateur ouvre le lien et appuie sur Start, le bot reçoit une commande contenant le paramètre :

/start ad_sep_anna

Telegram ne fournit pas automatiquement l'attribution publicitaire de ces lancements de bot. Le bot doit enregistrer le paramètre lors de la première création de la fiche utilisateur.

Ne comptez que les nouveaux utilisateurs si votre indicateur est l'acquisition de nouveaux utilisateurs. Un utilisateur existant qui ouvre un lien publicitaire ne devient pas un nouvel utilisateur.

4. Mini Apps : liens avec le paramètre startapp ​

Pour la Mini App principale d'un bot, utilisez :

https://t.me/<bot>?startapp=<parameter>

Pour une Mini App créée avec /newapp dans @BotFather, vous pouvez utiliser :

https://t.me/<bot>/<app>?startapp=<parameter>

Par exemple :

https://t.me/YourBot?startapp=ad_sep_anna

Si nécessaire, ajoutez un paramètre de mode d'affichage :

  • &mode=compact — mode compact.
  • &mode=fullscreen — mode plein écran.

La Mini App reçoit le paramètre dans le champ start_param. Le serveur de votre application doit l'enregistrer lors du premier lancement de l'application par l'utilisateur.

Si un utilisateur ouvre la Mini App sans lien publicitaire — par exemple via le bouton de menu ou le profil du bot —, le paramètre publicitaire peut être absent. Considérez ce lancement comme organique, sauf si une autre source d'attribution fiable est disponible.

5. Règles des paramètres ​

  • Longueur maximale :

    • Paramètre start — 64 caractères
    • Paramètre startapp — 512 caractères
  • Caractères autorisés :

    • A-Z, a-z, 0-9, _, -
    • N'utilisez ni espaces, ni caractères cyrilliques, ni points. Pour éviter les problèmes de compatibilité, limitez-vous au jeu de caractères autorisé.
  • N'incluez pas de données personnelles des utilisateurs dans les paramètres.

  • Modèle de nommage recommandé. Utilisez un format cohérent pour retrouver facilement les emplacements dans les rapports : ad_<month>_<source>_<creative>

    Exemples :

    • ad_sep_tgads_video1
    • ad_sep_blogger_anna

6. Les liens de campagne ne sont pas des liens de parrainage ​

Un lien de parrainage permet à un utilisateur d'inviter d'autres personnes et de recevoir une récompense.

Un lien publicitaire mesure le trafic provenant d'un emplacement publicitaire. À lui seul, il ne doit pas déclencher de récompense de parrainage.

Séparez les deux types à l'aide de préfixes :

  • ref_… — liens de parrainage des utilisateurs.
  • ad_… — liens des emplacements publicitaires.

Créer un lien de parrainage distinct pour chaque campagne publicitaire n'est qu'une solution temporaire. Cela peut entraîner le versement de récompenses de parrainage pour du trafic publicitaire et mélanger les statistiques.

7. Comment compter les clics ​

Telegram ne fournit pas de statistiques de clics pour les liens t.me.

Si vous devez compter les clics, faites d'abord passer les utilisateurs par votre propre redirection, puis envoyez-les vers Telegram.

Exemple :

https://yourdomain.com/go/ad_sep_anna → https://t.me/YourBot?start=ad_sep_anna

Votre serveur enregistre le clic et redirige l'utilisateur vers le lien de destination. Cela nécessite votre propre implémentation et ne remplace pas le suivi des lancements, des nouveaux utilisateurs ou des adhésions aux chaînes.

8. Tenir un tableau de résultats ​

Créez un tableau avec une ligne pour chaque lien unique.

Colonnes recommandées :

ChampQuoi enregistrer
Paramètre du lienPar exemple, ad_sep_anna
EmplacementNom de la chaîne, de la publication, de l'influenceur ou de l'annonce
DatesPériode de l'emplacement
DépensesCoût de la publicité
Nouveaux utilisateursNombre de nouveaux utilisateurs attribués au lien
Coût par utilisateurDépenses ÷ nombre de nouveaux utilisateurs

9. Liste de vérification avant le lancement ​

Avant de publier une annonce, assurez-vous que :

  • Chaque emplacement a son propre lien ; les liens ne sont pas réutilisés dans d'autres emplacements.
  • Le paramètre ne dépasse pas la longueur maximale et ne contient que des caractères autorisés.
  • Le lien a été testé avec un second compte : l'adhésion est comptabilisée ou le paramètre est enregistré par le bot ou la Mini App.
  • Le lien, le nom de l'emplacement et les dépenses ont été ajoutés au tableau.

Partie 2. Implémentation pour les développeurs ​

Les exemples ci-dessous utilisent Python, SQL et aiogram 3 pour le bot. Les mêmes principes peuvent être mis en œuvre avec d'autres technologies.

Le code constitue une base et non une intégration complète prête à l'emploi. Les fonctions d'accès à la base de données et certains détails d'intégration doivent être adaptés à votre application.

10. Quelles données stocker ​

L'attribution nécessite trois entités :

  1. Un registre des liens publicitaires et des campagnes.
  2. La source d'acquisition de l'utilisateur, enregistrée lors de la création de sa fiche.
  3. Un historique des visites des liens de campagne, y compris celles des utilisateurs existants.

Exemple de schéma SQL :

sql
-- Une ligne par lien publicitaire.
-- Par exemple, le paramètre "ad_sep_anna" correspond au code "sep_anna".
CREATE TABLE campaigns (
    code       text PRIMARY KEY,
    name       text NOT NULL,
    created_at timestamptz NOT NULL DEFAULT now()
);

-- La source d'acquisition de l'utilisateur est définie à sa création.
-- NULL signifie organique.
ALTER TABLE users
ADD COLUMN campaign text REFERENCES campaigns (code);

-- Tous les utilisateurs ayant ouvert des liens de campagne,
-- nouveaux comme existants.
CREATE TABLE campaign_visits (
    code     text REFERENCES campaigns (code),
    user_id  bigint,
    first_at timestamptz NOT NULL DEFAULT now(),
    PRIMARY KEY (code, user_id)
);

Le champ code doit contenir un code de campagne court, comme sep_anna. Le champ name décrit l'emplacement, par exemple Chaîne d'Anna, publication de septembre.

La table campaign_visits enregistre les visites séparément de la source d'acquisition d'origine de l'utilisateur. La source d'origine ne doit pas être écrasée chaque fois que l'utilisateur ouvre un autre lien.

11. Analyser les paramètres : un seul parser pour le bot et la Mini App ​

Utilisez un seul parser pour les paramètres publicitaires et de parrainage.

python
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 dans tous les autres cas."""
    if not param:
        return None

    if m := AD.fullmatch(param):
        return "ad", m[1]

    if m := REF.fullmatch(param):
        return "ref", m[1]

    return None

Après l'analyse, vérifiez si le code obtenu existe dans la table campaigns.

  • N'attribuez pas un code inconnu à une campagne existante. Considérez cette visite comme organique ou non attribuée.
  • N'enregistrez pas de valeurs brutes de paramètres non validées.
  • Appliquez les mêmes règles d'analyse aux paramètres reçus par le bot et par la Mini App.

12. Bot : traitement de /start ​

Lorsqu'un utilisateur lance un bot, Telegram transmet le paramètre dans les arguments de la commande /start.

Exemple avec aiogram 3 :

python
@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)

La fonction create_user_if_new ne doit créer une fiche utilisateur que si l'utilisateur n'existe pas encore.

Pour éviter les doublons, utilisez une opération atomique, par exemple :

sql
-- create_user_if_new : atomique, sûr si le bot et la Mini App interrogent en même temps
INSERT INTO users (id, campaign, referrer_id)
VALUES ($1, $2, $3)
ON CONFLICT (id) DO NOTHING
RETURNING id; -- une ligne renvoyée = nouvel utilisateur ; rien = utilisateur existant, laissé tel quel

Si la requête renvoie une ligne, l'utilisateur a été créé. Si elle n'en renvoie aucune, l'utilisateur existe déjà et sa source d'acquisition d'origine doit rester inchangée.

Pour enregistrer une visite d'un lien de campagne, utilisez :

sql
-- record_visit
INSERT INTO campaign_visits (code, user_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING;

Si un utilisateur existant ouvre un autre lien et reçoit /start ad_…, enregistrez la visite, mais n'écrasez pas son champ campaign.

Pour l'attribution des parrainages, définissez referrer_id uniquement pour les nouveaux utilisateurs. N'autorisez pas les utilisateurs à se parrainer eux-mêmes.

13. Mini App : traitement du premier lancement ​

Une Mini App peut recevoir le paramètre start_param dans les données de lancement de Telegram Web App.

Côté frontend, envoyez à votre serveur les données signées par Telegram :

javascript
// Frontend : chaque requête transmet les données d'initialisation signées par Telegram
fetch("/api/me", { headers: { Authorization: `tma ${Telegram.WebApp.initData}` } })

Sur le serveur, vérifiez l'authenticité de initData et son ancienneté avant d'utiliser l'ID utilisateur ou start_param.

Exemple de fonction de validation en Python :

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", "")
    # tous les champs sauf hash, "signature" compris, triés, une paire key=value par ligne
    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")
    }

Après une validation réussie, suivez le même processus que pour le bot (create_user_if_new et record_visit) :

  1. Récupérez user et start_param à partir des données validées.
  2. Analysez le paramètre avec parse_start.
  3. Créez l'utilisateur uniquement s'il n'existe pas encore.
  4. Enregistrez la visite du lien de campagne si le paramètre correspond à une campagne publicitaire connue.

Sécurité : utilisez uniquement des initData validées. Ne vous fiez pas à initDataUnsafe ni aux paramètres d'URL comme sources d'identité de l'utilisateur ou d'attribution, car ils peuvent être falsifiés.

Le paramètre start_param est fourni lorsque l'application est lancée via le lien correspondant. Il peut être absent lors des lancements suivants depuis le menu. Définissez donc la source d'acquisition d'origine lors de la création de l'utilisateur, et non à chaque lancement de l'application.

14. Un utilisateur, deux points d'entrée ​

Le bot et la Mini App peuvent partager une seule table users, dans laquelle chaque utilisateur est identifié par son Telegram user ID.

Par exemple, un utilisateur peut d'abord lancer le bot puis ouvrir la Mini App, ou l'inverse.

Règles d'attribution :

  • Le premier handler qui crée la fiche utilisateur définit la source d'acquisition d'origine.
  • Le second handler ne doit pas écraser cette source.
  • Les visites suivantes peuvent être enregistrées séparément dans campaign_visits.

Utilisez une insertion atomique, comme INSERT … ON CONFLICT DO NOTHING. Cela permet d'éviter les erreurs si les requêtes du bot et de la Mini App arrivent presque en même temps.

15. Chaînes : suivi des adhésions par lien d'invitation ​

Si vous avez besoin de votre propre suivi des adhésions plutôt que de vous fier uniquement à l'interface de Telegram, créez un lien d'invitation distinct pour chaque campagne et enregistrez-le avec le code de la campagne.

Exemple de création de lien en Python :

python
# Créer un lien par campagne et le conserver avec le code
link = await bot.create_chat_invite_link(
    CHANNEL_ID,
    name="ad_sep_anna"
)  # nom : 1 à 32 caractères
save_channel_link("ad_sep_anna", link.invite_link)

Dans cet exemple, le nom du lien d'invitation est limité à 1–32 caractères.

Pour recevoir les événements d'adhésion, le bot doit être administrateur de la chaîne et recevoir les mises à jour chat_member correspondantes. Si les demandes d'adhésion nécessitent une approbation, il doit aussi recevoir les mises à jour chat_join_request.

Exemple de configuration du polling :

python
# Les adhésions arrivent sous forme de mises à jour chat_member : le bot doit être administrateur et les demander
await dp.start_polling(
    bot,
    allowed_updates=[
        "message",
        "chat_member",
        "chat_join_request"
    ]
)

Exemple de handler d'adhésion :

python
@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
        )

Si un lien nécessite l'approbation d'un administrateur, traitez chat_join_request. Le lien d'invitation est disponible dans update.invite_link ; après vérification de la demande, vous pouvez appeler approve_chat_join_request.

Vous pouvez aussi enregistrer les départs des utilisateurs de la chaîne pour savoir qui est resté.

Telegram affiche déjà aux administrateurs le nombre d'adhésions par lien d'invitation. Votre propre base de données est utile si vous souhaitez combiner les données d'adhésion à la chaîne avec les informations sur les utilisateurs du bot ou d'autres statistiques.

16. Facultatif : suivre les clics avec une redirection ​

Pour compter les clics avant que les utilisateurs n'arrivent sur Telegram, créez votre propre endpoint de redirection.

Exemple en Python pour une Mini App :

python
@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:  # ignorer le robot d'aperçu des liens de Telegram
        record_click(code)

    return RedirectResponse(
        f"https://t.me/{BOT}?startapp=ad_{code}",
        status_code=302
    )

Cet exemple valide le code et exclut les requêtes dont le User-Agent contient TelegramBot, afin de ne pas compter les requêtes d'aperçu de lien de Telegram comme des clics ordinaires.

Adaptez l'implémentation à votre infrastructure et testez-la avec de vrais liens. La redirection doit mener au bon lien du bot ou de la Mini App avec le paramètre approprié.

17. Exemple de rapport ​

La requête suivante indique, pour chaque campagne, le nombre de visiteurs uniques des liens de campagne, de nouveaux utilisateurs et d'utilisateurs activés.

sql
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 : moment où l'utilisateur a effectué pour la première fois l'action payée par la campagne (une tâche, un achat)

Dans cet exemple, first_action_at est le moment où un utilisateur réalise pour la première fois l'action cible payée par l'annonceur, comme accomplir une tâche ou effectuer un achat.

L'indicateur visitors représente les utilisateurs ayant une visite enregistrée pour la campagne correspondante dans campaign_visits. Il ne correspond pas au nombre de clics sur le lien, sauf si les clics sont enregistrés séparément via une redirection.

18. Erreurs courantes et limites ​

  • Le bot ne reçoit le paramètre que lorsque l'utilisateur appuie sur Start. Tous ceux qui cliquent sur un lien ne lancent pas le bot ; le nombre de lancements peut donc être inférieur au nombre de clics.
  • Un redémarrage ne signifie pas un nouvel utilisateur. Si un utilisateur supprime le chat et relance le bot, le paramètre peut être transmis à nouveau, mais l'utilisateur n'est pas nouveau.
  • N'écrasez pas la source d'acquisition d'origine. Utilisez une table de visites distincte avec horodatage pour analyser les visites suivantes.
  • Séparez les comptes nouveaux et existants. Si l'objectif est l'acquisition, les visites répétées ne doivent pas augmenter le nombre de nouveaux utilisateurs.
  • Excluez les bots et l'auto-parrainage. Vérifiez is_bot et n'autorisez pas les utilisateurs à se parrainer eux-mêmes.
  • Respectez les limites des paramètres. La longueur totale du paramètre start ne doit pas dépasser 64 caractères. Utilisez des codes courts, comme sep_anna, pour laisser de la place au préfixe ad_ ou ref_.
  • Séparez l'attribution des parrainages et celle de la publicité. Des préfixes et des règles de traitement différents permettent d'éviter des récompenses et des rapports erronés.