← Back to Strategy Playbooks
Insights / Strategy Playbook

The Illusion of Paid Search: How to Build a Hybrid B2B SaaS Attribution Engine with GA4 and Self-Reported Data

By Daniel Leira
|
Gotham Growth Engine
|
August 2026

Let us begin with a scenario that plays out in the boardroom of mid-market and enterprise B2B Software-as-a-Service (SaaS) companies every quarter.

The Chief Marketing Officer stands before the board, presenting a chart of rising Customer Acquisition Costs (CAC) alongside a growth curve that is stubbornly flattening. The Chief Financial Officer points to the marketing spend ledger:

"According to Google Analytics 4, our search campaigns are driving 65% of our demo requests. Meanwhile, your organic content strategy, your weekly industry podcast, and the time your team spends publishing on LinkedIn are showing a combined contribution of less than 3%. If we want to scale efficiency, we should cut the podcast and double our budget on high-intent Google Search Ads."

The CMO feels a familiar, cold dread. They know, intuitively and from conversational feedback during sales calls, that customers are mentioning the podcast and LinkedIn posts as the primary reasons they decided to book a demo. Yet, the dashboard—the single source of truth accepted by the executive team—says otherwise.

The CMO yields. They shift 40% of the content budget into Google Search Ads targeting high-intent keywords. Three months later, a strange phenomenon occurs: despite the increased search spend, the overall volume of qualified pipeline does not double. In fact, it begins to drop. The cost-per-lead on Google Search skyrockets, and the efficiency of the entire sales funnel degrades.

What happened? The company fell victim to the Attribution Trap: optimizing their marketing engine around demand capture software while systematically starving their demand creation channels.

This article outlines how to escape this trap. By moving away from single-source software models and implementing a Hybrid Attribution Engine that unifies Google Analytics 4 (GA4) Client IDs with structured Self-Reported Attribution (SRA) at the point of conversion, B2B SaaS companies can accurately measure where demand is created, where it is captured, and how to allocate budget to optimize real pipeline growth.

The Signals We Track vs. The Decisions We Make

Modern digital analytics was built on a simple promise: if you can track it, you can optimize it. During the era of desktop dominance and permissive third-party tracking, software could follow a user from their initial discovery click on a banner ad down to their final credit card transaction.

In B2B Enterprise SaaS, this clean digital lineage is a fantasy. The modern buying journey does not occur within a single browser, on a single device, or within a 30-day cookie window. According to Gartner, B2B buyers spend only 5% of their active buying cycle interacting directly with any given SaaS vendor's sales reps or digital properties. The remaining 95% of their journey is spent conducting independent research—consulting peer networks, listening to industry podcasts, reading LinkedIn discussions, and engaging in private Slack or Discord channels.

graph TD subgraph Dark Funnel (Demand Creation) A[LinkedIn Post] --> B[Podcast Episode] B --> C[Word-of-Mouth Slack] end subgraph Visible Funnel (Demand Capture) C --> D[Search Brand on Google] D --> E[Demo Form Submitted] end style A fill:#FFF,stroke:#333,stroke-width:1px style B fill:#FFF,stroke:#333,stroke-width:1px style C fill:#FFF,stroke:#333,stroke-width:1px style D fill:#FFF,stroke:#000,stroke-width:2px style E fill:#000,stroke:#333,stroke-width:2px,color:#fff

This untrackable ecosystem is what industry analysts refer to as the Dark Funnel or Dark Social. When a buyer learns about a SaaS platform through a peer recommendation on a private Slack community, they do not click a tracked UTM link. They open a browser tab, search for the brand name, and hit the website directly.

When they submit the sign-up form, GA4 registers the traffic source as Organic Search or Direct. If they happen to click a brand search ad on Google to navigate to the site, Google Ads claims 100% of the credit.

Software-only attribution tools like GA4 are physically blind to the touchpoints where the buyer actually developed the intent to buy. They only see the digital touchpoint where the buyer decided to execute that intent. GA4 is excellent at measuring where demand is captured, but it is entirely incapable of measuring where demand is created.

The Core Distinction: Demand Creation vs. Demand Capture

To build an efficient growth engine, SaaS leadership must distinguish between two fundamentally different marketing activities:

  1. Demand Creation: Educating target buyers who are not currently in-market, changing their perspective on how to solve a problem, and building brand preference long before they actively search for a solution (e.g., podcasts, original research, LinkedIn editorial, speaking at industry events).
  2. Demand Capture: Capturing the traffic of buyers who are already in-market, actively looking for a solution, and ready to buy (e.g., Google Search Ads, software directory listings like G2, retargeting campaigns).

When you rely exclusively on software-based attribution (such as last-touch or even standard multi-touch models), your data will always favor demand capture. Why? Because capturing demand occurs at the end of the journey, where cookies, form fills, and sessions are easy to measure. Creating demand occurs at the beginning of the journey, in channels that do not support tracking links or cookie drops.

If you optimize your budget based solely on GA4, you will continuously cut funding from demand creation (which looks like it has 0% ROI) and shift it to demand capture (which looks like it has 100% ROI).

This is the equivalent of a retail store firing their advertising agency because all of their customers enter through the front door, and then concluding that the front door is the only marketing channel that works. Once you cut the advertising budget, the line outside the front door disappears.

The Solution: The Hybrid Attribution Paradigm

To bypass the blind spots of software-only tracking without falling back on unscientific guesswork, we use a hybrid approach that mirrors military intelligence strategies: combining Signal Intelligence (SIGINT) and Human Intelligence (HUMINT).

  • Software-Based Attribution (SIGINT): Automated tracking of digital footprints (cookies, UTM parameters, referrer data, IP addresses). This captures the technical paths of conversion.
  • Self-Reported Attribution (HUMINT): Directly asking the customer where they first heard of you, using a mandatory, free-text field during the conversion event. This captures the human story of discovery.

The magic happens when you do not treat these two data points as separate silos. Instead, you must unify them at the database level using the GA4 Client ID. This connection links the quantitative session data (where the click came from) with the qualitative human response (why they arrived) for every single lead.

The Technical Blueprint: Implementing Hybrid Attribution

Here is a step-by-step technical guide to building and integrating a hybrid B2B attribution engine using your existing web properties, GA4, and a centralized database (such as Google BigQuery).

Step 1: Capture the GA4 Client ID on the Frontend

Google Analytics 4 assigns a unique identifier called the Client ID to every browser instance that visits your site. This identifier is stored in the _ga cookie. By capturing this ID and passing it to your Customer Relationship Management (CRM) system alongside your standard form fields, you create a permanent link between your CRM database and your GA4 export data.

Add the following JavaScript to your website to extract the GA4 Client ID and inject it into a hidden field in your forms.

(function() {
    function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
        return null;
    }

    function extractClientIdFromCookie() {
        const gaCookie = getCookie('_ga');
        if (gaCookie) {
            const matches = gaCookie.match(/GA1\.\d+\.(\d+\.\d+)/);
            if (matches && matches[1]) {
                return matches[1];
            }
        }
        return null;
    }

    function injectClientIdToForms() {
        let clientId = extractClientIdFromCookie();
        if (clientId) {
            populateHiddenFields(clientId);
        } else if (typeof gtag === 'function') {
            gtag('get', 'G-XXXXXXXXXX', 'client_id', function(id) {
                if (id) {
                    populateHiddenFields(id);
                }
            });
        }
    }

    function populateHiddenFields(id) {
        const hiddenInputs = document.querySelectorAll('input[name="ga_client_id"], input#ga_client_id');
        hiddenInputs.forEach(input => {
            input.value = id;
        });
    }

    if (document.readyState === 'complete') {
        injectClientIdToForms();
    } else {
        window.addEventListener('load', injectClientIdToForms);
    }
})();

Step 2: Structure the Self-Reported Attribution Form Field

The design of the self-reported attribution question is critical. Standard dropdown menus (e.g., "Google", "LinkedIn", "Other") fail because they force users into predetermined buckets. The user will almost always select the easiest option ("Google" or "Other"), which destroys the value of the qualitative data.

<!-- B2B Enterprise Demo Request Form Snippet -->
<form id="lead-capture-form" action="/submit-lead" method="POST">
    <div class="form-group">
        <label for="email">Work Email</label>
        <input type="email" id="email" name="email" required placeholder="name@company.com">
    </div>

    <div class="form-group">
        <label for="sra-source" class="sra-label">
            How did you first hear about us?
            <span class="sub-label">Please be as specific as possible (e.g., "LinkedIn post by Daniel Leira", "Podcast episode #45").</span>
        </label>
        <input 
            type="text" 
            id="sra-source" 
            name="self_reported_source" 
            required 
            placeholder="e.g., LinkedIn, podcast, peer recommendation..."
            autocomplete="off"
        >
    </div>

    <input type="hidden" id="ga_client_id" name="ga_client_id" value="">
    <button type="submit" class="submit-btn">Request Demo</button>
</form>

Step 3: Unify the Data in Google BigQuery

Once the lead is submitted, the form data (including the self_reported_source and ga_client_id) is stored in your CRM (such as HubSpot or Salesforce). You must stream this CRM data to your data warehouse (e.g., BigQuery) alongside your raw GA4 export data.

The SQL query below demonstrates how to stitch these two data sources together. It matches the lead record with the corresponding GA4 session history to show the software attribution data side-by-side with the user's self-reported discovery source.

-- Matches CRM lead submissions with GA4 raw event export data using Client ID
WITH ga4_session_attribution AS (
  SELECT
    user_pseudo_id AS client_id,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id,
    MIN(timestamp_micros(event_timestamp)) AS session_start_time,
    ARRAY_AGG(
      STRUCT(
        traffic_source.source AS source,
        traffic_source.medium AS medium,
        traffic_source.name AS campaign
      ) ORDER BY event_timestamp ASC LIMIT 1
    )[OFFSET(0)] AS session_traffic
  FROM
    `your-gcp-project.analytics_123456789.events_*`
  WHERE
    _TABLE_SUFFIX BETWEEN 
      FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)) 
      AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
  GROUP BY
    client_id,
    session_id
),
crm_leads_data AS (
  SELECT
    lead_id,
    email,
    created_at AS lead_created_time,
    ga_client_id,
    self_reported_source
  FROM
    `your-gcp-project.crm_database.leads`
  WHERE
    ga_client_id IS NOT NULL
    AND created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
),
joined_attribution AS (
  SELECT
    l.lead_id,
    l.email,
    l.lead_created_time,
    l.self_reported_source,
    ga.session_traffic.source AS software_source,
    ga.session_traffic.medium AS software_medium,
    ga.session_traffic.campaign AS software_campaign,
    ROW_NUMBER() OVER (
      PARTITION BY l.lead_id 
      ORDER BY ABS(TIMESTAMP_DIFF(l.lead_created_time, ga.session_start_time, SECOND)) ASC
    ) as session_rank
  FROM
    crm_leads_data l
  LEFT JOIN
    ga4_session_attribution ga
  ON
    l.ga_client_id = ga.client_id
)
SELECT
  lead_id,
  email,
  lead_created_time,
  self_reported_source AS humint_source,
  IFNULL(software_source, 'No GA Session Found') AS sigint_source,
  IFNULL(software_medium, 'No GA Session Found') AS sigint_medium,
  IFNULL(software_campaign, 'No GA Session Found') AS sigint_campaign
FROM
  joined_attribution
WHERE
  session_rank = 1
ORDER BY
  lead_created_time DESC;

Data Harmonization: Categorizing Free-Text Inputs at Scale

Because the self-reported field is open-ended, buyers will input variations of the same source (e.g., "LinkedIn", "linkedin", "post by Daniel", "Daniel Leira's profile", "daniel on li").

At a low lead volume (under 100 leads per month), this data can be manually reviewed and categorized by a RevOps specialist. At enterprise scale, you must programmatically clean and bucket these inputs.

You can run automated parsing scripts using SQL expressions or API calls to LLMs to evaluate and categorize responses. The script below outlines a basic SQL-based bucket classifier used to clean the raw input for high-level reporting:

-- SQL classification logic to clean raw SRA text inputs into high-level categories
CREATE TEMP FUNCTION CategorizeSRA(raw_text STRING) AS (
  CASE
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(linkedin|li|post by|feed)') THEN 'LinkedIn / Social'
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(podcast|episode|show)') THEN 'Corporate Podcast'
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(referred|friend|colleague|slack|recommend|slack|mouth)') THEN 'Word of Mouth / Communities'
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(google|search|organic search|seo)') THEN 'Search Engine'
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(event|summit|conference|booth)') THEN 'Events / Trade Shows'
    WHEN REGEXP_CONTAINS(LOWER(raw_text), r'(newsletter|email)') THEN 'Email Marketing'
    ELSE 'Other / Unclassified'
  END
);

Case Study: The Deceptive Pipeline Fallacy

To understand how this system operates in practice, let us examine the case of a developer-tooling SaaS brand that scaled its annual recurring revenue (ARR) from $10M to $25M.

The Intervention

Before executing a planned 50% paid ads budget expansion, the marketing team worked with Gotham to implement the Hybrid Attribution Engine. We deployed the Client ID extraction script and introduced a mandatory self-reported field to the registration form.

For three months, we collected both software data and user-reported insights. The differences between the datasets were stark:

Lead ID User-Reported Source (HUMINT) GA4 Source (SIGINT) Real Path Analysis
#1092 "Co-worker sent me a link to your Docker podcast episode on Slack." Direct / None The user visited the site directly after listening, leaving no referrer data.
#1104 "Saw Daniel's post about database sharding benchmarks on LinkedIn." Organic Search The user read the post, then searched the brand name on Google.
#1120 "Met your team at the KubeCon booth." Google / Paid Search The user came home, searched the brand, and clicked a paid brand ad.

The Findings

When the data was consolidated at the end of the quarter, the aggregated comparison revealed the following:

GA4 Software Attribution (SIGINT)

Paid Search55%
Organic Search35%
Direct / Other10%

Self-Reported Attribution (HUMINT)

Podcast / Content32%
LinkedIn Organic28%
Word of Mouth & Communities20%
Events / Booths16%

Over 80% of the conversions attributed to search ads and direct traffic by GA4 were originally created in dark social channels (podcasts, LinkedIn posts, peer recommendations). The paid search ads did not create the customer's intent to buy; they merely served as the door the customer walked through when they were ready to convert.

Armed with this hybrid data, the CMO successfully argued against the 50% paid ads budget expansion. Instead, they:

  1. Maintained a baseline budget for Paid Brand Search to defend the brand name against competitors.
  2. Redirected 45% of the intended ad spend into production resources for the technical podcast and scaling engineering-focused LinkedIn content.
  3. Saved the company from over-allocating budget to paid ads that had hit point of diminishing returns.

Over the next two quarters, qualified pipelines increased by 42%, while the overall customer acquisition cost (CAC) fell by 28%.

Frequently Asked Questions

Will adding a mandatory free-text question lower our form conversion rates?

No. Multiple independent tests in B2B enterprise sales funnels have shown that adding a single, thoughtfully designed open text field to high-intent forms (like demo requests or pricing inquiries) has a negligible impact on conversion rates (typically under 1.5%). Buyers who are ready to speak with a sales representative for an enterprise software solution are not deterred by a question asking how they discovered the brand.

How do we handle blank, low-effort, or nonsensical answers (e.g., "Google", "a friend", "asdf")?

Low-effort answers like "Google" or "online" are valuable indicators in their own right. When a user writes "Google" in the SRA field and GA4 says Organic Search, you have perfect alignment. When a user writes "Slack community" but GA4 says Paid Search, you know the paid ad captured a user who was influenced by peer recommendations. We recommend treating search-related answers as valid data points, while filtering out nonsense entries like "asdf" into an "Unclassified" category.

What is the impact of user memory bias on self-reported data?

Human memory is imperfect. A user might discover your product via LinkedIn, read your blog for three months, listen to your podcast, and then write "blog post" on the form. This is called recency bias. However, this bias is actually a strategic advantage: it tells you what touchpoint made the most lasting impression on the buyer's mind. Traditional software attribution has a far worse bias: technical tracking bias. It assumes that the last link clicked is the only thing that influenced the sale. We prefer the strategic bias of the human mind over the technical bias of a cookie tracking script.

Conclusion: Take Control of Your Attribution Strategy

If you continue to run B2B enterprise marketing with last-touch software models, you are actively delegating your strategic budget decisions to a web browser's cookie storage settings. You will continue to over-spend on search ads that capture existing demand, and you will starve the creative engines that build your pipeline.

The transition to a hybrid attribution model requires an investment in both data engineering and team alignment. However, the returns on this investment are immediate: clarity on what marketing channels are driving value, a defensible budget strategy for the boardroom, and a lower, more sustainable CAC.

RECONCILE YOUR ACQUISITION STACK

Unify Your SIGINT & HUMINT Pipeline

At Gotham Growth Engine, we specialize in auditing RevOps stacks, setting up BigQuery data pipelines, and implementing hybrid attribution engines for mid-market and enterprise B2B SaaS companies.

Request Attribution Audit  ↗
← Back to Strategy Playbooks
© 2026 Gotham Group.