Web Development Blog — Coding, SEO, Domains & CMS Insights

Track HubSpot Forms in GA4, GTM & Meta Pixel: Complete Technical Guide

Written by Niko Yankovsky | March 19, 2026

HubSpot forms are one of the most common lead sources on modern websites — and one of the trickiest things to track correctly. This guide covers every reliable method to capture form submission events in Google Analytics 4 (GA4), Google Tag Manager (GTM), and Meta Pixel (formerly Facebook Pixel), with production-ready code for every scenario.

Why HubSpot Forms Are Hard to Track

HubSpot forms load via iFrame or dynamic JavaScript. Standard GTM "Form Submission" triggers only detect native DOM form events that bubble up to the main window — but events fired inside an iFrame are sandboxed and invisible to these triggers. The solution is a postMessage listener: HubSpot's Forms API broadcasts an hsFormCallback message when a form is submitted, and your tracking code intercepts it from the parent window. This approach works universally across all HubSpot form types.

Part 1: Tracking HubSpot Forms in Google Analytics 4 (GA4)

Method 1: GTM postMessage Listener (Best Practice for HubSpot CMS Pages)

Use this method when your form is managed by HubSpot CMS or when you don't have direct access to the embed code. This is the standard solution for forms on HubSpot-hosted pages and any setup where GTM is already in place.

Step 1: Create the Custom HTML Tag in GTM

In GTM, go to Tags → New → Custom HTML. Paste the following script and set the trigger to All Pages:

What this does: every time a message event fires on the window, the script checks if it originates from HubSpot (type === 'hsFormCallback') and if the form was successfully submitted (eventName === 'onFormSubmitted'). If both conditions are met, it pushes a custom event called hubspot_form_success to the dataLayer, along with the form GUID as hs_form_id. All subsequent GA4 and Meta Pixel tags listen for this event.

Step 2: Create a DataLayer Variable for the Form ID

In GTM, go to Variables → New → Data Layer Variable. Set the Data Layer Variable Name to hs_form_id and name the variable DLV - hs_form_id. You'll reference this variable in your GA4 and Meta Pixel tags to identify which specific form triggered the event — essential when tracking multiple forms on the same site.

Step 3: Create a Custom Event Trigger

Go to Triggers → New → Custom Event. Set the Event Name exactly to hubspot_form_success (matching the value in the dataLayer.push above). Name this trigger CE - hubspot_form_success. This single trigger will be reused for both your GA4 tag and your Meta Pixel tag.

Step 4: Create the GA4 Event Tag

Go to Tags → New → Google Analytics: GA4 Event and configure it:

  • Configuration Tag: select your existing GA4 configuration tag (or enter the Measurement ID directly)
  • Event Name: generate_lead — this is a GA4 recommended event optimized for conversion reporting
  • Event Parameters: add a row with parameter name form_id and value 0
  • Trigger: CE - hubspot_form_success

Step 5: Test Before Publishing

Click Preview in GTM, navigate to the page with your HubSpot form, and submit it. In the GTM debug panel, confirm that the hubspot_form_success message event appears and that the GA4 tag fires. Then open GA4 → Admin → DebugView and verify the generate_lead event arrives with the correct form_id value. Only publish the GTM container after both checks pass.

Method 2: HubSpot Embed Callback (No GTM Required)

If you're embedding HubSpot forms on an external website using hbspt.forms.create() and have direct access to the page code, you can fire GA4 events directly from the HubSpot callback without needing GTM at all:

Replace YOUR_PORTAL_ID with your HubSpot portal ID and YOUR_FORM_GUID with the form's unique identifier (found in HubSpot → Marketing → Forms → form details → the GUID in the embed code). Use a descriptive string for form_id — it will appear in GA4 event reports.

When to use this: ideal for WordPress sites, custom landing pages, or any setup where you call hbspt.forms.create() manually and want to keep tracking logic in one place without GTM overhead.

Advanced: Tracking Form Validation Errors

Tracking where users fail to submit a form is as important as tracking successes — it reveals friction points for CRO. HubSpot's Forms API fires onFormFailedValidation when a user clicks Submit but the form doesn't pass validation. Add this condition inside the same GTM listener tag:

In GTM, create a separate Custom Event trigger for hubspot_form_error and connect a GA4 Event tag with event name form_error. In GA4, build a funnel report comparing form_error vs generate_lead event counts per form to calculate your true form completion rate.

Part 2: Tracking HubSpot Forms in Meta Pixel (Facebook Pixel)

If you run paid campaigns on Facebook or Instagram, Meta Pixel is what closes the attribution loop between your ads and form-driven leads. HubSpot forms require exactly the same workaround as GA4 — standard form detection doesn't work across the iFrame boundary. Below are three approaches, ordered from simplest to most standalone.

Which Meta Pixel Events to Use for Form Submissions

Meta Pixel has standard predefined events. For HubSpot form submissions, choose based on your campaign goal:

  • Lead — the standard choice for contact, inquiry, and demo request forms; enables automatic campaign optimization
  • CompleteRegistration — for newsletter signups or account registration flows
  • Contact — for direct contact request forms (chat, callback)
  • trackCustom — for custom event names when you need granular per-form reporting in Events Manager

Using the Lead standard event (rather than a custom event) lets Meta's ad delivery system automatically optimize for conversions without additional configuration in Ads Manager. Use trackCustom when you need to distinguish between different forms in your campaign data.

Approach 1: Fire Meta Pixel via GTM (Recommended)

This is the cleanest implementation. You already have the hubspot_form_success Custom Event trigger from Part 1. All you need to do is add one more GTM tag that fires on that same trigger and calls Meta Pixel — no new listeners, no new triggers.

Prerequisite: your Meta Pixel base code must already be present on the page — either installed directly in the <head> or fired via a separate GTM Custom HTML tag on All Pages. The base code (which calls fbq('init', 'PIXEL_ID') and fbq('track', 'PageView')) must load before the event tag fires. Since the form submission happens after page load, this is almost never an issue in practice.

In GTM, go to Tags → New → Custom HTML and paste:

Set the trigger to CE - hubspot_form_success — the same trigger used for your GA4 tag. Name this tag Meta Pixel — Lead — HubSpot Form and publish.

Optional: Pass the Form ID as a Custom Parameter

When you track multiple HubSpot forms and want to see form-level breakdown in Meta Events Manager, pass the form GUID as a custom parameter. The value below references the DataLayer Variable created in Step 2 of Part 1:

The content_category field containing the form GUID will appear under Event Parameters in Meta Events Manager, letting you filter conversions by specific form.

Approach 2: All-in-One GTM Listener Tag (GA4 + Meta Pixel Combined)

If you prefer a single GTM tag that handles both trackers instead of separate tags on a shared trigger, use this combined postMessage listener. It fires once per submission and calls both GA4 and Meta Pixel in sequence:

The typeof fbq === 'function' guard prevents JavaScript errors if Meta Pixel hasn't finished loading when the form is submitted — for example, on slow connections where the user fills in the form very quickly. Set this tag's trigger to All Pages, exactly like the basic listener in Method 1.

Tradeoff vs Approach 1: easier to deploy (one tag), but harder to manage when individual forms need different tracking rules. Approach 1 (separate tags on a shared trigger) is more maintainable when you need to extend or debug tracking for specific forms independently.

Approach 3: Direct Embed Code (No GTM)

For external pages using hbspt.forms.create() without GTM, fire both GA4 and Meta Pixel directly from the onFormSubmitted callback. Both calls are wrapped in safety checks in case either script loads slowly:

Replace YOUR_PORTAL_ID and YOUR_FORM_GUID with your actual values. Replace 'contact_form' in the form_id parameter with a descriptive identifier for this specific form. This is the most portable solution — no external tag managers, no dependencies beyond the HubSpot Forms API itself.

Custom Meta Pixel Events for Per-Form Reporting

When you need to track multiple HubSpot forms as separate conversions in Meta Ads Manager (for example, a "Demo Request" form and a "Newsletter Signup" form with different campaign goals), use trackCustom instead of the standard Lead event:

Custom events appear under Custom Conversions in Meta Events Manager. Create a Custom Conversion rule that fires when form_id matches a specific HubSpot form GUID — this lets you set up separate campaign optimization goals for each form without sending separate Pixel events from your code.

Testing Your Meta Pixel Setup

Two tools to confirm Meta Pixel is capturing HubSpot form events correctly before you run any campaigns on the data:

  • Meta Pixel Helper (free Chrome extension): Open the extension on your page and submit the HubSpot form. The popup shows each Pixel event as it fires, the event name, parameters, and whether the Pixel ID was recognized. A green checkmark means the event was received without errors.
  • Events Manager → Test Events: In Meta Business Suite, go to Events Manager → your Pixel → Test Events. Enter your page URL in the field and click "Open Website." Submit the form and watch real-time events populate in the right panel with full parameter detail. This is the most authoritative verification tool — it confirms events are reaching Meta's servers, not just firing in the browser.

Quick Reference: Which Method to Use

Your Setup GA4 Method Meta Pixel Method
HubSpot CMS page + GTM GTM postMessage Listener (Method 1) Separate GTM tag on same trigger (Approach 1)
HubSpot CMS page + GTM, want one tag Combined listener (Approach 2) Same tag as GA4 (Approach 2)
External embed + hbspt.forms.create() + GTM GTM Listener or Embed Callback Separate GTM tag on same trigger
External embed + no GTM Embed Callback (Method 2) Direct fbq() in same callback (Approach 3)
Need per-form campaign attribution form_id parameter in GA4 tag trackCustom with form GUID (Custom Events)

HubSpot forms require a custom postMessage listener regardless of whether you're tracking in GA4 or Meta Pixel — standard GTM form triggers and Meta Pixel automatic event matching can't see across the iFrame boundary. The GTM listener approach (Method 1 + Approach 1) is the most maintainable: one listener tag pushes a hubspot_form_success event to the dataLayer, and separate GA4 and Meta Pixel tags both fire on that same Custom Event trigger. When using hbspt.forms.create() on external pages without GTM, the onFormSubmitted callback gives you direct, reliable access to fire both gtag() and fbq() calls in one place. Always verify your setup with GTM Preview, GA4 DebugView, and Meta Pixel Helper or Events Manager Test Events before running any campaigns on the data.