How to Connect HubSpot Pipeline Data to Every Marketing Touchpoint

    Muiz Thomas

    Muiz Thomas, Founder & CEO, AttributeIQ

    · 9 min read

    Here’s a situation I see constantly managing B2B marketing: you open HubSpot and you’ve got a deal that just moved to Contract Sent. You know which SDR touched it, you know the company, you know the value. What you don’t know, and what nobody in the room can tell you, is what happened before that first form fill. Which blog post brought them in. Which case study they came back to three days later. Which pricing page visit preceded the call where they said yes.

    HubSpot doesn’t have that data. GA4 does, but only if you’ve connected the two properly.

    This post is a complete walkthrough of how to do that using AttributeIQ, not conceptually, but practically, in a way that actually works across client accounts, without needing an ops team or a six-month implementation.

    The Data Infrastructure Required for HubSpot Pipeline Attribution

    Before we get into what to do with the data, it’s worth being precise about the infrastructure that makes this possible. There are three components.

    #

    Requirement

    What it means in practice

    1

    GA4 as your raw event source

    GA4 tracks every page visit, every session, every source, down to the individual browser session via client IDs. This is your behavioral data layer. The problem is GA4’s interface shows you aggregates and samples. The value is in the raw event stream, which you access properly via BigQuery export.

    2

    Identity resolution

    Connecting the GA4 client ID to the HubSpot contact is the lynchpin. GA4 assigns every browser a client ID. HubSpot assigns every contact a record. To connect them, you need to capture the GA4 client ID at the point of form submission and write it into a HubSpot contact property. Once you’ve done that, every anonymous visitor history in GA4 becomes attributable to a named contact in HubSpot.

    3

    A layer that joins the two and makes it readable

    Having the data linked is not the same as having it useful. You need something that traces back from conversion events to first touch, maps the page sequence, and connects it to the deal value and stage sitting in HubSpot. In practical terms, that means matching GA4 activity to CRM contacts through form submissions or other identifiers, then tracing the path from first visit to closed deal.

    This is the architecture that tools like AttributeIQ are built on. The HubSpot integration works by creating a ga4_client_id custom property in your HubSpot account, automatically, during onboarding, and then using a lightweight tracking script on the client’s site to populate that property whenever a contact submits a form.

    From that point, every new contact is tied to their full GA4 journey. The sync runs every six hours, so deal stage changes in HubSpot shown in the attribution dashboard without any manual exports.

    See which content pieces
    actually influenced your deals.

    AttributeIQ shows page-level pipeline attribution natively over your existing GA4 and HubSpot stack, live within 24 hours.

    Try 14 days for free →

    Nexa Corp · Journey

    Best MTA tools 2026

    Blog · Organic · Day 1

    Attribution guide

    Blog · Organic · Day 12

    Case study: Intercom

    Blog · Organic · Day 28

    Pricing page

    Direct · Day 31

    AttributeIQ + HubSpot: Complete Five-Step Integration Walkthrough

    AttributeIQ’s HubSpot integration is genuinely straightforward, the full documentation walks through it step by step, but I want to go deeper on each part, including what’s happening under the hood and what to watch out for.

    Before you start: this integration requires the Pro plan (£149/month). If you’re on Starter, you get full multi-touch attribution but without the HubSpot deal matching. Given what Pipeline Intelligence unlocks, the Pro plan is the one you want if revenue is the goal.

    Step 1: Connect HubSpot via OAuth

    Go to Settings → Integrations → HubSpot inside AttributeIQ and click Connect HubSpot. You’ll be taken through a standard OAuth flow, authorise access, get redirected back, and you’ll see your portal ID confirmed and the status showing “Connected.”

    Property

    NexaPathora
    HS

    HubSpot CRM

    Portal ID: 146264324

    ConnectedDisconnect

    Sync Contacts

    Pulls contacts with a ga4_client_id property and their associated deals into your account. Last synced 6/7/2026 (96 contacts).

    Contacts sync automatically every 6 hours.

    This is a one-time step. AttributeIQ will request read access to your HubSpot contacts and deals, which is all it needs. It’s not writing anything to HubSpot except one contact property (covered in Step 2), so you don’t need to worry about it touching your pipeline data.

    One thing worth flagging: if your HubSpot portal has property-level restrictions set up (common in more established RevOps setups), the automatic property creation in Step 2 may fail silently. Read Step 2 carefully before assuming everything worked.

    Step 2: The ga4_client_id Contact Property

    Every GA4 session has a unique client ID, a string that identifies a browser/device combination across visits. If you can write that ID into a HubSpot contact property at the moment someone submits a form, you now have a thread that connects their CRM record to their entire session history in GA4.

    When you complete Step 1, AttributeIQ automatically creates a contact property in HubSpot called ga4_client_id (internal name, must be exactly this). In most cases, this just works. If it doesn’t,  you can create it manually:

    • HubSpot → Settings gear → Properties → Contact properties
    • Create property → Label: GA4 Client ID → Internal name: ga4_client_id
    • Field type: Single-line text → Save

    The internal name is case-sensitive, underscore-separated, no spaces. If it doesn’t match exactly, the tracking script in Step 3 won’t be able to write to it, and the whole chain breaks down.

    Step 3: Add the Tracking Script to Your Site

    The tracking script does three things simultaneously: it sets up GA4 tracking, it captures and persists the GA4 client ID (including a localStorage fallback for users who clear cookies), and it listens for HubSpot form submissions to fire the identity-linking call at the moment of conversion.

    Paste this into your site’s head, the same place you’d normally drop your GA4 snippet, replacing G-XXXXXXXXXX with your actual GA4 Measurement ID.

    Tracking script

    <!-- AttributeIQ + GA4 tracking -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script>
      /* ── Base GA4 setup ──────────────────────────────────────── */
      window.dataLayer = window.dataLayer || [];
      function gtag() { dataLayer.push(arguments); }
      gtag('js', new Date());
      gtag('config', 'G-XXXXXXXXXX');
    
      /* ── Persistent user ID ──────────────────────────────────── */
      function getOrCreatePersistentUserId() {
        let persistentId = localStorage.getItem('persistent_user_id');
        if (!persistentId) {
          persistentId = 'user_' + Date.now() + '_' + Math.random().toString(36).substring(2, 10);
          localStorage.setItem('persistent_user_id', persistentId);
        }
        return persistentId;
      }
      const persistentUserId = getOrCreatePersistentUserId();
    
      /* ── GA4 client ID capture ───────────────────────────────── */
      gtag('get', 'G-XXXXXXXXXX', 'client_id', (id) => {
        window.ga4ClientId = id;
        localStorage.setItem('ga4_client_id', id);
        console.log('AttributeIQ: GA4 Client ID captured:', id);
      });
    
      /* ── Page visit tracking ─────────────────────────────────── */
      function trackPage() {
        const id = localStorage.getItem('ga4_client_id') || window.ga4ClientId;
        if (!id) return;
        fetch('https://attribute-iq.com/api/track/track-page-visit', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ pageUrl: location.href, ga4ClientId: id, persistentUserId: persistentUserId }),
        }).catch(() => {});
      }
    
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', trackPage);
      } else { trackPage(); }
    
    
      /* ── HubSpot embedded form tracking ────────────────────────
         Only relevant if you use HubSpot's embedded forms.
         This handles injecting the GA4 ID into the form payload
         and capturing identity once the form is submitted.
         If you only use custom HTML forms, this block is inactive
         but harmless to leave in.
      ─────────────────────────────────────────────────────────── */
    
      window.addEventListener('message', function(e) {
        if (e.data?.type !== 'hsFormCallback') return;
    
        if (e.data.eventName === 'onBeforeFormSubmit' && Array.isArray(e.data.data)) {
          const id = localStorage.getItem('ga4_client_id') || window.ga4ClientId;
          if (id) {
            e.data.data.push({ name: 'ga4_client_id', value: id });
          }
        }
    
        if (e.data.eventName === 'onFormSubmit') {
          const email = e.data.data?.find(function(f) { return f.name === 'email'; })?.value;
          const id = localStorage.getItem('ga4_client_id') || window.ga4ClientId;
          if (email && id) {
            fetch('https://attribute-iq.com/api/track/capture-identity', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({
                email: email,
                ga4_client_id: id,
                persistent_user_id: persistentUserId,
                property_id: 'default'
              }),
            }).catch(() => {});
          }
        }
      });
    </script>

    How to verify it’s working: Open any page on your site in a browser, hit F12, go to the Console. You should see: AttributeIQ: GA4 Client ID captured: [some string]. If that line isn’t there, either the script isn’t loading or the GA4 measurement ID is wrong. Both are fixable in about thirty seconds.

    If you’re using Google Tag Manager: Drop the script as a Custom HTML tag, set it to fire on All Pages. Make sure it’s firing on DOM Ready or later, if it fires too early, the GA4 client ID callback hasn’t resolved yet and you’ll get intermittent misses.

    Step 4: Form Setup (HubSpot Embedded vs Custom HTML)

    This step splits depending on how your forms are built.

    If you use HubSpot embedded forms (the standard hbspt.forms.create() approach), you’re done with the script from Step 3. The window.addEventListener('message', ...) block at the bottom of that script is specifically listening for HubSpot’s iframe message events, onBeforeFormSubmit injects the GA4 client ID into the form payload before submission, and onFormSubmit fires the identity-capture call. Nothing else to do.

    If you use custom HTML forms that submit to HubSpot’ API directly, common if you built your own design or you’re on a framework like Next.js, you need a slightly different setup. The key things you need to handle manually:

    1. 1.Create or select a HubSpot form in Marketing → Forms that matches your frontend form fields. Add ga4_client_id as a hidden field.
    2. 2.Grab your portal ID and the form GUID from the form URL.
    3. 3.In your form’s submit handler, pull ga4_client_id from localStorage and include it in the fields array when you POST to https://api.hsforms.com/submissions/v3/integration/submit/YOUR_PORTAL_ID/YOUR_FORM_GUID.
    4. 4.Fire the /api/track/capture-identity call in the same handler, passing the email & GA4 client ID.

    The full snippet for this is in the AttributeIQ docs. The summary is: the HubSpot API call gets the ga4_client_id into the contact record, and the capture-identity call links that session to AttributeIQ’s contact graph. Both need to happen. Skip one and you’ll have half a bridge.

    Step 5: Sync Contacts

    Go back to Settings → Integrations → HubSpot, click Sync now, and wait. AttributeIQ will pull every contact in HubSpot that has a ga4_client_id value populated, match them against the session data in GA4, and make them visible in Journey Explorer with their real name, company, and deal information.

    The first sync will only return contacts who have submitted a form since you installed the script in Step 3. That’s expected, the link between a HubSpot contact and their GA4 history only exists from the point of form submission onwards. If you were hoping to retroactively link your existing contacts to their historical journeys, that’s not possible: AttributeIQ needs the ID to have been written to HubSpot at the moment of conversion.

    What You Get Once AttributeIQ and HubSpot Are Connected

    The integration itself takes fifteen minutes. What it unlocks is harder to summarise briefly, so here’s what pipeline attribution actually looks like once it’s running.

    Pipeline Attribution by Page

    Once HubSpot is connected, AttributeIQ’s Page Influence tab becomes the place where you can finally answer “what influenced this deal?” at scale.

    AttributeIQAttributeIQ
    7d
    All conv

    Page Influence

    Track influenced pipeline from first touch to closed deal, page by page.

    Influenced Pipeline

    £2.4M

    +18% vs last period

    Closed Revenue

    £890k

    28% pipeline-to-close

    Top Asset Value

    £312k

    /pricing · last 28d

    Avg. Touchpoints

    5.2

    per converting journey

    Page URLUnique ConvertersInfluenced PipelineRole Distribution
    /pricing
    198£312k
    /case-study/10m-arr
    156£247k
    /blog/cmms-vs-spreadsheets
    312£189k
    /fexa-cmms/work-order-mgmt
    98£134k
    Entry
    Mid-funnel
    Closer

    Each row tells you how many contacts who converted touched that page, what deal value it was associated with, and whether it was acting as an entry point, a mid-funnel asset, or a closer.

    The journey strip expands when you click into a page, showing every recorded conversion sequence for that URL. In this case: a blog post brought them in, they came back via the homepage, read the security docs, visited another blog, hit pricing, and requested a demo.

    Journey Explorer with Real Contact Names

    Journey Explorer without HubSpot connected shows you the anonymous GA4 client IDs of every converting visitor and the exact sequence of pages they visited before converting. Useful.

    With HubSpot connected, those anonymous IDs resolve to actual people, their company, and the deal they’re associated with.

    Daniel Hughes / Orbitly

    daniel@orbitly.io

    Deal

    £24k

    contract sent

    Conversion Event

    demo_request

    Touchpoints

    3

    Duration

    5 days

    First TouchMar 19 · Organic / Google · 4m 22s on page

    /blog/attribution-guide

    TouchpointMar 22 · Direct · 3m 08s on page

    /case-study/10m-arr

    Last TouchMar 24 · Direct · 1m 44s on page

    /pricing

    Conversion!

    demo_request · 24 Mar 2026

    Presentation Scheduled

    Post-conversion visit

    /case-study/enterprise-roi

    Contract Sent

    You can also see post-conversion activity: the pages a contact visited after filling in a form and the deal stage progression. This is the part most attribution tools don’t touch. Knowing that a contact revisited a case study during the contract stage is genuinely useful intelligence for the sales team.

    Deal Tracking and Real-Time Alerts

    The Deal Tracker is probably the feature that most directly changes day-to-day sales-marketing alignment. You can see your entire HubSpot pipeline, every contact, every stage, the associated deal value, alongside their real-time web behaviour.

    You can also set up a Slack alert for when an SQL visits your pricing page. Set up an alert for when a known Opportunity visits a specific case study. Set up a weekly digest of which contacts in your pipeline have gone quiet for two weeks.

    Alert Rules

    2 active

    SQL visits /pricing three times

    Immediate · Slack

    URL contains /pricingQualified contactsSends immediately
    Edit

    Any contact visits /demo

    Immediate · Slack

    URL contains /demoAll contactsSends immediately
    Edit

    Qualified contacts inactive 14+ days

    Weekly on Monday · Slack

    Edit

    The alert logic is flexible: target all contacts, qualified pipeline only, or specific named contacts. Set it to fire immediately or batch it into a weekly summary. The point is that your sales team gets notified while interest is demonstrably warm, which is a very different conversation to have than the one you get when you’re following up cold three days after the signal has passed.

    Board Reporting with Pipeline Context

    If you’re on Pro, the Board Summary pulls together influenced pipeline, closed revenue, top-performing assets, and channel performance into a single exportable view, with a PPTX export option for when you need to drop it into a QBR deck without rebuilding it from scratch.

    SLIDE 01Cover + KPIs

    Pipeline KPIs

    Qualified pipeline, closed revenue, avg deal, top account

    SLIDE 02Attribution

    Channel Breakdown

    Revenue share by channel: organic vs paid vs referral

    SLIDE 03Content ROI

    Top Content

    Which pages appeared in every won deal, ranked by revenue

    SLIDE 04Executive

    Board Narrative

    Your editable commentary, formatted for leadership

    The Fastest Way to Get Pipeline Attribution Running

    If you’re already using HubSpot and GA4 and you don’t have this connection in place, the fastest path forward is:

    1. 1.Start a 14-day free trial of AttributeIQ on the Pro plan, you get full feature access
    2. 2.Complete Steps 1–5 above. Budget fifteen minutes; it’ll probably take ten.
    3. 3.Submit a test form on your site and confirm the ga4_client_id field populates in HubSpot.
    4. 4.Run your first sync.

    From there, the first thing worth doing is filtering Deal Tracker to your Closed Won deals and spending twenty minutes looking at what those journeys actually looked like. You’ll see patterns you didn’t expect, content that’s working harder than you realised, and probably at least one channel that’s been getting either too much or not enough credit for months.

    Muiz Thomas, Founder & CEO of AttributeIQ
    Author
    Muiz Thomasin
    Founder & CEO, AttributeIQ
    Muiz is the founder of AttributeIQ, a multi-touch attribution platform for B2B marketing teams, and GrowUp, a B2B search agency. He started building attribution tooling because he got tired of writing “directional.” in client reports as a way of saying “I can’t actually prove this.” He works mostly with SaaS, construction tech, and enterprise software teams, and has helped connect marketing programmes to £5M+ in qualified pipeline.