This is how attribution works in our own Salesforce org, the one that runs our lead handling and reporting. We built it in August 2026, when paid traffic started on Google Search and ChatGPT Ads, because a lead that cannot be tied to the campaign that paid for it turns every budget decision into a guess. Everything here can be named: the flows, the fields, and the parts that are not wired yet.
What is the path from an ad click to a Campaign member?
Ad URL
utm_campaign
gat-ai-automation-2026-08
Lead
UTM_Campaign__c
gat-ai-automation-2026-08
Campaign (active)
UTM_Campaign_Key__c
gat-ai-automation-2026-08
Campaign member
Status
Form Submitted
The attribution path, in five steps:
- Create the Campaign before the ad goes live. Name it
YYYY-MM | Brand | Channel | Theme, set the type to Advertisement, and give it a UTM campaign key such asgat-ai-automation-2026-08. - Put the key in the ad. The ad's URL carries
utm_campaignequal to the key, character for character. For Google Ads,utm_idcarries Google's campaign ID. - Keep the first touch on the site. The first page of a visit stores the UTM values, click IDs, landing page and referrer in session storage, so a form three pages later still knows where the visit started.
- Write it to the Lead. The contact form posts to a server route, an n8n workflow creates the Lead with the full attribution block, and a Cal.com booking writes its five UTM values only into empty fields.
- Resolve the Campaign. When a Lead is created with a campaign value, Lead: Assign Acquisition Campaign passes it to Resolve Lead Acquisition Campaign, which finds the active Campaign with that key and creates a Campaign member only if the Lead is not one already.
Which attribution fields does each Lead carry?
Eighteen, written once when the Lead is created. They are the reportable record of where a lead came from.
| Group | Fields | What they hold |
|---|---|---|
| Click IDs (4) | GCLID__c, GBRAID__c, WBRAID__c, FBCLID__c | Google and Meta click identifiers, kept for conversion import |
| UTM values (6) | UTM_Source__c, UTM_Medium__c, UTM_Campaign__c, UTM_Content__c, UTM_Term__c, UTM_ID__c | The six UTM parameters; UTM_ID__c holds the Google campaign ID |
| Pages (3) | Landing_Page__c, Submission_Page__c, Referrer__c | The visit's first page, the page with the form, and the referring site (origin and path only) |
| Context (2) | Inquiry_Topic__c, Form_Placement__c | What the visitor asked about and which form or booking they used |
| Consent (3) | Consent_Timestamp__c, Transactional_Contact_Consent__c, Promotional_Contact_Consent__c | What the visitor agreed to, and when |
The site accepts ten URL parameters, the six UTM values and four click IDs, and ignores everything else in the query string, so a stray parameter never reaches Salesforce. Each value is cut at 240 characters. The intake also sets Lead Source from the attribution: Advertisement for paid ChatGPT, Paid Search, Paid Social, Organic Search, and Web for everything else. Google Analytics treats UTM values as case sensitive, so google and Google are two sources there (URL builders, Google Analytics Help, read 16 October 2026); our keys are all lowercase with hyphens.
Why does the Campaign carry the key instead of the flow?
Campaigns change every month and flows should not. The resolver holds no Campaign IDs and no branch per campaign. A new campaign is a new Campaign record with its key, set by the Salesforce admin before launch, and nothing is deployed. The key field, UTM_Campaign_Key__c, is a 100-character text field marked unique, case-insensitive and external ID, so two campaigns can never claim the same key. The resolver also looks only at active Campaigns, so deactivating a finished campaign stops new members without touching the ads.
The key field was also the first change our new release pipeline shipped to production, a description edit on 14 October 2026. How that pipeline works is in how to set up Salesforce CI/CD with GitHub Actions.
What happens when the same person fills in the form twice?
The intake looks for an unconverted Lead with the same email. When it finds one, it leaves that Lead's fields alone, logs a completed Task (subject “Website form:” and the topic) holding the new message and the latest click detail, and sends us a repeat-submission notice. It creates no second Lead, overwrites no first-touch field, and adds no Campaign member. A Cal.com booking follows the same rule, because its UTM values go only into empty fields.
The cost of that choice is reporting. The Task tells a person which ad brought the visitor back, but free text cannot be reported by keyword or ad. The Campaign member is reportable and keeps the original campaign. We chose first touch; if repeat touches by campaign matter to you, add a second Campaign member on purpose and report on both. The rest of our duplicate handling, and how Salesforce duplicate rules behave on API inserts, is in how to handle duplicate leads in Salesforce.
How do Campaign member statuses follow the lead?
Our AI Automation campaign uses five member statuses: Form Submitted, the default every new member gets, then Review Booked, Review Held, Qualified and Disqualified. Moving members through them is what lets a campaign report answer more than how many forms came in: how many leads from that campaign booked a review, held it, and qualified. For what happens to the lead between those statuses, see Salesforce lead routing architecture.
Where do we read the attribution numbers?
On the Lead Desk home page in Salesforce, an owner dashboard we added on 14 October 2026. For a chosen window (this month, 30 days or 90 days) it shows new leads against the previous window, new leads by Lead Source, open leads by status and open opportunities by stage. For product signups it groups leads by where they came from, reading the UTM source first and the referrer when there is none, and names Google, Bing, LinkedIn, Reddit, ChatGPT, Claude and Perplexity as sources of their own. It reads records and changes none.
What is not wired yet?
- Google Ads offline conversion import.
GCLID__cis stored so closed deals can go back to Google Ads and bidding can learn which clicks became clients. The upload is not wired. Google's requirements for it: auto-tagging on, the GCLID captured and stored with the lead, and a click-to-conversion cycle under 14 or 90 days depending on the data source (Google Ads Help, read 16 October 2026). - A campaign written after the Lead exists. The resolver runs when a Lead is created. A booking tool that writes the UTM campaign after its first insert gets no Campaign member. An update-triggered version passed a production validation on 15 August 2026, and the version in our repository still triggers on create only. When you build the update version, compare against
$Record__Prior, and note that a record created and updated in one transaction shows no change to compare (Global Variables Resource, Salesforce Help). - A returning client. The repeat check matches unconverted Leads only, so someone who already converted arrives as a new Lead with a new first touch. Logging that touch on their Contact instead is specified and not built.
Frequently asked questions
How do you attribute leads to campaigns in Salesforce?
Give each Campaign a unique key field and use the same string as utm_campaign in the ad. Capture the UTM values on the site, write them to the Lead when it is created, and let an after-create flow find the active Campaign with that key and add the Lead as a Campaign member, once.
Should utm_campaign match the Salesforce Campaign name?
Match a key field instead. Campaign names change for reporting reasons, and a flow that matches names breaks when someone renames one. A dedicated key that is unique and case-insensitive lets the flow find the Campaign without a hardcoded ID, and renaming the Campaign breaks nothing.
How do you keep first-touch attribution in Salesforce?
Write the attribution fields only when the Lead is created. A repeat form fill from the same email logs a Task on the existing Lead instead of updating it, and the booking tool writes UTM values only into empty fields.
Can Salesforce send conversions back to Google Ads?
Yes, through Google Ads offline conversion import, using the GCLID stored on the lead. Google requires auto-tagging and a captured GCLID, and the click-to-conversion cycle has to fall within 14 or 90 days depending on the data source. We store the GCLID and do not upload conversions yet.
Does campaign attribution in Salesforce need Apex?
Not in our org. It is two flows, a key field on Campaign, the attribution fields on Lead, and a permission set that lets the integration user write them. An n8n workflow handles the contact form and Cal.com's own Salesforce app handles bookings.