Skip to content
All articles
8 min read

Does Your Click ID Survive the Jump Into an App?

A click identifier travels toward an app icon, splitting into paths marked arrives, does not arrive and unknown

You send a click into a native app, a Telegram bot, a Messenger thread, an Instagram DM, a WhatsApp chat, and want the same thing a postback gives you inside a browser flow: your click id waiting on the other side, ready to tie a conversion back to the exact click that produced it. The honest answer isn’t yes or no. It’s three answers, and the two that aren’t “yes” are not the same claim.

Three answers, not two

  • Arrives: the vendor documents a mechanism that carries it.
  • Does not arrive: the vendor says so directly, or its full published API surface has no path for it.
  • Unknown: no mechanism found, and no vendor statement ruling it out either.

Collapsing “does not arrive” into “unknown” misleads in both directions. Telling a buyer “WhatsApp might pass it, we just haven’t found how” invites them to keep trying random parameter names against a mechanism that’s documented not to have one. Telling them “nobody knows, same as WhatsApp” about a channel that’s genuinely undocumented, not denied, just unverified, throws away a channel that might actually work. The distinction is the point of this piece. Everything below sorts into one of the first two buckets, because those are the ones with evidence behind them.

Arrives

Link formMechanismConditions
https://t.me/<bot>?start=<payload>delivered to the bot as the /start argumentpayload up to 64 base64url characters; visitor must tap START
https://m.me/<page>?ref=<payload>messaging_postbacks for a new thread, messaging_referrals for a returning onevisitor must tap a CTA; the app must be subscribed to both webhook fields; ref is capped at 2083 characters and must be URL-encoded; Meta explicitly states it does not guarantee referrals will always work
https://ig.me/m/<user>?ref=<payload>same family as m.merequires Icebreakers configured, a published account, and app version 235 or later; ref allows [A-Za-z0-9_=-], up to 2083 characters

Every row here carries a condition, and the condition is not fine print. It’s the difference between the mechanism firing and not. The Telegram row needs an actual tap on START, not just the app opening. The Messenger row is qualified by Meta’s own documentation as something it does not guarantee, a different claim than “works reliably.” The Instagram row has three separate prerequisites stacked before the mechanism is even live for a given account.

Two Telegram variants sit outside this table because they behave differently. ?startapp= accepts up to 512 characters, but it’s delivered client-side into a Mini App’s init data. It only reaches a server if the operator’s own Mini App forwards and validates that data itself, which makes it a mechanism that depends on code you may not control. ?startchannel takes no value at all. It’s a bare flag, with nothing to carry your click id even if you wanted it to.

The startapp case is worth sitting with, because it’s the one entry in this piece that looks like it belongs in “arrives” and behaves more like “conditionally arrives, and the condition is your own infrastructure.” The payload genuinely reaches the client, inside the Mini App’s init data, every time. Whether it ever becomes something your server can see depends entirely on whether the Mini App code, running inside Telegram’s client, reads that init data and forwards it onward. If the Mini App belongs to a partner rather than to you, the click id can sit in front of the visitor’s device the whole session and never leave it.

Does not arrive

WhatsApp is the one buyers most often assume works, because wa.me/<phone>?text= looks exactly like a payload-carrying link. It isn’t one. The text parameter only prefills the message box. The visitor has to press send, can edit the text first, and the inbound webhook carries no referral object for an organic link regardless. WhatsApp does have a click identifier, ctwa_clid, but it’s generated by Meta after an ad click, not set by a link. A wa.me link a buyer builds and shares carries nothing that becomes ctwa_clid on arrival.

LINE states directly that you cannot determine how a user came to follow an Official Account, not undocumented, stated. Discord exposes no per-invite attribution and no event for it, confirmed in its own issue tracker. Threads’ webhook topic list covers replies, deletes, mentions, and publishes. There’s no messaging event in that list to carry anything through.

A stated absence is worth more than it might look like at first. Every entry in this section saves testing time precisely because it closes off a search rather than leaving it open. There’s no version threshold to wait for, no webhook field that might start working after a configuration change, no undiscovered parameter name to keep trying. LINE’s own statement, Discord’s own issue tracker, and Threads’ own webhook documentation each rule the door shut from the vendor’s side, which is a different and more useful thing to know than “we tried a few parameter names and none of them worked.”

Affiliate sub-ids are a different mechanism entirely

ProgramParameterRequirementWhere it actually works
Amazonascsubtagapproved affiliate account; the program itself is invitation-only, and the mechanism is not publicly documentedAmazon Associates links
Shopeesub_id1 through sub_id5approved affiliate accountShopee affiliate links
UbersubId1 through subId3approved affiliate account, routed through the Impact affiliate networkle.pxf.io, not uber.com

Values across all three follow the pattern [A-Za-z0-9], up to 255 characters. They do carry a per-click value end to end, but this isn’t the same channel as the deep link mechanisms above, and conflating them is a mistake in both directions. The Uber row is the sharpest illustration: the identifier only exists on links that run through Impact’s le.pxf.io domain. A link built directly against uber.com, however carefully you append a subId to it, carries nothing, because the mechanism that reads that parameter isn’t listening on that domain at all.

If your traffic is affiliate program traffic rather than an organic deep link, this is the mechanism that actually applies, and it lives in a completely different part of the vendor’s system than anything in the tables above. A buyer who reads “Amazon carries a sub id” as license to append one to any amazon.com link is applying an affiliate-program mechanism to a channel it was never part of.

The “arrives” column is real, and worth using, but every entry in it is conditional on something you don’t fully control: a tap on a specific button, a webhook subscription being correctly configured, an app version threshold, or a vendor’s own explicit non-guarantee. None of these behave like a postback field that returns your value on every hit. Building attribution logic that assumes a deep link click id arrives with postback-level reliability will be right often enough to look correct in testing, and wrong exactly when a campaign scales past the conditions that made testing look clean.

A click id that survives into an app is a genuine signal when it arrives, not a fallback you can lean on the way you lean on your own tracker’s internal identifier. DarkCore treats deep link ref parameters as one input among several, alongside sub ids and platform click ids, precisely because none of them is guaranteed the way an internal click id is. See Click ID vs Sub ID, fbclid, fbc and ttclid for how those responsibilities split.

The practical takeaway sorts cleanly along the same three-way split this piece opened with. Where the answer is “arrives,” design for the condition attached to it rather than around it. Where the answer is “does not arrive,” stop looking for a workaround the vendor has already ruled out. Where the honest answer is “unknown,” say so, rather than rounding it up to either of the other two.

FAQ

If Meta doesn’t guarantee messaging_referrals, should I rely on it at all?

Treat it as a bonus signal, not a primary key. It arrives under documented conditions often enough to be worth capturing, but Meta’s own documentation stops short of a guarantee. Build your attribution so a missing referral doesn’t break anything, rather than assuming it as the source of truth.

No. It’s generated by Meta specifically after an ad click. A wa.me link shared organically, in a bio, a post, a message, has no ad click behind it, so there’s no ctwa_clid to receive.

Does the ref payload need to be URL-encoded?

For m.me, yes, explicitly: the field is capped at 2083 characters and must be URL-encoded. Build the payload with that encoding in place before it goes into the link, rather than treating it as a plain string and hoping the platform normalizes it on receipt.

Does a longer ref payload buy more room to work with on Instagram than on Messenger?

Both cap at 2083 characters, so the ceiling is the same either way. What differs is everything stacked around it: Instagram’s mechanism additionally requires Icebreakers to be configured, the account to be published, and the app to be on version 235 or later, none of which relaxes just because the payload is short.

  • click id deep link
  • deep link attribution
  • tracking parameter native app
  • does click id survive