Tracking Link Macros: Syntax and Common Failures
What tracking link macros are, common syntaxes from {click_id} to ##CLICKID##, who replaces them, why a literal {click_id} reaches the MMP, and encoding.
A macro is a placeholder such as {click_id} that your own platform replaces with a real value before the redirect. The MMP never fills click-link macros for you, so a link that still shows {click_id} at the MMP has lost its click ID.
What is a tracking link macro?
A macro is a placeholder in a tracking link, such as {click_id}, that your ad server or tracking platform replaces with a real value for each click before it redirects the user to the MMP.
Macro: a token in a URL template that a platform swaps for a live value at click time.
Resolved link: the link after every macro has been replaced, which is what the MMP actually receives.
Common macro syntaxes
Every platform picks its own wrapper. The same click ID macro can look like any of these:
| Syntax | Example |
|---|---|
| Single braces | {click_id} |
| Double braces | {{click_id}} |
| Hashes | ##CLICKID## |
| Square brackets | [clickid] |
The name inside the wrapper is set by your platform too, so {TID} on one platform may be {click_id} on another. Copy the token from your platform's macro list rather than from an MMP's example link.
The generator on the home page lets you pick your platform's macro style, so the template uses the right wrapper from the start.
Who replaces the macro?
Your platform does, before the redirect: the MMP receives the click with whatever text is on the link and does not expand your macros for you.
Some MMPs spell this out in their partner documentation; Linkrunner's tracking link documentation, for example, says the platform must replace its own macros before the click arrives. AppsFlyer's template for ad networks follows the same pattern, with placeholders such as clickid={clickid} and advertising_id={gaid} for the network to fill.
A tracking setup involves two kinds of macro, and they live in different places:
- Your macros (click ID, sub-publisher, device ID): on the click link, filled by your platform.
- The MMP's postback macros (such as Adjust's
{label}or{idfa}callback placeholders): in the postback URL you give the MMP, filled by the MMP after a conversion. They never go on the click link. See tracking link vs postback.
The literal {click_id} failure
The most common macro failure is a final URL that still contains the macro text:
https://app.appsflyer.com/com.yourapp?pid=mediaName_int&c=diwali_offer&clickid={click_id}&af_sub_siteid={sub_publisher_id}
What happened: the platform did not recognise {click_id} as one of its macros, so it passed the text through unchanged.
What it costs:
- Every click carries the same "click ID", the literal text, so no conversion can be matched to a click.
- Sub-ID reports fill up with one row named
{sub_publisher_id}. - On Branch links, unfilled macros with braces can break the link in some browsers, according to Branch's own FAQ.
How to fix it:
- Open your platform's macro list and find the exact token for the click ID.
- Change the wrapper and name in the template to match, for example from
{click_id}to##CLICKID##if that is what your platform uses. - Click the live link once and read the URL that arrives, or ask the advertiser to look the click up in the MMP.
Encoding: when values need escaping
A macro is only half the job; the value it inserts must be URL-safe too. Practical rules:
- A space becomes
%20and an ampersand inside a value becomes%26; otherwise the next parameter starts early. - Never add a second question mark; join every parameter with
&. This explanation of broken query strings shows what a stray question mark does to the parameters after it. - AppsFlyer does not allow characters such as
{ } % & = + ? /in parameter keys or values (redirect parameters andaf_dpexcepted) and caps the whole link at 2,000 characters. Keep AppsFlyer values to letters, numbers, hyphens and underscores. - Adjust requires placeholders inside redirect URLs to be encoded, curly brackets included, and callback URLs to be percent-encoded as one value.
Double encoding
When one link is wrapped inside another, such as a store or deep link URL inside a tracker, the inner link is encoded once. Encoding it twice turns %20 into %2520, and the MMP stores the mangled value. If a sub-ID shows %2520 in reports, one layer of your stack is encoding a value that was already encoded.
Macros by MMP: what to watch
| MMP | Click ID parameter to fill | Watch for |
|---|---|---|
| AppsFlyer | clickid | Restricted characters; 2,000-character limit |
| Branch | ~click_id | Unfilled braces can break the link in some browsers |
| Adjust | None documented | Encode placeholders in redirect URLs, braces included |
| Airbridge, Tenjin, AppMetrica | click_id | AppMetrica uses it for deduplication |
| Linkrunner | tid | Must be named tid, not clickid |
Full formats are on the AppsFlyer and Branch pages.
A quick macro check before launch
- No braces or hash wrappers left in the resolved link
- The click ID changes between two test clicks
- Sub-IDs show real values in the MMP, not macro text
- No postback macros on the click link
The full sequence is in how to test a tracking link.
Questions
Why does my tracking link still show {click_id}?
Your platform did not recognise the macro, so it passed the text through unchanged. Check the exact token in your platform's macro list and update the template to match.
Which macro syntax should I use?
The one your own platform documents, not the one in the MMP's example. The MMP only sees the filled value, so the wrapper matters only to the platform doing the replacing.
Does the MMP replace macros on the click link?
No. The MMP receives whatever text arrives on the link, so your platform must fill its macros before the redirect.
Should I encode the macro or the value?
Encode the value your platform inserts, unless the MMP says otherwise. Adjust is one exception: placeholders inside redirect URLs must be encoded, curly brackets included.
Can I use my own macros in the postback URL?
No. Postback macros belong to the MMP, which fills them after a conversion, so copy the exact names from the MMP's postback documentation, such as label in braces on Adjust.
Can an unfilled macro break the link?
It can. Branch notes that unfilled macros with braces break the link in some browsers, so test with real values rather than raw templates.