Skip to content
All articles
8 min read

m.me and ig.me: The Only Meta Links That Hand Your Ref Parameter to a Backend

Two Meta deep links, m.me and ig.me, feeding a ref parameter into separate webhook paths

Meta has a handful of link formats that look like they carry a click identifier or sub id into a conversation. Exactly two of them actually hand that value to a webhook you can read server-side. Get the wrong one, or miss one of the conditions attached to the right one, and the parameter isn’t lost in transit — it was never delivered anywhere in the first place, and nothing in your logs will say so.

LinkShapeBackend mechanism
Messengerhttps://m.me/<page>?ref=<payload>messaging_postbacks for a new thread, messaging_referrals for a returning visitor
Instagramhttps://ig.me/m/<user>?ref=<payload>same referral family as m.me

Both forms exist to do the same job: carry a deterministic identifier from a click into a webhook payload your backend can read. Neither one is optional plumbing — a ref value that doesn’t reach one of these two webhook fields never reaches your server at all, by any other route.

Which webhook carries it depends on whether you’ve talked to this person before

This is the detail that quietly breaks the most integrations. The webhook field carrying your ref value isn’t fixed — it depends on Messenger’s own history with the visitor:

  • A visitor opening a thread with the page for the first time delivers the ref through messaging_postbacks. Meta treats it as part of the payload attached to that very first postback event.
  • A visitor who already has an existing thread with the page delivers the same ref through messaging_referrals instead — a separate webhook field, and one your app has to be subscribed to independently of the first.

Subscribe to only one of the two, and you don’t get a smaller version of the same data — you get a clean split of your audience by history with the page, with no error anywhere telling you which half went missing. A campaign into a page with a lot of returning contacts can look like it’s barely generating referrals at all, while every new-thread click is landing perfectly.

What’s actually allowed in the value

ParameterCapCharacter constraint
m.me ref2083 charactersmust be URL-encoded
ig.me ref2083 characters[A-Za-z0-9_=-] only

Both caps sit well above what a click ID or short payload needs, so the limit itself rarely bites. The character constraint on ig.me is the one worth checking against whatever your tracker actually generates: if the payload includes characters outside [A-Za-z0-9_=-], it either needs to be encoded into that set before it goes into the link, or it doesn’t belong in an ig.me ref at all. m.me is more forgiving in form — its requirement is URL-encoding, not a restricted alphabet — but the practical fix is the same: build the payload assuming the stricter of the two rules, and it works cleanly on both links.

Every condition that has to hold before any of this fires

None of the mechanism above runs unconditionally, and the two links don’t carry an identical checklist. ig.me stacks extra requirements on top of the ones both links share:

Conditionm.meig.me
Visitor taps a CTArequiredrequired
App subscribed to both messaging_postbacks and messaging_referralsrequiredrequired
Icebreakers configured on the accountrequired
Account published (not sandbox/dev state)required
Client on app version 235+required

The two conditions both links share are the ones people generally remember: the ref doesn’t ride in on an organic open of the thread, it has to arrive through a button click Meta recognizes as the referral source, and your app has to be subscribed to both webhook fields or it only sees the half of the audience described above. The three additional conditions attached specifically to ig.me are the ones that get skipped in a rushed setup, because none of them look like tracking configuration — Icebreakers reads like an onboarding feature, publish status reads like a launch checklist item, and app version reads like something outside your control entirely. All three still gate whether the ref value ever reaches a webhook.

And even with every applicable condition satisfied: Meta’s own documentation states outright that it does not guarantee referral delivery — one more case where an identifier doesn’t survive the trip across an app boundary. Every condition on this list is necessary. None of them, together or separately, is sufficient. Build your measurement around that fact rather than around an assumption of full delivery — a missing ref on some share of clicks is expected background noise on this mechanism, not automatically a sign your integration is broken.

Why this looks fine until you count it

None of the gaps described so far produce an error anywhere visible — the same invisible-failure shape as a deep link that quietly lands the visitor in a browser instead of the app. A visitor who taps a CTA on a page without Icebreakers configured still opens a real conversation in Instagram — the thread exists, the visitor can talk to the account, and nothing about the experience signals that the ref value silently didn’t make the trip. The same is true for a returning visitor hitting an app that only subscribed to messaging_postbacks: the conversation continues normally, and the missing messaging_referrals event leaves no trace for either side of the chat to notice.

That’s the pattern worth internalizing across both links: every failure mode here is invisible at the point of the click and only shows up later, as a gap between clicks recorded on one side and referrals recorded on the other. There’s no single dashboard number that tells you which condition failed — CTA-less traffic, an unsubscribed webhook field, missing Icebreakers, an unpublished account, or an old client version all produce the identical outcome of “no ref arrived.” Isolating the cause means checking each condition directly against your own setup, not inferring it from the shape of the drop-off.

Contrast with WhatsApp: wa.me doesn’t do any of this

It’s worth being explicit about what wa.me doesn’t do, because the two mechanisms look similar from a distance and behave nothing alike underneath. The organic link https://wa.me/<phone>?text=<message> only prefills the message box. The visitor can edit that text, delete it entirely, or close the chat without sending anything at all. None of that reaches your backend as a referral, because there is no referral object for an organic wa.me link — the inbound webhook simply doesn’t carry one.

The identifier that does exist on the WhatsApp side, ctwa_clid, doesn’t come from a link you build. It’s generated by Meta after an ad click specifically, and it cannot be set or influenced by any link — organic or otherwise — that you construct yourself. If the traffic didn’t come through a Meta ad, ctwa_clid isn’t part of the picture, and no amount of query-string engineering on a wa.me link produces an equivalent.

This matters for how you plan a Meta messaging campaign in the first place. It’s tempting to treat m.me, ig.me and wa.me as three versions of the same idea because they all open a chat from a link. They aren’t. Two of them are referral mechanisms with webhook events and a documented (if unguaranteed) delivery path. The third is a form autofill. Routing tracking logic meant for one onto the other doesn’t degrade gracefully — it just has nothing to attach to.

So across Meta’s own family of messaging surfaces, exactly two link shapes complete the round trip to a backend at all — m.me and ig.me — and both do it only conditionally. wa.me was never a third option; it solves a different problem entirely.

What to build around this

  • Subscribe to both messaging_postbacks and messaging_referrals from day one. New and returning visitors don’t share a webhook field, and there’s no way to infer the missing half from the one you have.
  • Keep ig.me payloads inside [A-Za-z0-9_=-]. Anything outside that set needs to be encoded before it fits, if it can fit at all.
  • Confirm Icebreakers, publish status and app version 235+ before trusting ig.me referral numbers — any one of them missing removes the mechanism entirely, silently.
  • Don’t budget for guaranteed delivery on either link. Meta says outright that it isn’t guaranteed; treat unmatched clicks as expected gap, not a bug to chase down every time it appears.
  • Don’t try to replicate this pattern on wa.me. There’s no referral object to subscribe to on an organic link — the only thing that link does is fill a text box, and the visitor decides what happens after that.

DarkCore’s Messenger and Instagram routing reads whichever of the two webhook fields actually fired for a given click and reconciles it against the click that generated the ref — because the new-thread-versus-returning-visitor split is exactly the kind of gap that quietly halves a reported conversion rate when nobody’s specifically watching for it.

  • m.me ref parameter
  • ig.me link
  • messenger referral tracking
  • instagram dm deep link