In brief: GA4 says organic. The CRM says direct. The rep says the buyer mentioned a podcast. None of those views is complete. I fix the tracking first, use the CRM for stages and revenue, use GA4 to understand what happened before the form, and look for agreement across the different layers before moving budget.
Attribution arguments in B2B SaaS tend to start the same way. Somebody opens GA4, somebody else opens the CRM, the numbers disagree, and the meeting turns into a discussion about which system is right.
I’ve sat through a few versions of that meeting.
Usually, neither system has the whole story. GA4 sees the browser behaviour it was able to observe. The CRM sees whatever attribution data made it through the form and onto the record. A podcast mention, a recommendation in Slack or three months of reading the newsletter may appear in neither.
So the first job isn’t choosing an attribution model. It’s working out what each system can actually see, and whether the tracking underneath it is working properly.
Fix the tracking before reading it
A surprising number of attribution problems turn out to be implementation problems.
These are the ones I find most often:
- Duplicate events. A hardcoded
gtagsnippet is still sitting in the site header after GTM was added. The same conversion fires twice and the ad platform starts optimising against an inflated number. - Thank-you pageviews counted as conversions. Refreshes, bookmarks and shared URLs can all create another conversion. I cover the mechanics and the replacement in the marketing engineering post.
- Cross-domain breaks. The marketing site lives on
wwwand the product onapp. Without cross-domain measurement configured in the Google tag, the move between them can start a new session and distort the original source.1 - Referral problems. Payment providers, authentication services and other domains in the journey start appearing as sources even though they didn’t create the demand.
- Iframe forms the page cannot observe. The person submits the form inside another document while the parent page records a visit with no conversion.
- UTM chaos.
LinkedIn,linkedinandLinkedinbecome three sources in the report because nobody wrote down a naming convention. - Consent misconfiguration. The visitor grants consent but the banner never sends the correct state to the tags. The channel appears to have stopped working when the measurement did.
- Internal traffic. Your own team keeps testing the site and slowly becomes one of its most engaged audiences.
None of these is particularly exotic. Most are the result of a setup changing over time.
That’s why I diagnose the existing tracking before I build a dashboard or start interpreting channel performance. If the capture is broken, better reporting just makes the broken data easier to look at.
The GA4 + GTM setup I use
Once the obvious problems are fixed, I want the setup to be boring enough that I can understand it six months later.
My usual order is:
- One GTM container. Configure the Google tag through it and remove any duplicate hardcoded snippets.
- One event contract. A single
dataLayerevent represents each user action, and the platform-specific tags listen to that event. - Only meaningful GA4 key events. Demo requests, trials and other actions that matter. Scroll depth doesn’t become a conversion because somebody once added a trigger for it.
- Cross-domain measurement across every domain involved in the funnel.
- Referral configuration for the payment, authentication and other domains that can interrupt the journey.
- Internal traffic rules for staging environments and whatever internal traffic can be identified reliably.
- Consent Mode v2 connected to the consent banner and tested in both granted and denied states. Google introduced the additional
ad_user_dataandad_personalizationconsent parameters for its EEA advertising and measurement requirements in 2024.2 - QA before release. GTM Preview first, then GA4 DebugView.
- BigQuery export from the start. GA4’s native export gives you the event-level record that is much harder to reconstruct later.3
The point isn’t to make GTM complicated. I want one place where I can see what fires, what causes it to fire and where the resulting data goes.
An event and UTM taxonomy for B2B SaaS
I name events as object_action, in snake_case, and put the detail in parameters.
So I’d rather have:
form_submit with form_id = demo
than:
demo_form_submit_v2_footer
The first survives a redesign. The second slowly turns the analytics property into a history of the website’s component names.
A simple event taxonomy looks like this:
| Event | Fires when | Key parameters | Consumed by |
|---|---|---|---|
form_submit | Any form completes successfully | form_id, form_location | GA4, ad platforms when relevant |
demo_request | Demo form completes | form_id, plan_interest | GA4 key event, Google/LinkedIn/Meta conversions |
trial_start | Account created | plan, source_surface | GA4 key event, ad platforms |
pricing_view | Pricing page viewed | plan_viewed | GA4, remarketing audiences |
docs_engaged | Meaningful docs engagement | section | GA4, possible scoring input |
The exact events depend on the product. The naming discipline matters more than copying this list.
I do the same with UTMs. There’s a written standard and one URL-builder sheet rather than each person inventing their own version.
| Parameter | Convention | Examples |
|---|---|---|
utm_source | Platform, lowercase | google, linkedin, newsletter |
utm_medium | Channel type from a fixed list | cpc, paid-social, email, partner |
utm_campaign | objective-audience-yyyymm | capture-competitor-202607 |
utm_content | Creative or placement variant | casestudy-a, carousel-2 |
utm_term | Paid search keyword | auto-populated |
Lowercase everything. Use hyphens rather than spaces. Don’t put campaign UTMs on internal links because you end up replacing the acquisition information you were trying to preserve.
I also capture the relevant parameters into hidden form fields. That gives the CRM its own copy of the source data rather than asking an analytics cookie to remember it forever.
Consent Mode and server-side tagging
Consent Mode is useful, but I try to describe it quite literally.
Google’s tags change their behaviour according to the consent state they receive. With the appropriate implementation, denied-consent traffic can send cookieless signals, and eligible properties may use behavioural or conversion modelling to estimate some of what’s missing.4
That estimate can be useful at an aggregate level. It is not a reconstructed record of what an individual visitor did.
More importantly, Consent Mode does not turn a refusal into consent. If somebody says no, the implementation needs to respect that.
Server-side GTM is a separate decision.
Instead of sending every marketing request directly from the browser to each vendor, the browser can send data through a server-side tagging container controlled by the company. Google documents the first-party and data-control benefits of that setup.5
There are good reasons to use it:
- more control over what data leaves the browser
- fewer direct third-party requests
- a cleaner place to transform or remove parameters
- potentially more resilient first-party measurement
There’s also another service to host, monitor and debug.
For a growth-stage SaaS company, I normally add server-side tagging when the value of better measurement and data control justifies owning the extra infrastructure. I don’t start there by default.
What each attribution view can and cannot tell you
I don’t try to make one model answer every question.
| View | How it works | I use it for | What it misses |
|---|---|---|---|
| Platform-reported (Google/LinkedIn/Meta) | Platform tags, click/view attribution and modelling | Optimising campaigns inside that platform; comparing activity within the same platform | Other platforms may claim the same conversion; view-through windows add credit for impressions |
| GA4 data-driven attribution | Allocates credit across the touchpoints GA4 can observe | Directional channel analysis across observable web journeys | Dark social, offline influence, missing consented data, broken identifiers and anything GA4 never saw |
| CRM source fields | First/last-touch values carried onto the lead/contact record | Pipeline and revenue by recorded source; board reporting | Only as good as the form capture; compresses a multi-touch journey into a few fields |
| Self-reported attribution | Free-text “how did you hear about us?” field | Finding podcasts, communities, recommendations, newsletters and other influence tags miss | Human memory, recency bias, messy answers |
| Marketing mix modelling | Statistical modelling of outcomes against spend and other drivers | Larger-scale budget allocation when there is enough history and variation | Weak signal at small budgets; uncertainty can be wide |
GA4’s own attribution options have also narrowed over time. Google retired several rules-based models in 2023, leaving data-driven and last-click approaches in Analytics.6 At the larger end of the market, open-source MMM frameworks now include Meta’s Robyn and Google’s Meridian.78
I find those developments interesting, but they don’t change the basic setup I need at growth stage.
First I need to know that the click was captured, the form worked, the source reached the CRM and the opportunity stage means what everybody thinks it means.
The dashboard architecture
I want one funnel view, but I don’t expect one system to own every number in it.
I pull each metric from the system closest to the thing being measured:
- Spend and clicks: ad platforms.
- Sessions and on-site behaviour: GA4, with BigQuery when I need the event-level data.
- MQL, SQL, opportunity, closed-won and revenue: the CRM, using the lifecycle stages and routing already defined there.
- The connection between them: click IDs and campaign parameters captured on the CRM record by the form.
For anything with money attached, the CRM wins.
If Salesforce says an opportunity is worth £80,000 and GA4 says there were 14 conversions, those aren’t competing versions of the same number. They describe different things.
GA4 helps me understand what happened before somebody became a CRM record. The CRM tells me what happened after.
That distinction sounds obvious, but it prevents a lot of dashboard arguments.
How I use attribution to make decisions
I treat attribution as evidence rather than a verdict.
If Google Ads says a campaign is working, CRM-sourced pipeline from the same campaign is rising and buyers are also naming Google or the problem-specific search in the free-text field, I have several different signals pointing in the same direction.
I’m comfortable moving budget on that.
If the ad platform looks brilliant but the CRM has nothing, I don’t immediately conclude that the ads are useless. I check the tracking first. If the tracking is sound and the disagreement still matters financially, I’d rather test the channel than spend another quarter debating the dashboard.
That might mean a geographic holdout, a controlled pause or another experiment appropriate to the channel and spend level.
And I keep the “how did you hear about us?” field.
Answers like “a friend”, “some podcast” or “your newsletter” aren’t clean enough for a pie chart, but they tell me about demand the tags can’t see. They also feed straight back into the voice-of-customer research that shapes the messaging.
When I start an engagement and the dashboards disagree, I map the funnel end to end before changing the reporting.
What fired in the browser? What reached GA4? What entered the form? What was written to the lead? What happened when the lead became an opportunity? Which identifier survived far enough to connect those steps?
Most attribution problems become much easier once those questions have answers.
Then the dashboard can do the useful part: show where the business is creating pipeline, where the journey is breaking and where another pound of spend has a reasonable chance of doing something useful.
Sources
-
Google Analytics Help, “Set up cross-domain measurement.” support.google.com (opens in new tab) ↩
-
Google Analytics Help, “Verify and update consent settings in Google Analytics.” support.google.com (opens in new tab) ↩
-
Google Analytics Help, “BigQuery Export.” support.google.com (opens in new tab) ↩
-
Google Analytics Help, “Behavioral modeling for consent mode.” support.google.com (opens in new tab) ↩
-
Google, “Server-side tagging.” developers.google.com (opens in new tab) ↩
-
Search Engine Land, “Google confirms sunset details for 4 attribution models in Ads and Analytics,” October 2023. searchengineland.com (opens in new tab) ↩
-
Meta, Robyn (open-source marketing mix modelling). facebookexperimental.github.io (opens in new tab) ↩
-
Google, “Meridian is now available to everyone,” 29 January 2025. blog.google (opens in new tab) ↩