Skip to main content

Tracked Links and Delivery Proof

Two questions matter once your money leaves escrow: did the ad actually run as promised, and did it work? This page covers the machinery that answers both — the links in your ad and what is measured about them, and the signed delivery-proof archive on every delivered order.

One rule decides what every link becomes, and it is the same rule on every engine — a paid promotion, a cross-promotion and an exchange placement are measured the same way. Every link a reader can tap — a text link, an address typed into the text with or without https:// (example.com/sale, t.me/somechannel), an @handle, and every inline button — is published as its own short link of the form onflowads.com/rr/NNNN-NNNN, such as onflowads.com/rr/4821-7305, and every tap on it is counted. Where the short link sends the reader depends only on where it points:

The link points atWhere its short link sends the readerWhat is counted, and by whom
A Telegram channel or group you have connected to Onflow Ads (our bot is an admin there)A campaign invite link into that channel, minted for this booking. The reader lands in your channelEvery tap, at the short link. Joins on top: Telegram attributes every join to the invite link it came through and tells the bot about each one; the bot records it. Leaves are recorded too, and the channel's own subscriber count is checked beside the join count
Any other Telegram address — another channel, an invite hash, a bot, a bot's start link, a post linkThat address, exactly as written — a bot's start payload arrives byte for byte. Telegram's in-app browser opens it straight back in Telegram, so the reader lands where the link pointsEvery tap, at the short link
Any ordinary websiteYour page, carrying the campaign tags (utm_source=onflowads, utm_medium, utm_campaign, and utm_content naming the exact link)Every tap, counted at the short link with nothing for you to install — deduplicated to one per reader per day, link previews and crawlers excluded. The Onflow tag on your page then counts landings and conversions on top
Why every link takes one hop

A tap cannot report itself to us, so the only way to count every tap is to be the address the tap opens. That hop is instant — the link is looked up (from memory for a busy link) and the redirect is sent before anything is written, so the count can never slow a reader down. The address is a short onflowads.com/rr/… link; the destinations are listed under the preview before anyone approves the post. Into your own channel the hop opens an invite link, so Telegram reports joins natively on top — a better number than a tap.

What the reader sees in your post

A link you made by selecting text in the editor keeps its visible text exactly as you wrote it; only the destination behind the words changes. An @handle keeps its words and becomes a text link. An address typed into the text is replaced by its short link, which Telegram links by itself — unless that would take the post past Telegram's length limit, in which case the longest typed addresses keep their visible text and are linked in place instead. Either way every one is counted.

Each occurrence gets its own code: the same destination written twice gets two short links, each counted separately, and the report names where in the ad each one sat — Text link, Address in the text, @handle in the text or Button. Up to 50 links in the text are counted — the team can raise or lower that number; buttons are outside that budget.

Left exactly as written: something that is not a web address, such as an email address (Telegram does not link those as web links); a malformed or spoofed address, such as https://[email protected]; a link that is already an onflowads.com short link; and anything inside code formatting, which Telegram does not link either.

UTM tags are added, never overwritten

Standard tags are appended only where you have not set that key yourself. If you already instrumented the campaign, your own values survive untouched. A Telegram address is never tagged at all.

Joins, counted natively​

To have joins counted, the channel the ad points at must be yours and connected — listed on Onflow Ads on any engine, with the bot an administrator that may create invite links. At checkout a fresh invite link named after the campaign is created in that channel (you will see it in the channel's own invite-link list); if the booking fails or is an idempotent replay, it is revoked again. If the bot cannot create one — not an admin, missing the invite right — the short link sends readers to the channel's address as written instead: every tap is still counted, but joins cannot be.

A reader who taps the link lands in your channel. Telegram reports the join to the bot as it happens; a member who later leaves is recorded as having left; a member who comes back through the same link is not counted twice. Beside the join count the report shows channel growth — the channel's own subscriber count, from Telegram, since the link was minted — so a number that could only be inflated by real joins sits next to the one being claimed.

The Onflow tag​

For a web destination every tap is already counted. To also see how many taps arrived on your page, and to attribute signups or purchases, put one line on that page:

<script src="https://onflowads.com/tag.js" async></script>

It reads the campaign tags off the address, reports the arrival as a landing — deduplicated to one per reader per link per day — and remembers the link for the session so a later

OnflowAds.convert({ value: 1999, label: 'purchase' }) // value in cents, both optional

on your thank-you page attributes the conversion to that same link. Nothing on your page is read, no cookie of ours is set, and the only thing sent is the link's own token.

What is measured, and what is never stored​

  • Taps and landings are deduplicated to unique visitors using a salted, non-reversible fingerprint of the request. The IP address and browser string are stored for 90 days and then deleted automatically, leaving the fingerprint and what was derived from it — country, device, operating system, browser. Crawlers and link-preview fetchers are served but never counted (they are recorded and marked as crawlers, so an automated spike can be shown for what it was), and one reader's raw taps are capped per day, so a reload loop cannot pump a figure. You never see an individual visitor — only totals and breakdowns.
  • Joins are recorded against a salted one-way hash of the Telegram user — enough to notice the same person leaving, never enough to name them.
  • Taps, landings, joins and uniques roll onto the order, the campaign's CTR, and your analytics. Each campaign's links are listed inline on its card in Campaigns under Links & results, each marked taps counted, taps and joins counted or — for bookings made before every link became a short link — joins counted, redirect or tagged, with where in the ad it sat and a Details button that opens the click analytics panel for it.

Before you book, the composer's pre-flight says how your links will be measured, a sentence at a time. First how many there are — "1 link in your ad is published as its own onflowads.com/rr/ short link — every tap is counted, and readers land exactly where you pointed them.", or with several, "All 3 links in your ad are published as their own onflowads.com/rr/ short links — every tap is counted, and readers land exactly where you pointed them." Then, wherever they apply: "Addresses and @handles typed into the text count as links too, so they are tracked the same way.", "Joins to @yourchannel are counted too, through a campaign invite link.", "Add the Onflow tag to your web page to count arrivals and conversions as well." and "A mail address or one of our own links is published as written." With no link at all it says "No link yet — add a text link or a button so results can be measured."

Measurement never blocks a booking

If an invite link cannot be created, the short link sends readers to your channel's address as written; if a link's row cannot be stored, that link goes out as written, uncounted. A booking never fails because of measurement, and a measurement failure never delays a delivery.

The click analytics panel​

Every campaign card in Campaigns that has counted links carries the Links & results block. Press Click analytics in its header to open the panel for every link of the campaign at once, or Details on one link to open it for that link alone.

  • 7 days, 30 days or 90 days — the period switch at the top. Days and hours are shown in your own time zone.
  • Headline figures: Taps, Readers (each counted once over the period), Joins where a link goes into your channel, Busiest hour, Top country, and Not counted — previews and crawlers, automated bursts, and taps past a reader's daily limit.
  • Taps over time, By day or for the Last 48 hours, with unique readers (and, by day, joins) in the hover; When readers tap, by hour of the day; and Day of the week. Each has a Show as table button.
  • Breakdowns by Countries, Devices, Opened in (the app a tap was opened inside), Operating systems, Browsers, Languages and Came from (the referring site).
  • For the whole campaign, a table of every link with its own taps, readers counted once a day and joins, each with a Details button; All links goes back.

The panel shows counts, never who tapped, and reaches back 90 days — as long as the full tap record is kept. The same panel opens from Cross-Promotion results and from the Subscriber Exchange; see the click analytics panel in Links and results.

Proving the ad ran: two layers​

From weakest to strongest.

1. The live post link​

Every published order carries a "🔗 View live post ↗" chip that opens the actual Telegram post. Good for a quick look — but a live link cannot prove what the post looked like last week, and it disappears with the post.

2. The delivery-proof archive​

Once a placement is delivered, its expanded details on the Campaigns page grow a "Delivery proof" chip. Opening it reveals the panel headed:

Delivery proof archive — frozen and signed. What a dispute is argued over.

Its rows, oldest first:

  • Creative as booked — your caption and media manifest, frozen at the moment the order was marked delivered, in the same transaction. This is why your ad cannot be edited after paying: the archive verifies the live post against exactly what you booked.
  • Monitor capture — one row per check the monitor made during the run: its timestamp, the view, forward and reaction counts it read, and links to the post and to any screenshot.

Every row carries a "✓ signature valid" or "⚠ signature mismatch" stamp, recomputed from that row's own stored contents on every view — a tampered row fails on itself. A row whose live content had drifted from what you booked is additionally flagged "edited since booking", which is the evidence behind the standard dispute reason "The content was altered".

A "What does this prove?" button offers a plain-language explanation of the trail. It draws on your AI text allowance and reports honestly when that allowance is spent.

If something goes wrong​

What you seeWhat it meansWhat to do
⚠ signature mismatch on a proof rowThat row's stored contents no longer match its signatureRaise it with support quoting the OFO-. This is exactly what the signature exists to surface
edited since booking on a captureThe live post drifted from the creative you bookedIf the change matters, that is the "The content was altered" dispute reason, and this flag is its evidence
Odd utm_ parameters on your own destination pageThe standard campaign tagsExpected. Any UTM values you set yourself are preserved
A t.me link in your caption shows no UTM tags in your analyticsBy design — a Telegram address is never tagged, so its join or start payload reaches Telegram intactNothing to do. Its taps are counted at its short link, and joins into your own connected channel through the invite link
A link to your channel in an older booking reads t.me/+…It is the campaign invite link into your channel, published directly before every link became a short link; joins through it are what the report countsNothing to do. Readers land in the same channel
A link to your channel shows taps but no joinsThe channel is not connected to Onflow Ads, or the bot cannot create invite links there, so its short link sends readers to the channel's address as writtenConnect the channel and give the bot the invite right; the next booking counts joins
A web link shows taps but no landingsThe page it opens does not carry the Onflow tagAdd the one-line tag; taps are counted either way, and your own analytics see the campaign tags
Every link in your caption shows as onflowads.com/rr/…Each link's own short link, which counts the tap and sends the reader straight on — a Telegram link included (older bookings may show onflowads.com/go/yoursite.com/…; both keep working)Nothing to do
A typed address kept its own words in the published postReplacing it with its short link would have taken the post past Telegram's length limit, so it was linked in place insteadNothing to do — it is counted like every other link
The same address shows up as two rows under Links & resultsYou wrote it twice. Each occurrence gets its own short link and is counted on its ownNothing to do — each row says where in the ad it sat
Taps show but CTR is blankCTR needs taps and measured viewsWhile the placement still says Measuring…, the views side is not final. Blank means not measured yet, never zero
"The creative is archived, but no capture rows are available for it yet."The archive exists but the monitor has not yet written a captureNormal early in a run. Check again after a monitor cycle
"You've used today's AI actions." on the explainerYour AI allowance is spentThe proof trail itself is fully readable without it
From the support chat

Once the proof is in, confirm delivery of my order in the chat proposes the confirmation that releases the owner's payout — the same step as the button here. What the assistant can do for you has the full list and the confirmation rule.