Telegram Bot Deep Links: Track Campaign Source with Start Codes

To capture which campaign brought someone into your Telegram bot, give each entry placement a distinct start code and configure the bot to save the code it receives. Creating a tagged link is only half the task: the bot needs a rule for recognizing the code, recording the event and handling someone who returns through another link.

The useful deliverable is a source map plus a tested recording policy. This guide uses a hypothetical workshop campaign to separate the first valid source your application observes from the latest valid source it observes. Neither field proves where someone originally discovered your business.

1. Define the source question before making links

Suppose the same workshop is promoted on your website, on a printed QR card and in a partner post. Your question is which of those entry links a person used when starting the bot. Choose one code per placement so the bot can distinguish them without guessing from the greeting or asking the visitor to remember.

Keep a small campaign register containing the placement, code, intended offer and owner. Keep meanings stable: reusing an old workshop code for a different offer makes historical records ambiguous. This is incoming source capture; the Telegram bot message personalization guide covers choosing the destinations and variants in messages sent afterward.

2. Give the bot owner an exact source map

ExampleCampaignBot is a fictional username used only to illustrate the specification below, not a verified live integration. These example addresses are not destinations to visit. Replace the username with your own bot and configure the matching source map before publishing anything. The proposed introductions describe the same workshop, while acknowledging the entry invitation.

Telegram allows start payloads up to 64 characters using A–Z, a–z, 0–9, underscore and hyphen. The three codes below fit that format. Keep them short and non-sensitive. A placement label is enough; putting a customer name, phone number or confidential order detail into a reusable campaign link adds no value to this source question.

PlacementIllustrative bot linkExpected commandMapped introduction
Website workshop pagehttps://t.me/ExampleCampaignBot?start=web_workshop/start web_workshopWorkshop details from the website invitation.
Printed workshop QR cardhttps://t.me/ExampleCampaignBot?start=qr_workshop/start qr_workshopWorkshop details from the printed invitation.
Partner workshop posthttps://t.me/ExampleCampaignBot?start=partner_workshop/start partner_workshopWorkshop details from the partner invitation.

3. Separate opening the link from pressing Start

For these ordinary bot links with a supplied start parameter, Telegram displays a Start button even when the person has already started the bot. The person must press it to pass the parameter. Opening the address alone does not establish that your bot received a command. After Start, the website example produces /start web_workshop in the private bot conversation.

Test both a new account and an account with an existing conversation. Inspect the received command and the saved result, rather than relying only on the welcome message visible in chat. For the broader access and subscription journey, use the Telegram bot start and messaging access guide; this source test does not replace preference or stop controls.

Conceptual website, QR card and partner post carrying distinct source tags into one bot entry and a campaign register
A source code connects a received bot start with the entry link used; recording that connection requires your own bot configuration.

4. Specify what the start handler must do

Give the bot owner these decision steps. First, handle the private /start command and read its payload separately from the command name. Second, compare the payload exactly with the three-code allowlist in the source map. Treat an absent value as missing and an unrecognized value as unknown. Do not infer a campaign from arbitrary text.

Third, record a start event against the sender’s Telegram user ID, with observed_at defined as the handler’s UTC receipt time. Save the allowlisted source_code or the missing/unknown status. Fourth, apply the first/latest rules below and select the mapped introduction for a valid code. For missing or unknown input, show the general workshop introduction and available choices.

These are proposed application rules for your developer or bot platform to implement. Telegram delivers the command; it does not automatically create this campaign register, preserve source fields or produce the report. Ask the owner to show the configured mapping and one saved test event before you distribute the real links.

5. Preserve first source and update latest source

Under this example policy, first_valid_source is set only when that person has no saved valid source. Once set, it stays unchanged. latest_valid_source is updated whenever a new valid start event arrives, including a return through another placement. Save the associated observation times so the report can distinguish an early entry from a later return.

A missing or unknown payload creates its own event status and receives the default introduction, while leaving existing valid source fields intact. If neither field exists, leave both unset. Repeating a valid start may add another interaction event, but it does not add another person. Count distinct Telegram user IDs separately from start events when reviewing the test.

6. Run this six-case acceptance sequence

Run the following sequence with one controlled test identity against your configured bot. A means web_workshop; B means partner_workshop. Clear that identity’s test source fields before the first case. The expected results describe the proposed policy, not a claim that an unconfigured bot already behaves this way.

For each case, compare the incoming command, recorded event status, first/latest values and visible introduction. Save the observations beside the source map. Also verify qr_workshop against its mapping before printing the real QR card. A correct URL cannot compensate for an unrecognized code or a handler that overwrites the first source on every visit.

CaseExpected evidenceFirst / latest after case
New person starts with AValid A event; website introduction; one distinct personA / A
Same, existing person starts with BValid B event; partner introduction; same personA / B
Same person repeats AAnother valid A start event; website introduction; same personA / A
Same person sends plain /startMissing status; general introduction; valid sources preservedA / A
Same person sends /start unknown_workshopUnknown status; general introduction; valid sources preservedA / A
Same person opens B link without pressing StartNo start command from this opening; no new start eventA / A

7. Read the report as observed entry evidence

A forwarded partner link still carries partner_workshop. Someone can also share or manually enter a known code. Your record therefore identifies the code used, not independently verified exposure to the original placement. Label the report “observed bot entry source” and keep qualified enquiries and sales as separate outcomes.

Ordinary website UTM parameters do not automatically become a bot start payload; map the campaign to a supported start code. If your destination is a human account with suggested enquiry text, the Telegram Business chat links guide explains that different route. Choose the destination first, then measure the event that actually occurs there.

Explore PSYKE audience checks

Frequently asked questions

Can I put normal UTM query strings into a Telegram bot link?

Do not expect arbitrary utm_source or utm_campaign parameters to arrive in /start. Use a supported start payload, map its code to the campaign in your application, and test the received command.

Does someone who already started the bot have to press Start again?

For an ordinary bot deep link with a supplied start parameter, Telegram displays Start even for an existing user. They must press it to pass that parameter. Your application should record the new event against the same person rather than count another acquired user.

Sources and further reading

Related guides