INTERMEDIATE
DocsCampaign links and sub-IDs
A campaign rarely lives in one place - it runs through a newsletter, a couple of partners, maybe a printed flyer. This guide wires those placements up so every source answers for itself: how many clicks, how many of them human, and when the campaign should stop.
One campaign, many placements
The uncomfortable question in any traffic buy isn’t “how many clicks did we get” - it’s “which of those clicks were people, and who sent the rest.” A single total can’t answer that: the newsletter, the partners, and the flyer all pour into the same number, and the worst source hides behind the best one.
Kilo answers it with three pieces that work together. A campaign groups the links and carries the shared controls - a time window, a scan target, one place to end everything. Sub-IDs tag each placement so it reports separately. And click-quality classification labels every click as it happens - datacenter, VPN or proxy, likely human - so each source’s split stands on its own.
Create the campaign
In the dashboard, open Campaigns and choose New campaign. Three decisions do most of the work:
- The window. An optional start and end. Outside it, the links stop forwarding to their normal destinations and take the ending you chose instead.
- The scan target. Set a number and choose what it means: Track as goal only shows progress - links keep working past it - while Stop at target closes the campaign automatically once human opens reach the number, checked every few minutes.
- The ending. When the campaign is over, links can resume their own destinations, send visitors to a campaign-end URL - or a branded “ended” page when you haven’t set one - or return a permanent 410.
Two details are deliberate. The cap counts human opens only - the same figure the analytics headline shows - so bot traffic can never close your campaign early. And a campaign-end URL set on the campaign wins over each link’s own fallback, so one field re-points the whole ending. You can also close or reopen a campaign by hand at any time. The scan target as a goal is free on every plan; enforcement, the campaign-end URL, and manual close are part of the paid campaign controls.
Tag every placement with a sub-ID
Sub-IDs need no setup at all. Take the campaign’s link and hand each placement its own tagged variant - the same link with one extra query parameter:
https://qr2r.com/aA3k9?sub_id=newsletter
https://qr2r.com/aA3k9?sub_id=partner-42
https://qr2r.com/aA3k9?s1=flyer-aprilKilo captures the tag at redirect time, and the analytics grow a row per value. The parameter names are the ones ad platforms already emit - subid, sub_id, s1 through s5, aff_sub through aff_sub5 - so traffic arriving from an affiliate network is often tagged before you’ve done anything. One tag is kept per click, values are capped at 80 characters, and untagged clicks still count everywhere else - they just don’t get a source row.
Or drive it over the API
The same setup is two calls with a write-scoped key. Create the campaign - timestamps are epoch milliseconds:
curl https://qr2r.com/api/groups \
-H "Authorization: Bearer $KILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Spring launch",
"ends_at": 1735689600000,
"target_scans": 10000,
"enforce_target_scans": true,
"campaign_fallback_url": "https://example.com/spring-recap"
}'Then mint each placement’s link inside it. On a plan with traffic filtering, you can also opt the link into blocking at creation:
curl https://qr2r.com/api/links \
-H "Authorization: Bearer $KILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"default_target": "https://example.com/spring",
"name": "Spring - newsletter",
"group_id": 51,
"traffic_filter_enabled": true
}'The gates match the dashboard exactly: enforce_target_scans and campaign_fallback_url need the paid campaign controls, and traffic_filter_enabled needs a plan that carries traffic filtering - a request past your plan is refused with 402 plan_required, never quietly downgraded. Setting target_scans alone, as a goal, is free on every plan.
Read the split, then act on it
As traffic arrives, open the link’s - or the whole campaign’s - analytics. The Click quality panel shows the datacenter / VPN-or-proxy / likely-human split, and beneath it the traffic sources by sub-ID table gives every placement its own row: clicks and quality, side by side. One glance tells you the newsletter is nearly all people while partner-42 is two-thirds datacenter.
Then act. Pause the bad placement, take its row into the invoice conversation, shift spend toward the sources that send humans. If a source keeps sending machines, you can turn on Filter bot & datacenter traffic for that link - off by default, opt-in per link, on plans that carry it. With it on, known datacenter networks and declared bots get a “verify you’re human” page instead of your destination, and the blocked visits are still counted, so you can see exactly what it turned away.
Honest limits
Blocking covers what can be proven: datacenter networks and declared bots. VPN and proxy traffic is labeled but never blocked - much of it is ordinary people minding their privacy - and a bot that impersonates a normal browser well enough can evade classification. The click quality guide covers what the labels mean and where their edges are.
That’s the loop: group the links, tag the placements, read each source’s split, and let the campaign end itself at the target. Every number in it comes from the same aggregate analytics as the rest of Kilo - built without ever storing a raw IP address.
Open your campaigns