All articles

Digital Marketing

GA4 events for B2B SaaS: the minimum useful taxonomy

May 24, 2026 · 4 min read

A CEO asks why marketing reported 412 demo bookings last quarter while sales only saw 38 qualified ones. You open GA4 and find nothing but auto-collected events — page_view, form_submit — and realize the funnel has never actually been instrumented.

GA4's default configuration cannot answer B2B SaaS questions: where prospects drop off, which channels produce activated users, what a channel is actually worth. That takes a deliberate event taxonomy. Here is the minimum useful one.

The five events every B2B SaaS funnel needs

  1. 1lead_captured — form submissions creating a contactable record (newsletters, gated assets, contact requests). Parameters: method, form_id, content_offer.
  2. 2demo_booked — confirmed calendar events via Chili Piper, Calendly, or HubSpot Meetings. Parameters: booking_source, rep_assigned, account_domain.
  3. 3trial_started — user activation of a trial workspace. Parameters: plan, seat_count, signup_method.
  4. 4activation_milestone — the in-product action that correlates with paid conversion (teammate invited, integration connected, first report run). Parameters: milestone_name, time_to_activation_sec.
  5. 5paid_conversion — first successful charge. Parameters: plan, arr_value, currency, billing_cycle.

Mark all five as key events in GA4 (Admin → Events → Mark as key event) so they flow into attribution reporting and Google Ads conversion import.

How to fire them: GTM trigger plus dataLayer push

Fire events from application code, not from CSS selectors — selectors break the day a developer renames a class. The pattern:

// Fire from your app code when the action actually completes
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'lead_captured',
  method: 'demo_form',
  form_id: 'enterprise-contact-v3',
  content_offer: 'roi-calculator',
  user_id: 'usr_8f3a2c',
  account_domain: 'acmecorp.com'
});

In Google Tag Manager, create a custom event trigger listening for the event name, then a GA4 Event tag mapping each dataLayer key to an event parameter. For server-side events like paid_conversion from Stripe webhooks, use the GA4 Measurement Protocol with the same parameter structure so the schema stays consistent.

How to track them in GA4: custom dimensions and user_id

Event parameters are invisible in standard GA4 reports until you register them as custom dimensions. Go to Admin → Custom definitions and register the ones you will actually filter on: plan, milestone_name, booking_source, account_domain.

Set user_id on every event once known (after sign-in or form capture) so GA4 can stitch journeys across devices instead of showing fragmented sessions. For revenue, set value and currency on paid_conversion so attribution is ARR-weighted — a $40,000 enterprise deal should not look the same as a $49 self-serve signup.

Where teams typically screw it up

  1. 1PII in event parameters. Email addresses, phone numbers, and names in user_id or parameters risk property suspension. Hash emails or use internal user IDs.
  2. 2Missing user_id. Without it, lead_captured on the marketing site never connects to trial_started in-product — the funnel breaks exactly where it matters most.
  3. 3Double-firing. "Thank you" pages that fire demo_booked on every reload inflate conversions 20–40%. Fire on API success callbacks, not redirects.
  4. 4Client-side paid conversions. Firing paid_conversion after a Stripe redirect loses 10–15% of conversions to ad blockers and abandoned tabs. Send it server-side.

This setup is the standard first-two-weeks work of every conversion analytics engagement we run. Most SaaS teams do not have it — not because it is hard, but because it kept getting deprioritized behind the next launch. Two weeks of instrumentation buys every quarter of reporting after it.

Have a question about this topic?

Book a 30-minute call. We will give you a useful read on it.