How partners send data through their tracking URLs, and how Relo uses those parameters for attribution, reporting, and commission.
partner_id and campaign_id server-side from the t.relo.mx/c/CODE short link (not from URL params — more secure). Partners can freely append utm_* or custom x_* params for their own sub-IDs, creatives, ad groups, etc. Everything captured gets queryable in the partner + admin Conversions tab.
| Layer | Where it comes from | Example |
|---|---|---|
| AUTO | Set by the click wrapper server-side when a user visits t.relo.mx/c/CODE. Partner does not configure these. |
partner_id, campaign_id, click_id |
| CAMPAIGN | Configured by Relo admin when creating the campaign or the short link (stored in CF KV). | Landing URL, optional UTM overrides, campaign slug |
| PARTNER | Partners append these to the short URL when running ads. We don't prescribe a schema — partners can track whatever they want. | utm_source, utm_campaign, sub1, asset_id, creative_id |
| CUSTOM | Per-event advertiser metadata sent via relo('lead', {...}) from the site itself (not the URL). |
product, stage, lead_value, custom x_* fields |
A partner gets one short URL from Relo:
https://t.relo.mx/c/ab12CD
They can add whatever they want after it. Every param survives the redirect:
// Partner's actual ad URL:
https://t.relo.mx/c/ab12CD?utm_source=facebook
&utm_campaign=summer_auto
&utm_content=video_a
&sub1=adset_123
&creative_id=vid_042
&asset_id=SAM-MX-A1B2C3
When a user clicks, the click wrapper:
ab12CD in KV → gets {url, partner_id=30, client_id=5, campaign_id=8}.click_id (ULID), stores all context in Redis (30-day TTL)._relo_cid=<click_id> on .relo.mx.&relo_click_id=<click_id>.Result URL after redirect:
https://quote.miami/?utm_source=facebook
&utm_campaign=summer_auto
&utm_content=video_a
&sub1=adset_123
&creative_id=vid_042
&asset_id=SAM-MX-A1B2C3
&relo_click_id=01KPVT...
The pixel inspects the landing URL once and stores tracking params in a first-touch cookie (30 days) + last-touch cookie (session). These ride with every event going forward.
| Param | Purpose | Where it lands |
|---|---|---|
utm_source, utm_medium, utm_campaign, utm_content, utm_term, utm_id | Standard UTM tagging | event_properties on purchase/lead_submit/form_submit |
gclid, gbraid, wbraid | Google Ads click ID | Same |
fbclid | Meta click ID (for CAPI dedup) | Same, plus used for Meta CAPI match |
ttclid, twclid, msclkid, yclid | TikTok / Twitter / Bing / Yandex click IDs | Same |
af_sub1–af_sub5 | AppsFlyer sub-publishers (works for pixel sites too) | first_touch cookie, surfaced on conversions |
af_ad, af_adset, af_channel | AppsFlyer creative / ad group / channel — also used for asset tracking | Same |
pid, c | AppsFlyer partner ID + campaign shortcut | Same |
mc_cid, mc_eid | Mailchimp campaign + email ID | Same |
irclickid, cj_aid | Impact / CJ affiliate IDs | Same |
partner, sub_id, click_id, relo_click_id | Generic partner IDs | Same |
af_ad as the canonical asset-ID field. The Link Generator at /c/SLUG/link-generator auto-appends af_ad=SAM-XX-XXXXXX when a partner generates a link for a specific creative. Queries like "which banner drove the most conversions?" become GROUP BY event_properties['af_ad'] in ClickHouse.
Anything not in the allowlist above is ignored by getUrlParams(). If partners want to track custom sub-publishers or IDs that aren't in the list, they have two options:
Map whatever they want into an allowlisted slot. For a "studio ID" for example, use af_sub4=studio_abc. Then admin + partner both see it in event_properties['af_sub4'].
If you need a brand-new canonical param (e.g. studio_id), add it to TRACKING_PARAMS in backbone/workers/pixel/src/pixel.ts and redeploy the pixel worker. This is a code change, not a config change — keep the allowlist small.
When the lead finally converts, the advertiser site can pass advertiser-controlled metadata that doesn't rely on URL params:
relo('lead', {
product: 'Auto Insurance Quote',
form_id: 'quote-v2',
stage: 'raw',
lead_value: 50,
currency: 'USD',
// Anything under extra.* surfaces as x_* on the Relo side
extra: {
zip: '33131',
preferred_agent: 'maria',
quote_id: 'Q-2026-0422-771',
studio_id: 'miami-001'
}
});
Relo stores these as:
event_properties.product = "Auto Insurance Quote"event_properties.stage = "raw"event_properties.lead_value = "50"event_properties.x_zip = "33131"event_properties.x_preferred_agent = "maria"event_properties.x_quote_id = "Q-2026-0422-771"There are two attribution paths, and pixel clients use the first:
t.relo.mx/c/CODE.{partner_id, campaign_id} in Redis keyed by click_id._relo_cid cookie (or relo_click_id URL param as fallback) on every event.Redis.GetClick(click_id) → populates partner_id + campaign_id columns.?partner_id=30 in the URL? Because URL params can be forged. A competitor could send traffic with ?partner_id=SOMEONE_ELSE and steal attribution. The click wrapper seals partner+campaign server-side so the partner can only tag events they actually own.
For mobile app installs where there's no click wrapper, partners get a CID pattern like mx_pd_affiliate_relo_none_always-on_sub1_banner_none_conversion. AppsFlyer passes the whole campaign string in the S2S postback. Relo matches against partner_clients.attribution_values using regex/contains/startswith/endswith to resolve the partner.
This lives in attribution.md and isn't what pixel clients use.
| Location | What they see |
|---|---|
| Partner portal → Conversions tab | Per-conversion list with all event_properties surfaced. Filterable by date, stage, search. |
| Partner portal → Dashboard | Aggregated counts, top products, funnel, traffic sources (UTM breakdown), landing pages, geo. |
| Partner portal → Links | Short URL stats: clicks per code, conversions per code. |
| Partner portal → Assets | List of assets with af_ad tracking IDs. Performance per creative. |
| Location | What they configure |
|---|---|
| Config → Data Pipeline → Web Pixel | Allowed domains, consent defaults, replay sampling, HMAC secret for postbacks. |
| Partners → + Onboard partner | Create partner + campaign + short link in one form. Sets KV {pid, cid, aid}. |
| Partners → Manage → Lead rates | Per-event / per-stage / per-product commission rates (fixed or %). With optional monthly_cap. |
| Campaigns → Settings | Campaign metadata, product patterns, landing URL template, UTM defaults. |
| Admin → Conversions | All conversions across the client. Filter by event_types, partner, date. CSV export. |
| Admin → Audit → Live events | Real-time event stream with raw event_properties visible for debugging. |
https://t.relo.mx/c/fbAgency
?utm_source=facebook
&utm_campaign=jul2026_auto
&utm_medium=cpc
&fbclid=IwAR... (Meta auto-adds this)
&sub1=adset_cheap_auto
&sub2=ad_video_v3
https://t.relo.mx/c/creativeA
?utm_source=google
&utm_campaign=miami_quote_q2
&gclid=EAIaIQ... (Google auto-adds)
&af_ad=SAM-MX-A1B2C3 (Relo asset tracking ID)
https://t.relo.mx/c/cjAffiliate
?utm_source=cj
&utm_campaign=autumn_push
&cj_aid=123456 (CJ auto-adds)
&irclickid=xyz (Impact auto-adds)
&sub1=publisher_foo
Admin can slice conversions by any captured param. Examples:
-- Conversions by sub1
SELECT event_properties['sub1'] AS sub1, count() AS leads
FROM events
WHERE client_id = 5
AND event_name = 'lead_submit'
AND event_time >= today() - INTERVAL 30 DAY
GROUP BY sub1
ORDER BY leads DESC;
-- Conversions by creative (af_ad = asset tracking ID)
SELECT event_properties['af_ad'] AS asset,
count() AS conversions,
sum(toFloat64OrZero(event_properties['lead_value'])) AS value
FROM events
WHERE client_id = 5
AND event_name = 'lead_submit'
AND event_properties['af_ad'] != ''
GROUP BY asset
ORDER BY conversions DESC;
-- Traffic source breakdown
SELECT event_properties['utm_source'] AS source,
countIf(event_name = 'page_view') AS sessions,
countIf(event_name = 'lead_submit') AS conversions
FROM events
WHERE client_id = 5
AND event_time >= today() - INTERVAL 7 DAY
GROUP BY source;
t.relo.mx/c/CODE. Don't link directly to the advertiser domain — attribution breaks.utm_source, utm_campaign, utm_medium, utm_content, utm_term — these are universal.sub1–sub5 for your own sub-publishers. We preserve these and partners can filter by them in the portal.af_ad for asset / creative IDs. Ask Relo for asset tracking IDs from the Link Generator.CODE to two different partners.+ Onboard partner) to create partner + campaign + short link atomically. Avoids inconsistent state.TRACKING_PARAMS in the pixel source and redeploy. Keep the list small (under 30 items) to avoid param pollution.