Telegram Bots and Channels: One Setup, Full Attribution
In Telegram traffic the bot is your attribution bridge. An ad click by itself is just a redirect; once a bot is connected, Leadgram knows exactly which click pressed Start, which subscriber came from which campaign, and can feed those conversions back to Meta or Google so the algorithm buys you more of the users who actually convert. Ten minutes of setup here is what makes every dollar of spend measurable later.
Add a bot
- Open @BotFather in Telegram, send
/newbotand copy the API key it returns (it looks like110201543:AAHdqTcv...). - Go to Bots and click Add New Bot.
- Paste the key into Telegram Bot API Key - the platform validates the token and pulls the bot's
@usernameautomatically. - Pick the type: Production Bot (live traffic, real users) for the bot you put in ads, Draft Bot (for testing flows) for experiments.
- Click Add Bot.
The bot shows up with an Active badge right away, but that badge just means the row saved - it isn't a signal that Telegram accepted the connection. Behind the scenes, saving the bot also registers a Telegram webhook for it, so there's no server to stand up and no URL to paste anywhere. That registration call is best-effort: if it fails, the bot still saves and still shows Active, and Telegram simply never learns where to send updates. If a freshly added bot goes quiet, see "Bot stays silent on Start" below.
Once the webhook is live, Telegram sends messages and button taps to it, and both get routed into your funnel. Channel membership changes and join requests reach the webhook too, but nothing currently turns them into flow activity - more on that in the next section.

How the bot attributes clicks
The chain looks like this: campaign tracking link → landing → deep link t.me/your_bot?start=click_id. When a user taps Start, Leadgram matches the payload to the stored click (a ref_id passed by an external tracker works too), launches the active flow bound to this bot from its first node, and records the chat into the bot's subscriber base. Add a Bot Start event node to the flow and the click advances to the Started status and ships as a server-side conversion. Repeating /start always restarts the funnel from the beginning, exactly how Telegram users expect a bot to behave.
Channels and join events
Channels aren't detected automatically - you add every one by hand.
- On Channels, click Don't see your channel?.
- Fill in Channel Telegram ID (a negative number starting with
-100- find it via @userinfobot or by forwarding any channel post to @JsonDumpBot), a title, and the type - Public or Private. - Submit. The channel saves with a Pending status badge.
The status badge can also read Awaiting activation or Active, but right now nothing moves a channel out of Pending on its own. Treat the row as a reference record you attach to campaigns and postbacks, not a live health check.
channel_join is a real event type: you can forward it through Postbacks, and it maps to a Subscribe event when delivered to Meta. But nothing watches Telegram for actual channel joins yet - the only way a channel_join event fires today is a Channel Join node placed mid-flow in Message Flows, or a direct API call. join_request exists as an event type but isn't offered as a flow node option.
Where bots appear across the product
- Message Flows - a flow can be created without a bot bound to it, but it needs one before you can set it Active. The bot picker in the flow create dialog lists the bots you added here.
- Campaigns - the campaign's bot is stamped onto each click so the
/startmatch works reliably. - Pushes - the send list is the subscribers your bot collected via Start. A subscriber who blocks the bot drops out of that list, and sending
/startagain puts them right back on it.
Common pitfalls
- Token rejected. Copy the entire key from BotFather - digits, colon and the 35-character tail. A partial paste fails validation instantly.
- Bot stays silent on Start. Two different causes produce the same symptom. Most often, the bot only responds when a flow with the Active status is bound to it; no active flow, the update is ignored by design. Less often, webhook registration failed silently when the bot was added - the row still saved with no error shown, but Telegram never got told where to deliver updates. If the first cause checks out and the bot still doesn't respond, contact support to have the webhook re-registered.
- Unattributed starts. Users who open the bot by username bypass the tracking link, so there is no click id in the payload. Always route paid traffic through the campaign's tracking URL.
- Channel stuck on Pending. That's the current normal state, not a sign something broke - see Channels and join events above. It doesn't stop the channel from working in campaigns or postbacks.
- Testing on the production bot. Keep a separate Draft bot for flow experiments so a broken test never touches live traffic.
- Deleting a bot. Any flow that was Active on it drops to Draft instead of breaking outright - clicks, campaigns and channel history tied to the bot stay intact. Bind a new bot to the flow and set it Active again before it fires.