Only click-to-WhatsApp gives you a true click identifier. WhatsApp inbound messages carry ctwa_clid in the referral object. Messenger and Instagram carry a referral object with ref and ad_id instead, and the Conversions API identifies the person by a page-scoped or Instagram-scoped user ID rather than by a click.
Meta's three click-to-message destinations look symmetrical in Ads Manager. They are not symmetrical in the API, and the differences decide what you can measure. This page sets out, field by field, what each destination actually delivers, quoted from Meta's webhook and Conversions API references.
Do all Meta click-to-message ads give you a click ID?
No. WhatsApp is the only one. That single asymmetry is the reason WhatsApp funnels are easier to measure than Messenger or Instagram funnels, and it is why advice written for one destination frequently fails on another.
| Destination | Click identifier | Ad identity | Person identity |
|---|---|---|---|
| Click to WhatsApp | ctwa_clid | source_id, "Ad ID." | WhatsApp phone number identity |
| Click to Messenger | None | ad_id plus optional ref | page_scoped_user_id (PSID) |
| Click to Instagram Direct | None | ad_id plus optional ref | ig_sid (IGSID) |
| Link to Telegram | None | None from Meta | Whatever you carry in the start parameter |
The last row is not a Meta destination at all. It is included because it is the shape most teams actually run: a Meta ad pointing at a Telegram funnel, where Meta issues nothing and you build the whole handoff yourself.
What WhatsApp gives you
A per-click identifier plus the ad's identity, both inside the referral object on the first inbound message. Meta's schema reference labels the object "Only included if message via a Click to WhatsApp ad" and describes ctwa_clid simply as "Ad click ID."
The same object carries source_id ("Ad ID."), source_url ("Ad URL."), headline ("Ad headline."), body ("Ad primary text.") and the media fields. Two useful consequences follow:
- Creative-level reporting needs no Conversions API work.
source_idalone tells you which ad produced which conversation, inside your own inbox. - Sending conversions back does need it.
ctwa_clidis the field Meta accepts to credit the click, and Meta's customer information parameters reference marks it "Do not hash."
The full treatment, including where the identifier is missing and what Meta does not document about it, is in ctwa_clid explained.
What Messenger gives you
A referral object with ref, an ads context block and the ad's identity, but no click identifier. There is also a scheduling subtlety that catches most first implementations.
Meta's messaging_referrals reference opens with a condition that is easy to read past:
"This callback will occur when the user already has a thread with the bot and user comes to the thread from:
Following an m.me link with a referral parameter
Clicking on a Messenger Conversation Ad"
"For tracking referrals in new threads, refer to Postback Event."
Meta, Messenger Platform, messaging_referrals. developers.facebook.com/documentation/business-messaging/messenger-platform/webhooks/webhook-events/messaging_referrals. Page shows "Updated: Jul 1, 2025". Checked 14 August 2026.So messaging_referrals fires for people who already have a conversation with your page. A brand new thread routes through a different event. Building only the referrals handler means you silently miss every first-time contact, which is most of the traffic a new campaign produces.
Meta also states a subscription requirement on the message path: "Message with Ads Referral Information requires the application to have page subscriptions to both the messages and the messaging_referrals fields." Subscribing to one is a common and quiet misconfiguration.
The Messenger referral fields
| Property | Type | Meta's description |
|---|---|---|
source | String | "The source of the referral. Supported values: ADS SHORTLINK" |
type | String | "The referral type. Currently supports OPEN_THREAD." |
ref | String | "The optional ref attribute set in the referrer. Only alphanumeric characters as well as -, _, and = are supported." |
referer_uri | String | "The URI of the site where the message was sent." |
ads_context_data | Object | Information about the click-to-Messenger ad the thread was started from, including ad_title, post_id and optional media URLs |
The ref field is the interesting one, because it is the Messenger analogue of Telegram's start parameter: a value you choose, set on the m.me link, and receive back. Its permitted character set is alphanumerics plus hyphen, underscore and equals, which is base64url plus the padding character. The same design rule applies as on Telegram: carry a short opaque reference, not a payload.
Note what ref is not. It is not issued by Meta, it does not identify a click, and it is only as unique as you make it. If you set the same ref on every ad, you have a campaign label. If you mint one per visitor from a bridge page, you have person-level attribution, and you have built the same machinery Telegram requires.
What Instagram gives you
The same shape as Messenger, with Instagram's own naming. Meta's Instagram messaging webhooks reference describes the messaging_referral field as firing when "an ig.me link with a referral parameter is clicked by a customer in an existing conversation", mirroring the Messenger condition exactly.
In the messages payload, Meta annotates the referral block with the comment "Included when a customer clicks an CTD ad" and shows ref, ad_id, source set to ADS, type set to OPEN_THREAD and an ads_context_data object.
The field is ad_id, not ig_ad_id. And ig_sid is not a click identifier: Meta's business messaging guide describes the Instagram-scoped ID as "an identifier that represents the user in a user<>business conversation". It identifies a person in a relationship with your account, which is a different thing from identifying a click, and it does not tell you which ad brought them.
The Conversions API payload differs per channel
All three use action_source of business_messaging, which Meta defines as "Conversion was made from ads that click to Messenger, Instagram or WhatsApp." The messaging_channel and the identifying fields inside user_data are what differ.
| Channel | messaging_channel | Fields in user_data | Hashed? |
|---|---|---|---|
whatsapp | whatsapp_business_account_id, ctwa_clid | No, both pass through | |
| Messenger | messenger | page_id, page_scoped_user_id | No, both pass through |
instagram | instagram_business_account_id, ig_sid | No, both pass through |
Meta's customer information parameters reference marks each of these "Do not hash", describing page_scoped_user_id as the value to "Use the page-scoped user ID provided to your webhook" and ig_sid as obtainable from the Instagram webhook. Hashing any of them is accepted by the API and matches nothing, which is the failure mode our payload validator was built to catch.
Meta makes one attribution statement that applies across all three: "Attribution is based on the page/dataset id and is not related to the app id."
FlowTracker's inbox covers WhatsApp, Instagram, Messenger, Telegram and Live Chat, and stores the right identifier for each on first contact, so the conversion goes back with the fields that channel actually accepts.
What the asymmetry means in practice
Four consequences, in rough order of how much money they cost people.
- A WhatsApp implementation does not port to Messenger. There is no
ctwa_clidto store, so a codepath that keys on it produces empty records and no errors. Build per channel or build against the union of fields. - Messenger and Instagram need a bridge page to reach person-level attribution. Because the only value you control is
ref, andrefis only unique if you mint it per visitor. That is the same architecture Telegram needs, for the same reason. - Ad-level reporting is available everywhere, cheaply. WhatsApp gives
source_id, Messenger and Instagram givead_id. If your question is "which creative starts conversations", you can answer it on all three without any Conversions API integration. - Deduplication is your responsibility on all three. Meta states it "does not assist with deduplicating events for Conversions API for Business Messaging so we highly encourage advertisers to perform deduplication before sending them over Conversions API for Business Messaging."
Where Telegram sits
Entirely outside this system. Meta issues no identifier for a Telegram destination, because Telegram is not a Meta surface, so there is no referral object, no ad_id and no click identifier arriving on the far side.
What you get instead is a parameter you populate yourself. Telegram documents the bot start parameter as accepting "A-Z, a-z, 0-9, _ and -" up to "64 characters long", which is enough for a reference and not for a payload. The mechanics are in the start parameter reference, and channel joins, which have no start parameter at all, are in what a Telegram channel join reveals.
The pattern across all four destinations is the same once you see it. Somewhere before the app boundary you have to write down who this person is and where they came from, because after the boundary the only thing that crosses is whatever you deliberately sent with them. WhatsApp is the one case where Meta does part of that work for you. Everywhere else it is yours to build, which is what FlowTracker's attribution layer does across the five channels its inbox covers.
Sources
Every link below was fetched and read on 14 August 2026. Where a vendor does not document something, this article says so rather than filling the gap with an estimate.
Last reviewed 14 August 2026