Why Stars payments are invisible to ad platforms
On a website, a purchase fires the pixel and the server sends a Conversions API event; Meta learns who bought and what it cost. A Stars payment happens entirely inside Telegram. The invoice is a message, the payment sheet is Telegram's, and the only party told about the result is the bot that issued the invoice, or the channel's bot for a subscription. Ads Manager keeps reporting clicks, the Stars balance in your bot's settings grows, and nothing says which campaign paid for which Star.
The fix uses what Telegram does give: the bot receives a successful_payment update for every payment, with the amount, the currency XTR, a charge id and the invoice's payload. If the payload carries the click id, or if the payer is someone whose join was tracked, the payment can be credited to an ad and reported like any other deposit. Tellmetric listens to your bot for exactly these updates. Joins, messages and payments are tracked through your own bot, created with @BotFather and connected on Connections, never through a personal account.
Stars payments in a bot
When your bot sends an invoice in Stars and the person pays, Telegram delivers successful_payment to the bot. Tellmetric records it as a Purchase with the amount, the currency and the charge id, once per charge, so a replayed update stores nothing twice. Attribution goes in two steps:
- By the click id in the invoice payload. Every invoice has a free-text
invoice_payload that comes back unchanged in the payment update. If your bot puts the click id there, the purchase is tied to that click directly: campaign, ad set, creative, the fbclid or ttclid and the browser cookies the click carried. The bot knows the click id because the person arrived through t.me/<bot>?start=<click id> from a tracking link of the kind "Opens a chat with your bot".
- Through the person's join, when the payload has no click id. Many bots do not control the payload, or the payment comes from a different bot flow. Then the payer's Telegram user id is looked up against their latest tracked join in the workspace, or a link they opened in the last 24 hours, and the purchase inherits that ad. A person who joined your channel from a Meta ad in March and pays in the bot in June is credited to the March ad.
A payment from someone with neither is recorded as a Purchase without an ad behind it, so the revenue is counted and the unattributed share is visible on the dashboard rather than hidden.
Before the payment, Telegram sends the bot a pre_checkout_query and waits ten seconds for an answer; that is handled too, so a connected bot does not block its own checkout. Payments also go through the same optional review step as any deposit if the workspace has deposit review switched on.
Paid channels: Star subscriptions
A paid channel sells access for a number of Stars a month through a subscription invite link. Telegram tells the channel's bot about the first paid join, as a chat_member update whose invite link carries the subscription_price, and about nothing else: no update arrives for a renewal and none for a cancellation. Tellmetric handles the three moments differently.
- The first paid join. Recorded as the join itself and as a
Purchase worth the subscription price, credited to the ad behind the person's join. Tracking links of the kind "Opens your group" that point at a paid channel mint a subscription link per click, so the join and the first payment both land on the click. A paid link nobody used within a day is revoked, so it cannot be passed around later and credit a stranger's subscription to the ad.
- Renewals. Every few hours the worker asks Telegram for each paid member's
until_date. A period that moved forward by at least a week is a renewal, recorded as another Purchase at the same price, one per period, credited to the same ad as the first. The dashboard's member value over time, on the Pro and Agency plans, therefore shows what a subscriber from each creative is worth after three or six months, not only at the first payment.
- The end. A period that ran out and was not renewed within a day is recorded as
SubscriptionEnded. It is a negative event: kept for reports, never sent to any ad platform.
Refunds
When a Stars payment is refunded, Telegram sends the bot a refunded_payment update with the same charge id. Tellmetric records a Refund tied to the original Purchase: it carries the purchase's event id and the same ad keys, so a report by creative shows the refund against the ad that produced the sale. A refund for a charge Tellmetric never saw is still recorded, without a linked purchase.
Refunds are never sent to ad platforms. Meta, TikTok and the others accept positive conversions only; there is no event that takes a purchase back, and sending a Purchase with a negative value would be rejected or, worse, counted. The right place for a refund is your own reporting, where cost per paying member and return are computed net of refunds, and that is where it stays. The same rule covers refunds reported through the postback from your own checkout.
Paid media
A channel or bot can post media that costs Stars to unlock. Telegram's purchased_paid_media update tells the bot who bought, but names no price and no charge. Tellmetric records it as a Purchase marked paid media with a value of zero, attributed through the payload if the bot set one and otherwise through the person's join. It is kept for reports, so you can see which ad brings people who unlock posts, but it is not delivered to any ad platform: a purchase with no value would teach the optimiser nothing and could mislead it. Repeat unlocks by the same person with the same payload collapse into one row, which is acceptable while the value is zero.
How the value reaches Meta
Ad platforms accept ISO currencies only; XTR is not one, and Meta rejects a whole batch for a single unknown currency. So every Stars amount is converted to US dollars at a configured rate before delivery, and the original Star count is stored alongside on the event. The Purchase goes out through the Conversions API with value, currency: USD, the hashed Telegram user id as external_id, and whatever the click carried: the fbclid, and the _fbp and _fbc cookies if the click passed through a page with the snippet. TikTok receives it as CompletePayment; Snapchat, Reddit, Spotify, X and Google Ads as their equivalents, on the Pro and Agency plans.
That is the point of the exercise: a campaign optimising for Purchase value is handed real payers with real amounts and begins to find more of them. Without it, the campaign optimises for link clicks or bot starts, and Stars revenue stays a number no one can tie to spend.
Meta refuses events older than seven days. Bot payments and first paid joins are delivered within minutes; a renewal found by the polling check is dated when it was found, so it arrives in time as well.
A worked example
The figures are illustrative. A trading-signals channel charges 500 Stars a month and runs two Meta ad sets to it, each with its own tracking link. Over the first month:
- Ad set A: €800 spent, 2,000 clicks, 140 paid joins, 6 refunds in the first week. Cost per paying subscriber €5.71; net of refunds €5.97.
- Ad set B: €800 spent, 1,400 clicks, 95 paid joins, 1 refund. Cost per paying subscriber €8.42; net €8.51.
A looks better. Two months later the renewal check has recorded the second and third payments: 48 of A's subscribers are still paying, 71 of B's. Revenue per original ad euro is now higher for B, and cost per retained paying member is where the budget decision is made, not cost per first payment. All of this comes from the bot's updates and the renewal check; nobody exported anything from BotFather.
Where it breaks, and how to tell
- The bot is not the one connected on Connections. Payment updates go to the bot that issued the invoice; if that is a different bot, Tellmetric never sees them. One workspace, one bot.
- The payload holds something other than the click id. The purchase then falls back to the person's join; if there is no tracked join either, it is unattributed. Put the click id from the
start parameter into the invoice payload, or make sure payers come in through a tracked join.
- The channel's subscribers joined through the channel's public link. Their first payment is recorded but has no ad behind it. Use one tracking link per ad; see tracking channel subscribers from ads.
- The bot lost admin rights in the paid channel. No join updates, no renewal checks. The Tracking health page flags it and an email notice goes out.
- Renewals seem late. They are found by polling every few hours, not at the second of payment. A renewal shows within the day.
- Return looks too high. Check that refunds are being subtracted in the report you are reading; they are recorded, and never sent to Meta, so Events Manager's purchase value is gross by design.
Frequently asked
Does Tellmetric need access to my Stars balance or payouts?
No. It reads the payment updates Telegram sends your bot and the paid members' subscription dates. Nothing about your balance or withdrawals is touched.
What does Meta receive for a Stars payment?
A Purchase with the value converted to US dollars, the hashed Telegram user id and the click identifiers from the ad, through the Conversions API. The Star amount stays on the event for your own reports.
Are subscription renewals counted?
Yes. Each renewed period is a further Purchase, found by checking each paid member's until_date every few hours, credited to the ad behind the first join.
Are refunds sent to the ad platforms?
No. A Refund is recorded against its Purchase for your reports and never delivered, because ad platforms have no event that takes a purchase back.
Does paid media count as revenue?
It is recorded as a purchase with value zero because Telegram's update names no price. It shows which ads bring people who unlock posts, and is not sent to any platform.