A click ID is a unique value that your tracker or ad network generates for every click, and a SubID is a parameter you attach yourself to say where that click came from. Both have one job: to travel with the visitor from the ad to the offer so that a sale can be matched to the click that produced it. If the value disappears anywhere along the way, the conversion shows up in the network with no source, and you can't tell which creative or placement paid for it.
The values are easy to generate and surprisingly easy to lose. Most of the "my tracker shows fewer leads than the network" problems start with a parameter that was dropped by a redirect, a hard-coded link or a form. This article shows the full path a parameter takes, the places where it gets cut, and a short script that keeps it alive on a landing page.
The click ID is created at the first hop (your tracker link or the ad network) and has to reach the offer link in a parameter the affiliate network accepts. SubIDs (sub1 to sub5) are your own labels for creative, placement, campaign and so on. To keep them through redirects, make sure every hop copies the query string forward: the redirect method, the landing page links, the form action and any JavaScript redirect. Test with a dummy value before spending money.
What click ID and sub1 to sub5 mean
The click ID identifies one click. Your tracker creates it when the visitor hits your link, stores the click data under it (time, country, device, source) and later looks it up when a postback arrives. Some ad sources also issue their own click identifier and append it to the destination URL. Treat it as a separate field: it is useful, but it belongs to the source, not to your tracker.
SubIDs are free-form labels. The numbering (sub1, sub2, up to sub5 or more) is a convention, not a standard, and each tracker and network lets you use them a little differently. A typical split looks like this:
sub1: traffic source or ad accountsub2: campaignsub3: ad set, creative or placementsub4: landing page or prelander versionsub5: anything else you want to split by, such as a test number
The click ID answers "which exact click was this". SubIDs answer "what kind of click was this". You need both: the first for matching a conversion, the second for deciding what to scale.
The path a parameter travels
In a standard funnel, one value goes through four hops:
- Ad URL. The ad carries your tracking link with macros:
https://track.example.com/abc?sub1={campaign}&sub2={placement}. The ad network replaces each macro with a real value when it serves the click. Macro names differ between sources, so use the ones from the source's own documentation. - Tracker or TDS link. The link receives the query string, creates the click ID, logs the click and picks a destination by rules.
- Landing page. The visitor arrives with the parameters in the address bar, reads the page and clicks the button.
- Offer link. The button sends the visitor to the affiliate network with the click ID in the parameter the network expects. Most networks call it something like
clickid,subidoraff_sub. Check your network's docs for the exact name.
Later, when the visitor converts, the network calls your postback URL and returns the same value. The tracker finds the click, adds the conversion and the revenue. If you haven't set that part up yet, read how a postback URL works first. A click ID that is not returned in the postback is of no use, and a postback without a click ID can't be matched to anything.
Where parameters get lost
Every hop is a place where the query string can be cut. These are the usual suspects.
Redirect methods that drop the query string
A redirect sends the visitor to a new URL. If the new URL is stored in the rule as a plain address without parameters, the visitor arrives without anything. Some setups append the incoming query string to the destination automatically, others only do it when you tell them to, and some methods (meta refresh, JavaScript, iframe) behave differently from a plain 301 or 302. Don't assume: test each redirect method you use with a made-up parameter and look at the address bar on arrival. The same issue shows up with UTM tags, which is covered in how to keep UTM tags through redirects.
Landing links hard-coded without the parameter
The most common cause on landing pages. The page arrives with ?sub1=...&clickid=... in the URL, and the button still points to https://offer.example.com/go. The parameters stay in the address bar and never reach the offer. Fix it with the script below.
Forms
If the lander has a form that posts to the offer, the parameters in the page URL don't travel with it. The form needs hidden fields with the click ID and the SubIDs, filled in from the page URL. A form that submits to your own server and then redirects has the same problem one step later.
JavaScript redirects
A script that does window.location = "https://offer.example.com" sends the visitor to a clean URL. The code has to build the destination with the incoming parameters, not replace them.
URL encoding
A value containing &, #, a space or a non-Latin letter can break the query string if it isn't encoded. A placement name like news&sport turns into two parameters, and the second half is silently lost. Everything you put into a macro value should be safe characters, or percent-encoded when you build URLs in code.
Cross-domain hops
Cookies and local storage don't cross domains. If your funnel goes from a tracker domain to a landing domain to an offer domain, the only thing that carries data from one to the next is the URL. Don't rely on a cookie set on the first domain to be readable on the last one.
Appending parameters on a landing page
This script copies the query string of the current page to every outbound link you mark with a data-pass attribute. It keeps parameters that the link already has and doesn't overwrite them.
<a href="https://offer.example.com/go?offer=123" data-pass>Get the offer</a>
<script>
(function () {
var incoming = new URLSearchParams(window.location.search);
try {
// remember for the next page of a multi-page lander
if (window.location.search.length > 1) {
sessionStorage.setItem("tds_qs", window.location.search);
} else {
var saved = sessionStorage.getItem("tds_qs");
if (saved) { incoming = new URLSearchParams(saved); }
}
} catch (e) {}
document.querySelectorAll("a[data-pass]").forEach(function (a) {
var url = new URL(a.href, window.location.href);
incoming.forEach(function (value, key) {
if (url.searchParams.has(key) === false) {
url.searchParams.set(key, value);
}
});
a.href = url.toString();
});
})();
</script>
A few notes. Put the script at the end of the page so the links exist when it runs. URLSearchParams handles encoding for you. The sessionStorage part covers landers with more than one page: the second page has no query string, so it takes the saved one. If your offer expects the click ID under another name, map it in the script: read clickid from the incoming parameters and set it as the name the network wants.
For a form, add a hidden input per parameter and fill it from the same URLSearchParams object before the form is submitted.
Naming conventions for sub parameters
Pick a scheme once and keep it for every campaign. Reports are only as clear as the labels you put in.
- Fixed meaning per slot. If sub3 is the creative, it is the creative in every campaign. Don't use it for a placement next week.
- Short, lowercase, no spaces.
cr_video_12survives encoding,Video Creative #12doesn't. - IDs over names. Pass the numeric ID from the source when it offers one and keep the readable name in your own notes.
- Reserve a slot for tests. One slot for a test number saves you from changing the scheme mid-flight.
- Check the length limit. Some networks cut or reject long values. Look at your network's docs before you put a long string in.
Common losses and fixes
| Where it breaks | Symptom | Fix |
|---|---|---|
| Redirect without the query string | Landing opens with no parameters in the address bar | Enable parameter passing for that redirect, or build the destination URL with macros |
| Hard-coded button link | Parameters present on the page, missing at the offer | Append them with the script above |
| Form without hidden fields | Leads arrive with an empty click ID | Add hidden inputs filled from the page URL |
| JavaScript redirect to a clean URL | Works on desktop test, lost in live traffic | Build the destination from location.search |
| Unencoded special characters | A value is cut at the first & or # |
Use safe characters in macros, encode values in code |
| Cookie-based passing across domains | Works on one domain, empty on the next | Pass everything in the URL |
| Wrong parameter name for the network | Network shows conversions with no subid | Match the exact name from the network's postback and offer docs |
A five-minute test before you spend money
- Open your tracking link in a browser with a fake value, for example
?sub1=test_a&sub2=test_b. - Watch the address bar after each hop. The values should be present on the landing page.
- Click the button and check the offer URL. The click ID and your sub values should be in the parameter names the network uses.
- Look at the click in your tracker's click log and confirm the sub values were recorded.
- Repeat on a phone and in at least one more browser, since in-app browsers sometimes behave differently.
In TDS.SO the incoming parameters can also be used as a rule condition (URL parameters are one of the 20+ conditions), and each click shows up in the click log with its time, country, device, referrer and status. The redirect method is chosen per link from 10+ options, so you can change it and re-run the test without touching the ad. Conversion tracking with postbacks and revenue is in beta; the click ID side of it works the same way as described above.
FAQ
What is the difference between click ID and SubID?
A click ID is unique per click and exists so a conversion can be matched to that click. A SubID is a label you choose and it repeats across many clicks, such as the same creative number on thousands of visitors. Many people use the word SubID for both, and some networks name their click ID parameter subid, so read the docs of the network you work with.
How many sub parameters do I need?
Three to five cover most setups: source, campaign, creative, landing page and one spare. More slots mean more chances to mix up the scheme. Add one only when you have a real question that the existing ones can't answer.
Why does the network show a conversion with an empty subid?
The click reached the offer without the value. Check the landing links, the form and any JavaScript redirect first, then confirm the parameter name matches what the network expects.
Can I pass the click ID through a landing page that I don't control?
Only if that page forwards the query string on its own. If it doesn't, you need to host your own copy of the funnel step or use a redirect that sends the visitor straight to the offer.
If you want to test how your links behave, create one in the redirects section, pick a redirect method and run the five-minute check above. The analytics page shows what each click log records.
Guides and write-ups on routing, bot filtering and tracking from the TDS.SO team.
All articles by the author