How to Integrate GA4 with HubSpot Using AttributeIQ (Step-by-Step)

    Muiz Thomas

    Muiz Thomas, Founder & CEO, AttributeIQ

    · 9 min read

    Key Takeaways
    • Connecting GA4 to HubSpot natively only captures top-of-funnel pageviews inside a data silo. Anonymous web traffic never maps back to contacts, deals, or closed-won revenue.
    • Closing that loop requires persistent identity stitching. The GA4 client ID gets captured during a session, written into the HubSpot contact record, and matched against a continuous feed of deal-stage data.
    • Building this bridge manually through custom GTM setups tends to be a maintenance liability. Hidden form fields and manual QA routinely break the moment a form, script, or page layout changes.
    • AttributeIQ handles all of this with a single script and a sync that runs every six hours, so a contact’s entire path, from first visit through to closed deal, stays visible as one journey instead of fragments across GA4 and HubSpot.

    GA4 HubSpot Integration: Native Capabilities and Attribution Gaps

    HubSpot’s own knowledge base is explicit about the scope of its native integration: you add a GA4 Measurement ID (or a full tracking snippet) to your site settings, and HubSpot injects that code into your HubSpot-hosted pages. If you’re on Marketing Hub Starter without a Content Hub subscription, you can only use the Measurement ID method; adding the full tracking code to your site header HTML requires Marketing Hub Professional or Enterprise.

    That setup is useful, but it’s also narrow. At best, it gives you visitor-level reporting inside GA4, but you can’t connect that activity to real people or revenue outcomes.

    If your goal is to follow someone from a blog visit all the way to a closed deal, you need a couple of additional pieces that the native integration doesn’t handle on its own:

    #

    Requirement

    What it means in practice

    1

    A persistent identifier tied to a HubSpot contact record

    GA4 assigns every visitor a client ID, a pseudonymous string that identifies a browser across sessions. On its own, this ID lives inside Google Analytics and has no connection to a name, email, or company. To use it for attribution, that client ID needs to land on the matching HubSpot contact record, typically the moment someone fills out a form.

    2

    Deal-stage data flowing back out of HubSpot

    Once a contact’s client ID is on their record, you need their deal stage, deal value, and lifecycle stage synced continuously, so a journey that started as an anonymous blog visit six months ago can be traced all the way to Closed Won today.

    Building this manually means engineering time and ongoing maintenance most marketing teams don’t have. AttributeIQ sets up both pieces automatically during onboarding, then keeps them synced without anyone touching HubSpot’s backend.

    Recommended Reading: Why HubSpot’s Multi-Touch Attribution Isn’t Enough on Its Own

    Pre-Integration Checklist for GA4 and HubSpot Attribution Setup

    This checklist covers AttributeIQ’s GA4-HubSpot integration, not HubSpot’s native tracking setup. The two have different requirements, and this page assumes you’re using AttributeIQ’s

    #

    Check

    Why it matters

    1

    AttributeIQ account created (Pro plan)

    The GA4-HubSpot sync runs on Pro, which starts at £149/month. A free trial is available, so you can confirm the integration behaves as expected before committing to a subscription. Do this first, everything below assumes the account already exists.

    2

    Admin/editor access confirmed

    AttributeIQ needs to authorise an OAuth connection to both platforms and create a contact property in HubSpot during onboarding. Without admin rights on your GA4 property and your HubSpot account, the connection will fail partway through.

    3

    Accept that tracking only runs forward

    AttributeIQ starts tracking a contact’s GA4 client ID from the moment the connection goes live, it does not retroactively reconstruct months of dark journeys for contacts who already exist in your CRM.

    GA4 + HubSpot Integration via AttributeIQ: 5 Steps to Revenue Attribution

    GA4 and HubSpot don’t connect by default, so most teams never get past surface-level reporting, this five-step guide shows how to turn both into revenue attribution.

    Step 1: Connect Your GA4 Property to AttributeIQ

    When you create an AttributeIQ account, the onboarding flow starts with a GA4 connection.

    Everything downstream, the client ID capture, the HubSpot sync, the Pipeline Intelligence reporting, depends on this being the right property.

    2

    Select Your GA4 Property

    nexa-marketing (GA4)
    nexa-marketing (GA4 Property)Current
    nexa-prod (GA4 Property)
    nexa-staging (GA4 Property)
    client-brightwave (GA4 Property)
    Continue
    or+ Add another property

    Once you’ve selected your property, AttributeIQ automatically starts syncing your raw GA4 event data from BigQuery. There’s no implementation project to manage or tracking changes to deploy. Most teams are connected and waiting for their first data sync within 24 hours of signing up.

    Step 2: 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 requests read access to your HubSpot contacts and deals, which is all it needs. The only thing it writes to HubSpot is a single contact property, covered next, so there’s no risk to your existing 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 3 carefully before assuming everything worked.

    Step 3: 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 2, 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 4 won’t be able to write to it, and the whole chain breaks down.

    Step 4: 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.

    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 5: Form Setup (HubSpot Embedded vs Custom HTML)

    If you use HubSpot embedded forms (the standard hbspt.forms.create() approach), you’re done with the script from Step 4. 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’s 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’s HubSpot Integration docs.

    What Happens Next

    Once contacts start syncing with a populated ga4_client_id, AttributeIQ has what it needs to stitch a visitor’s anonymous GA4 journey to their HubSpot record and, from there, to whatever deal that contact eventually rolls into.

    Give the sync a few hours after your first contacts come through, then check Settings → Integrations → HubSpot for the contact count and sync timestamp. If that number matches what you’d expect from your form volume, the integration is working end to end.

    What You Get Once GA4 and HubSpot Are Connected in AttributeIQ

    The integration itself takes about fifteen minutes. What follows is a connected view of GA4 behaviour and HubSpot data that shows how pipeline is actually influenced.

    Pipeline Attribution by Page

    Someone on the leadership team eventually asks which content is actually driving revenue, and most marketing teams answer with traffic and vibes. Not because they’re bad at their jobs, but because nobody’s ever connected the dots from a specific page to a specific deal.

    With AttributeIQ’s Page Influence, you can see every page a contact touched before becoming a deal, how much that deal is worth, and where it sits in the funnel right now.

    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

    In this example, the table below shows how your content impacts revenue. Every page is tied to three core metrics: the number of converters who interacted with it, the total pipeline it influenced, and where it typically sits in the buyer’s journey (first touch, middle, or closing).

    Take /blog/cmms-vs-spreadsheets versus /pricing: the blog post brought in 312 eventual converters, far more than the 198 who hit the pricing page. But when you look at the pipeline, the blog only influenced £189k compared to the pricing page’s £312k. High traffic doesn’t always mean high value, and standard analytics tools like GA4 miss that nuance completely because they can’t tie a pageview to a closed deal.

    When you click into a specific page, you see the real buyer behavior behind those metrics. A typical journey might start on that CMMS blog post, loop back to the homepage, navigate to your security docs, and end in a demo request that closes for £3.5k. Instead of that first blog visit getting lost as a single line item in a traffic report, you can finally see its exact role in a multi-touch revenue journey.

    Recommended Reading: Content-to-Revenue Tracking Using GA4, HubSpot, and AttributeIQ

    Journey Explorer with Real Contact Names

    Journey Explorer without HubSpot connected already shows you the anonymous GA4 client ID of every converting visitor and the exact sequence of pages they visited before converting. That’s useful on its own. With HubSpot connected, those anonymous IDs resolve to actual people, their company, and the specific deal they’re now sitting inside.

    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

    In most setups, once a form is submitted, the journey effectively stops. But here, you can still see what they do next, like a prospect reopening a case study during contract review.

    Deal Tracking and Real-Time Alerts

    The Deal Tracker is probably the feature that most directly changes day-to-day sales-marketing alignment the most, because it puts your entire HubSpot pipeline, every contact, every stage, every deal value, next to their real-time web behaviour instead of in a separate tab nobody checks.

    On top of that, you can wire up alerts, get a Slack ping when an SQL visits pricing three times, when a known opportunity revisits a specific case study, or a weekly digest of who in the pipeline has 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

    Board Reporting with Pipeline Context

    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.

    AttributeIQAttributeIQ

    Board Summary

    Export a board-ready summary of marketing’s influence on pipeline and revenue.

    Q2 2026 · Board Summary · 1 Apr 2026 – 30 Jun 2026

    Qualified Pipeline

    £4.1M

    from 47 contacts

    Total Revenue

    £1.27M

    from 14 closed deals

    Avg Closed Deal

    £90.7k

    from 14 closed deals

    Top Account

    Nexa

    £340k influenced

    Channel Breakdown
    Organic / Google
    £1.68M41%
    Paid / Google
    £902k22%
    LinkedIn / Social
    £697k17%
    Direct
    £451k11%
    Referral
    £246k6%
    Email
    £123k3%
    Top 5 Content in Closed Deals
    PageDeals ContainingRevenue Influenced
    /pricing14/14 (100%)£1.27M
    /case-study/10m-arr11/14 (79%)£1.01M
    /blog/cmms-vs-spread..9/14 (64%)£823k
    /homepage14/14 (100%)£1.27M
    /b2b-saas-seo-audit g..7/14 (50%)£635k

    This is the report most marketing leaders end up assembling by hand every quarter anyway, pulled from three different tools and stitched together the night before the meeting. Here it’s already built from the same data everyone downstream has been looking at, which means the numbers in the boardroom match the numbers the team has actually been working from all along.

    Why Not Just Use HubSpot’s Native Integration or Google Tag Manager?

    You might be wondering why you need a dedicated platform. Here is exactly how our solution stacks up against doing it yourself or relying on HubSpot’s basic native features.

    Native GA4-HubSpot

    GTM/DIY Client ID

    AttributeIQ

    What It Captures
    Pageviews and sessions on HubSpot-hosted content only. Anything outside HubSpot’s own pages, your marketing site, a docs subdomain, isn’t tracked at all.
    The GA4 client ID on the contact record, and nothing past that. You still need to build the reporting layer that turns an ID into a journey.
    The full picture: page visits, GA4 client ID, resolved contact identity, deal stage, and revenue, all linked to the same journey automatically.
    Setup Time
    A few minutes to drop in a Measurement ID, assuming you’re on the right Hub tier.
    Hours if you already know GTM well. Longer, plus a learning curve, if you’re setting up tags and triggers for the first time.
    Under 15 minutes, GA4 and HubSpot both connected in the same onboarding flow.
    Cost
    Free, but the full tracking snippet requires Marketing Hub Professional or Enterprise, from $890/month.
    Free tool, but developer or agency time to build and maintain it adds up.
    From £149/month on Pro, GA4 and HubSpot sync included in the same plan.
    Reaches Deal-Level Attribution?
    No. It stops at session data with no link to a contact or deal record.
    Only partially; leaves your team to manually extract data, stitch spreadsheets, and build complex reporting models on top.
    Yes, right out of the box; directly connects individual marketing touchpoints to actual CRM revenue and closed-won deals.
    Requires GTM or a Developer?
    No.
    Yes, GTM knowledge or developer time to set up and maintain.
    No.
    Works on HubSpot’s Free CRM Tier?
    Yes.
    Yes.
    Yes.

    Once GA4 and HubSpot Are Connected: Activate Revenue Attribution

    If you’re already using GA4 and HubSpot but haven’t connected them properly yet, the fastest way forward is simply to activate the bridge and validate that data is flowing end to end.

    1. 1.Start a 14-day free trial of AttributeIQ on the Pro plan. You get full feature access from day one, so there’s nothing to unlock later once you decide it’s working.
    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, then check the contact count against what you’d expect from recent form volume.

    Once that first sync completes, Page Influence and Journey Explorer start populating with real data straightaway. No separate implementation phase, no waiting on a data team to build something on top. The entire point of this setup is closing the distance between content and a closed deal, and once the connection is live, that distance closes on its own from every form fill forward.

    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.