Google Analytics 4 Event Tracking on HubSpot | Blue Frog Docs

Google Analytics 4 Event Tracking on HubSpot

Track HubSpot-specific events in GA4 including forms, CTAs, meeting bookings, and custom interactions.

Google Analytics 4 Event Tracking on HubSpot

HubSpot has unique features (forms, CTAs, meetings) that require custom event tracking to capture in Google Analytics 4. This guide covers HubSpot-specific event implementation.

Prerequisites

Before implementing event tracking:

  1. Install GA4 on HubSpot
  2. Verify base GA4 tracking is working in Realtime reports
  3. Have access to HubSpot Site Header HTML or template code

HubSpot-Specific Events to Track

Priority Events

Event HubSpot Feature Business Value
Form Submissions HubSpot Forms Lead generation
CTA Clicks HubSpot CTAs Engagement tracking
Meeting Bookings Meetings Tool Conversion tracking
Chat Interactions HubSpot Chat Support engagement
File Downloads HubSpot Files Content engagement

Standard Web Events

Also consider tracking:

Tracking HubSpot Form Submissions

HubSpot forms fire a JavaScript event when submitted. Capture this for GA4.

Add this code to Site Header HTML after your GA4 config:

<script>
  // Track HubSpot form submissions
  window.addEventListener('message', function(event) {
    if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
      var formData = event.data.data;
      var formGuid = event.data.id;

      // Send to GA4
      gtag('event', 'generate_lead', {
        'form_id': formGuid,
        'form_name': formData.formGuid || 'unknown',
        'page_location': window.location.href,
        'page_title': document.title
      });

      console.log('GA4 Form Event Sent:', formGuid);
    }
  });
</script>

Method 2: GTM Custom Event (If Using GTM)

If you're using Google Tag Manager:

1. Add Data Layer Push to Site Header HTML:

<script>
  window.addEventListener('message', function(event) {
    if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        'event': 'hubspot_form_submit',
        'formId': event.data.id,
        'formType': 'hubspot',
        'pageUrl': window.location.href
      });
    }
  });
</script>

2. Create Trigger in GTM:

  • Trigger Type: Custom Event
  • Event Name: hubspot_form_submit

3. Create GA4 Event Tag:

  • Tag Type: GA4 Event
  • Event Name: generate_lead
  • Event Parameters:
    • form_id: \{\{dlv - formId\}\}
    • form_type: hubspot
  • Trigger: hubspot_form_submit

See GTM Data Layer for more details.

Method 3: HubSpot Form Callbacks (Per-Form)

For individual forms with specific tracking needs:

<script>
  window.addEventListener('message', function(event) {
    if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
      var formId = event.data.id;

      // Track different forms with different event names
      if (formId === 'your-contact-form-guid') {
        gtag('event', 'contact_form_submit', {
          'form_destination': 'sales',
          'value': 10 // Estimated lead value
        });
      } else if (formId === 'your-demo-form-guid') {
        gtag('event', 'demo_request', {
          'form_destination': 'demo_team',
          'value': 50
        });
      }
    }
  });
</script>

Testing Form Tracking

  1. Open GA4 → AdminDebugView
  2. Submit a form on your HubSpot site
  3. Verify generate_lead event appears in DebugView
  4. Check that parameters (form_id, etc.) are populated

Tracking HubSpot CTA Clicks

Track clicks on HubSpot's native Call-to-Action (CTA) elements.

Method 1: Click Event Listener

Add to Site Header HTML:

<script>
  document.addEventListener('click', function(event) {
    // Check if clicked element is a HubSpot CTA
    var ctaElement = event.target.closest('.cta_button, [class*="hs-cta"], a[data-hs-cta-id]');

    if (ctaElement) {
      var ctaId = ctaElement.getAttribute('data-hs-cta-id') || 'unknown';
      var ctaText = ctaElement.textContent.trim();
      var ctaUrl = ctaElement.href || '';

      gtag('event', 'cta_click', {
        'cta_id': ctaId,
        'cta_text': ctaText,
        'cta_url': ctaUrl,
        'page_location': window.location.href
      });

      console.log('CTA Click Tracked:', ctaText);
    }
  });
</script>

Method 2: Smart CTA Tracking (Personalized CTAs)

Track Smart CTAs that change based on visitor lifecycle:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Track which CTA variant is shown
    var smartCtas = document.querySelectorAll('[class*="hs-cta"][data-hs-cta-variant]');

    smartCtas.forEach(function(cta) {
      var ctaVariant = cta.getAttribute('data-hs-cta-variant');

      // Track CTA impression (shown to user)
      gtag('event', 'view_promotion', {
        'creative_name': ctaVariant,
        'promotion_id': cta.getAttribute('data-hs-cta-id'),
        'promotion_name': cta.textContent.trim()
      });

      // Track click
      cta.addEventListener('click', function() {
        gtag('event', 'select_promotion', {
          'creative_name': ctaVariant,
          'promotion_id': cta.getAttribute('data-hs-cta-id')
        });
      });
    });
  });
</script>

Tracking HubSpot Meeting Bookings

Track when visitors schedule meetings using HubSpot's meetings tool.

Meeting Booking Event Listener

Add to Site Header HTML:

<script>
  // Track HubSpot meeting bookings
  window.addEventListener('message', function(event) {
    // Check for meeting booking success
    if (event.data.meetingBookSucceeded === true) {
      var meetingData = event.data.meetingPayload || {};

      gtag('event', 'meeting_booked', {
        'event_category': 'meetings',
        'event_label': meetingData.meetingType || 'unknown',
        'meeting_duration': meetingData.duration || '',
        'value': 1.00, // Assign value to meeting bookings
        'currency': 'USD'
      });

      console.log('Meeting Booking Tracked');
    }
  });
</script>

Track Meeting Widget Interactions

Track when the meeting widget is opened:

<script>
  window.addEventListener('message', function(event) {
    // Meeting widget opened
    if (event.data.type === 'MEETINGS_OPENED') {
      gtag('event', 'meeting_widget_opened', {
        'event_category': 'meetings',
        'page_location': window.location.href
      });
    }

    // Meeting time selected
    if (event.data.type === 'MEETINGS_TIME_SELECTED') {
      gtag('event', 'meeting_time_selected', {
        'event_category': 'meetings'
      });
    }
  });
</script>

Tracking HubSpot Live Chat

Track interactions with HubSpot's live chat widget.

Chat Event Tracking

<script>
  // Wait for HubSpot conversations API
  window.HubSpotConversations.on('conversationStarted', function(payload) {
    gtag('event', 'chat_started', {
      'event_category': 'engagement',
      'event_label': 'live_chat'
    });
  });

  window.HubSpotConversations.on('conversationClosed', function(payload) {
    gtag('event', 'chat_closed', {
      'event_category': 'engagement',
      'session_duration': payload.sessionDuration || 'unknown'
    });
  });

  // Track when user sends first message
  window.HubSpotConversations.on('userMessage', function(payload) {
    gtag('event', 'chat_message_sent', {
      'event_category': 'engagement',
      'is_first_message': payload.isFirstMessage ? 'yes' : 'no'
    });
  });
</script>

Note: Ensure conversations API is loaded:

<script>
  // Wait for Conversations to be ready
  window.hsConversationsOnReady = [function() {
    console.log('HubSpot Conversations Ready');
    // Add event listeners here
  }];
</script>

Tracking File Downloads

Track when users download files hosted in HubSpot.

File Download Tracking

<script>
  document.addEventListener('click', function(event) {
    var link = event.target.closest('a');

    if (link && link.href) {
      var href = link.href;

      // Check if it's a HubSpot file URL or common file extension
      var isFile = /\.(pdf|docx?|xlsx?|pptx?|zip|csv)$/i.test(href) ||
                   href.includes('hubspot.net/hub/') ||
                   href.includes('hs-fs.hubspot.net/');

      if (isFile) {
        var fileName = href.split('/').pop().split('?')[0];

        gtag('event', 'file_download', {
          'file_name': fileName,
          'file_url': href,
          'link_text': link.textContent.trim(),
          'page_location': window.location.href
        });

        console.log('File Download Tracked:', fileName);
      }
    }
  });
</script>

Tracking Video Interactions

Track video plays on HubSpot pages (YouTube, Vimeo, HubSpot Video).

YouTube Video Tracking

<script>
  // Load YouTube IFrame API
  var tag = document.createElement('script');
  tag.src = "https://www.youtube.com/iframe_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  // Track YouTube videos
  function onYouTubeIframeAPIReady() {
    var videos = document.querySelectorAll('iframe[src*="youtube.com"]');

    videos.forEach(function(videoElement) {
      new YT.Player(videoElement, {
        events: {
          'onStateChange': function(event) {
            var videoTitle = event.target.getVideoData().title;

            if (event.data === YT.PlayerState.PLAYING) {
              gtag('event', 'video_start', {
                'video_title': videoTitle,
                'video_provider': 'youtube'
              });
            }

            if (event.data === YT.PlayerState.ENDED) {
              gtag('event', 'video_complete', {
                'video_title': videoTitle,
                'video_provider': 'youtube'
              });
            }
          }
        }
      });
    });
  }
</script>

HubSpot Video Player Tracking

<script>
  // Listen for HubSpot video player events
  window.addEventListener('message', function(event) {
    if (event.data.type && event.data.type.includes('video')) {
      var eventName = event.data.type;
      var videoData = event.data;

      if (eventName === 'video-played') {
        gtag('event', 'video_start', {
          'video_title': videoData.videoName || 'unknown',
          'video_provider': 'hubspot',
          'video_id': videoData.videoId
        });
      }

      if (eventName === 'video-ended') {
        gtag('event', 'video_complete', {
          'video_title': videoData.videoName || 'unknown',
          'video_provider': 'hubspot',
          'video_id': videoData.videoId
        });
      }
    }
  });
</script>

Tracking Custom Interactions

Scroll Depth Tracking

Track how far users scroll on HubSpot blog posts or landing pages:

<script>
  var scrollMilestones = [25, 50, 75, 100];
  var firedMilestones = [];

  window.addEventListener('scroll', function() {
    var scrollPercent = Math.round(
      ((window.scrollY + window.innerHeight) / document.documentElement.scrollHeight) * 100
    );

    scrollMilestones.forEach(function(milestone) {
      if (scrollPercent >= milestone && firedMilestones.indexOf(milestone) === -1) {
        firedMilestones.push(milestone);

        gtag('event', 'scroll', {
          'event_category': 'engagement',
          'percent_scrolled': milestone,
          'page_location': window.location.href
        });
      }
    });
  });
</script>

Track clicks to external websites:

<script>
  document.addEventListener('click', function(event) {
    var link = event.target.closest('a');

    if (link && link.href) {
      var currentDomain = window.location.hostname;
      var linkDomain = link.hostname;

      // Check if link goes to different domain
      if (linkDomain && linkDomain !== currentDomain && !link.href.includes('hubspot')) {
        gtag('event', 'click', {
          'event_category': 'outbound',
          'event_label': link.href,
          'link_text': link.textContent.trim(),
          'destination_url': link.href
        });
      }
    }
  });
</script>

Enhanced Form Tracking with CRM Data

Pass HubSpot contact properties when forms are submitted:

<script>
  window.addEventListener('message', function(event) {
    if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
      var formGuid = event.data.id;

      gtag('event', 'generate_lead', {
        'form_id': formGuid,
        {% if contact %}
        'lifecycle_stage': '{{ contact.lifecycle_stage }}',
        'contact_status': 'existing',
        'lead_source': '{{ contact.hs_analytics_source }}',
        {% else %}
        'contact_status': 'new',
        {% endif %}
        'page_location': window.location.href
      });
    }
  });
</script>

Complete Event Tracking Implementation

Combined Site Header HTML

Comprehensive tracking code for Site Header HTML:

<!-- Google Analytics 4 with HubSpot Event Tracking -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');

  // 1. FORM SUBMISSIONS
  window.addEventListener('message', function(event) {
    if (event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormSubmitted') {
      gtag('event', 'generate_lead', {
        'form_id': event.data.id,
        'page_location': window.location.href
      });
    }
  });

  // 2. CTA CLICKS
  document.addEventListener('click', function(event) {
    var ctaElement = event.target.closest('.cta_button, [class*="hs-cta"]');
    if (ctaElement) {
      gtag('event', 'cta_click', {
        'cta_text': ctaElement.textContent.trim(),
        'cta_id': ctaElement.getAttribute('data-hs-cta-id') || 'unknown'
      });
    }
  });

  // 3. MEETING BOOKINGS
  window.addEventListener('message', function(event) {
    if (event.data.meetingBookSucceeded === true) {
      gtag('event', 'meeting_booked', {
        'event_category': 'meetings',
        'value': 1.00,
        'currency': 'USD'
      });
    }
  });

  // 4. FILE DOWNLOADS
  document.addEventListener('click', function(event) {
    var link = event.target.closest('a');
    if (link && link.href && /\.(pdf|docx?|xlsx?|pptx?|zip)$/i.test(link.href)) {
      gtag('event', 'file_download', {
        'file_name': link.href.split('/').pop().split('?')[0]
      });
    }
  });
</script>

Testing Your Events

1. Use GA4 DebugView

  • Go to AdminDebugView in GA4
  • Enable debug mode (add debug_mode: true to config)
  • Trigger events on your HubSpot site
  • Verify events appear with correct parameters

2. Use Browser Console

Add console logs to your event code:

gtag('event', 'generate_lead', {
  'form_id': formGuid
});
console.log('Event sent: generate_lead, form_id:', formGuid);

3. Check Network Requests

  • Open DevTools → Network tab
  • Filter by "collect"
  • Trigger event
  • Verify request contains event parameters

4. Verify in GA4 Realtime

  • Open GA4 → Reports → Realtime
  • Trigger events
  • Verify they appear within 30 seconds

Troubleshooting

Events Not Appearing in GA4

See detailed guide: Events Not Firing

Quick checks:

  1. GA4 base code is installed and working
  2. Event syntax is correct (check console for errors)
  3. Event names follow GA4 naming conventions (lowercase, underscores)
  4. No ad blockers interfering with tracking

HubSpot Event Listeners Not Working

Problem: Form/meeting events not triggering

Solutions:

  • Verify event listener is in Site Header HTML (loads on all pages)
  • Check browser console for JavaScript errors
  • Ensure HubSpot form/meeting embed loaded before listener
  • Try wrapping in DOMContentLoaded:
document.addEventListener('DOMContentLoaded', function() {
  // Your event listeners here
});

Parameters Not Passing Correctly

Problem: Event fires but parameters are empty/undefined

Debug:

window.addEventListener('message', function(event) {
  console.log('Message event:', event.data); // See what data is available
  if (event.data.type === 'hsFormCallback') {
    console.log('Form ID:', event.data.id);
    console.log('Form Data:', event.data.data);
  }
});

Next Steps

For general GA4 event concepts, see GA4 Event Tracking Guide.

// SYS.FOOTER