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:
- Install GA4 on HubSpot
- Verify base GA4 tracking is working in Realtime reports
- 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:
- Video plays (embedded videos)
- Outbound link clicks
- Scroll depth
- Time on page
Tracking HubSpot Form Submissions
HubSpot forms fire a JavaScript event when submitted. Capture this for GA4.
Method 1: Form Event Listener (Recommended)
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
- Open GA4 → Admin → DebugView
- Submit a form on your HubSpot site
- Verify
generate_leadevent appears in DebugView - 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>
Outbound Link Clicks
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 Admin → DebugView in GA4
- Enable debug mode (add
debug_mode: trueto 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:
- GA4 base code is installed and working
- Event syntax is correct (check console for errors)
- Event names follow GA4 naming conventions (lowercase, underscores)
- 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
- Set up Ecommerce Tracking - If using HubSpot Commerce
- Install GTM - For easier event management
- Configure GTM Data Layer - Pass HubSpot data to GTM
For general GA4 event concepts, see GA4 Event Tracking Guide.