Attribution
First and last touch UTMs and ad click ids, captured by the SDK and joined with your ad spend.
Every lead in Orwel says where it came from. The SDK captures the campaign parameters of the landing URL, keeps them across sessions, and sends them with each conversion. The server uses them for the lead source and to join leads with the spend of your Google Ads and Meta Ads campaigns.
What the SDK captures
| Group | Parameters |
|---|---|
| UTMs | utm_source, utm_medium, utm_campaign, utm_term, utm_content, utm_id |
| Ad click ids (SDK 1.7.0+) | gclid, gbraid, wbraid (Google), fbclid (Meta), ttclid (TikTok), msclkid (Microsoft), li_fat_id (LinkedIn) |
They are read from the URL query string, then from a query inside the hash (/#/?utm_source=..., for hash routers), then from the referrer. Within a session they are kept in sessionStorage, so they survive client side navigation and redirects.
First and last touch
Across sessions the SDK keeps an attribution object in localStorage:
{
"first_touch": { "utm_source": "google", "utm_medium": "cpc", "utm_campaign": "brand" },
"last_touch": { "utm_source": "meta", "utm_medium": "paid", "utm_id": "120210000000" },
"first_click_ids": { "gclid": "Cj0KCQ..." },
"last_click_ids": { "fbclid": "IwAR..." }
}first_touchandfirst_click_idsare written once: the campaign that first brought the visitor.last_touchandlast_click_idsare overwritten on every new tagged visit.
Every conversion() carries this object. You don't need to read the URL or pass UTMs yourself.
How the server uses it
- Lead source: an explicit
sourceproperty on the conversion wins. Otherwise the last touchutm_source, then the first touch, then the UTMs of the session. - Google Ads: the last touch
gclid(orgbraid/wbraid) is stored on the lead and matched with the clicks of your synced Google Ads campaigns, so each lead is tied to the campaign that paid for it. - Meta Ads: Meta has no click level report, so
fbclidproves that a visit came from a Meta ad but cannot be joined with spend. The join usesutm_id(the Meta campaign id), with the campaign name inutm_campaignas a fallback. - Older SDKs: if a conversion has no
attributionobject (SDK before 1.6) the server recovers UTMs and click ids from the landing URL of the session.
With attribution and cost synced, the Campaigns screen shows cost per lead, cost per qualified lead and spend that produced no qualified leads.
Tag your ads
Ad platforms add their click id automatically (gclid with auto tagging in Google Ads, fbclid on Meta). Add UTMs as well, and always utm_id: unlike utm_campaign it survives a campaign rename.
utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_id={campaignid}
utm_source=meta&utm_medium=paid&utm_campaign={{campaign.name}}&utm_id={{campaign.id}}
utm_source=linkedin&utm_medium=paid&utm_campaign=q4_launch
Check it
Open your site with ?utm_source=test&utm_campaign=check using the development key, submit a conversion, and open the request in Dev mode: the payload has the attribution object, and there is no missing_attribution warning. A conversion without UTMs or click ids gets that warning and the lead counts as direct.