Google Analytics 4 events are the reason your reports look different from the Universal Analytics setup you might still remember. Universal Analytics organized everything around pageviews: a visit loaded a page, that page got logged, and your reports counted from there. Google Analytics 4 events treat every interaction, a pageview included, as one instance of the same underlying object. That single change explains most of the confusion business owners run into when they open GA4 for the first time and the totals don't line up with what they expected.
What Google Analytics 4 events actually measure
An event in GA4 is a record with a name and a set of parameters attached to it. A pageview is an event called page_view. A scroll past 90 percent of the page is an event called scroll. A click on an outbound link and a video play are also events, logged the same way, sitting in the same underlying table as the reports you see on screen.
This matters because Universal Analytics treated pageviews as a special, protected category and everything else as an optional add-on you had to configure by hand. GA4 flattens that hierarchy. A session in GA4 is really a cluster of events grouped by time and a session ID. Once that clicks, the reports stop feeling arbitrary. They are counting instances of things that happened, not counting visits the way older tools counted them.
Why sessions and pageviews behave differently now
GA4 calculates a session differently than Universal Analytics did. Universal Analytics ended a session at midnight or after thirty minutes of inactivity, no exceptions. GA4 uses a rolling engagement model: a session stays open as long as the user keeps generating events, and a single session can span midnight without splitting into two.
The practical effect is that GA4 session counts and Universal Analytics session counts were never going to match for the same traffic, even during the period both tools ran side by side. I've watched business owners spend hours trying to reconcile the two totals, assuming a tracking bug, when the real answer is that the two tools define a session using different rules. Once you stop expecting GA4 to restate Universal Analytics numbers, the frustration mostly disappears.
Work With John
Your site should be your best salesperson. If it is not, that is a fixable problem.
I work with US service businesses and B2B brands to build SEO systems that produce consistent, compounding leads. I will tell you exactly what is broken. No pitch.
Book a free strategy callRecommended events, custom events, and parameters
GA4 splits events into three tiers, and mixing them up is where a lot of setups go sideways. Automatically collected events (page_view, scroll, session_start, first_visit) fire the moment the tag loads, with no configuration required. Recommended events (things like generate_lead, sign_up, or purchase) use names and parameters Google has already defined, which means GA4's own reports and Google Ads integrations know how to interpret them without extra mapping on your end. Custom events are anything you name yourself, with parameters you define yourself, and they carry none of that built-in interpretation.
The practical implication: if a recommended event name already covers what you're tracking, use it. A form submission that represents a new lead should almost always fire as generate_lead rather than a custom name like form_submit_v2, because generate_lead is what feeds certain built-in GA4 reports and plays more cleanly with Google Ads conversion imports. Parameters attached to an event, form_id, page_location, value, ride along with that event as extra detail. They don't change whether the event counted. They change how much you can filter and segment once it did. A form event with no parameters tells you a form was submitted somewhere on the site. The same event with a form_id parameter tells you which form, which is the difference between a usable report and a number you have to guess at.
Event-scoped versus user-scoped custom dimensions
Parameters get more useful once you register them as custom dimensions in GA4, because a parameter that's only attached to the raw event data is hard to build a report around. When you register one, you have to pick a scope, and this is a step people skip past without realizing it changes what the data means.
An event-scoped custom dimension applies to the single event it rode in on. A form_id parameter registered as event-scoped tells you which form was submitted on that one occurrence. A user-scoped custom dimension attaches to the user record instead and persists across every session that user has going forward, which is the right choice for something like a customer tier or an account type that doesn't change from visit to visit. Registering a per-visit detail as user-scoped, or a stable user attribute as event-scoped, produces reports that technically have the data but group it in a way that answers the wrong question. This is a five-minute setting, but it's one of the more common reasons a business owner builds a custom report in GA4 and the numbers don't segment the way they expected.
The mistake I see most often with event setup
The most common mistake with Google Analytics 4 events isn't a tracking failure. It's a naming problem. GA4 auto-collects a small set of events (page_view, scroll, click, session_start) with no setup required, and business owners assume that covers everything. It doesn't. Anything specific to your business, a quote form submitted, a phone number clicked, a booking confirmed, has to be defined and marked as a conversion event on purpose.
A pattern I see often: a site owner insists their form isn't generating leads because GA4 shows zero conversions, when the real issue is that the form submission was never set up as an event at all. The form works fine. GA4 was just never told to count it. This is a configuration gap, not a data problem, and it's the first thing worth checking before assuming a funnel is broken.
How to check this yourself in ten minutes
You don't need a developer to sanity-check whether an event is firing correctly. Open GA4, go to Admin, and click DebugView under the Data display section. Install the Google Analytics Debugger browser extension, or add ?debug_mode=1 as a URL parameter to a test visit on your own site. Then walk through the action you want to verify: submit the form, click the phone number, load the page you're checking.
DebugView shows events arriving in something close to real time, along with every parameter attached to each one. If the event you expect doesn't show up at all, it isn't being triggered, which usually means a tag in Google Tag Manager either isn't firing or is watching for the wrong trigger. If the event shows up but with an empty or wrong parameter, the trigger works but the variable feeding it is misconfigured. That distinction matters, because the fix for a missing event and the fix for a bad parameter are completely different jobs, and DebugView is what tells you which one you're actually dealing with before you start changing things.
How duplicate events sneak into your reports
The most common data quality problem I find in an existing GA4 setup isn't a missing event. It's the same real action getting counted twice, which is worse in some ways because the numbers look plausible instead of obviously broken.
Here's how it usually happens. A site has GTM installed, and someone also pastes the GA4 gtag.js snippet directly into the page header just to be safe, or because an earlier developer set it up that way before GTM was added. Both fire the same generate_lead event on form submit. GA4 doesn't flag this as an error. It counts two events for one form submission, and every downstream report, conversion rate, cost per lead, funnel completion, comes out roughly double what actually happened.
A second version of the same problem: enhanced measurement's automatic outbound click tracking is turned on by default, and a custom GTM tag is also built to fire on the same outbound link using a Click trigger. Both fire. Both look correct in isolation. Together they overcount.
The fix isn't complicated once you know to look for it, but you have to look for it deliberately, because nothing in the standard GA4 interface warns you that a metric is doubled. Open DebugView, trigger the action once, and count how many times the event name appears in the stream. One click should produce one event. If you see two, open GTM's Preview mode at the same time and check whether more than one tag is bound to that trigger, or whether a native gtag snippet is running alongside the container. Nine times out of ten it's one of those two causes.
When the GA4 interface stops being enough: BigQuery export
Every GA4 property, even the free tier, can link to BigQuery and export raw event data automatically once a day. Most service businesses never touch this, and for a while that's the right call. But there's a point where the built-in reports genuinely can't answer the question you're asking, usually because you need to join event data against something GA4 doesn't know about: which customer record a lead turned into, which rep it got assigned to, whether a specific batch of leads from one campaign actually closed.
Once exported, each day's events land in a table named events_YYYYMMDD, with one row per event and every parameter nested inside it. You can query it with regular SQL, join it against a CRM export on a shared identifier like a transaction ID or a hashed email, and answer questions the GA4 UI was never built to answer, like true revenue per channel measured weeks after the visit instead of estimated at the moment of conversion.
In my experience, a service business handling a few hundred leads a month rarely needs this on day one. It becomes worth setting up once you're trying to reconcile analytics data against actual closed business rather than against on-site conversion events, which is a different question than GA4 answers on its own.
Where GA4 events end and Search Console data begins
It's worth being clear about the boundary between GA4 events and Google Search Console, because the two get conflated constantly. GA4 events only exist after someone has already landed on your site. Everything upstream of that click, which query someone searched, how many people saw your listing, what position you ranked in, lives in Search Console instead, and GA4 has no visibility into it at all.
That split means a drop in GA4 conversions and a drop in Search Console clicks can have completely different causes, and treating them as one problem wastes time. If Search Console clicks are flat but GA4 events for form submissions dropped, the issue is on the site, not in rankings. If Search Console impressions and clicks both fell while on-site events held steady, the problem sits upstream of anything GA4 can show you. I've written a full walkthrough on reading Search Console data correctly, which pairs well with this once you've got events sorted, because diagnosing a traffic problem means checking both sides of that boundary rather than assuming the answer lives in whichever tool you happen to have open.
An edge case worth knowing: self-referrals splitting your sessions
Some service businesses send visitors off-domain during a conversion: a payment processor, a scheduling tool hosted on its own domain, a booking widget that lives on a different subdomain, then back again once the action completes. If that return domain isn't listed in GA4's referral exclusion list, GA4 treats the trip back as a brand new session with a source and medium set to whatever domain the visitor came back from, rather than continuing the original session.
The practical effect: a single visitor journey, organic search to your site, out to a scheduling tool, back to a confirmation page, gets recorded as two sessions instead of one, and the conversion event on the confirmation page gets attributed to the scheduling tool's domain instead of the organic search that actually brought the visitor in. Your organic numbers look worse than reality, and a channel that did nothing but host a form gets credit for the lead.
The fix lives in Admin, under Data Streams, in the tag settings for the stream, where you can list domains that should never be treated as a referral source. If you're running a cross-domain setup for real, a booking tool on its own subdomain that you control, GA4's cross-domain measurement setting under the same menu is the more complete fix, since it tells GA4 to treat both domains as one property rather than merely ignoring the referral.
Understanding events is step one. Once they're firing correctly, which metrics actually correlate with new business and how to set up conversion tracking specifically for a service business are the next two questions worth answering. More in the Analytics & Data archive. If GA4 still doesn't line up with real inquiries once tracking is fixed, that's often a sign the underlying technical SEO needs a look too, not just the analytics setup.
What to check before you trust a GA4 report
Before drawing a conclusion from a GA4 report, confirm three things about how the underlying event is defined. Does it fire on the action you actually care about? Does it fire once per real occurrence rather than once per page load? Is it marked as a key event, GA4's current term for what conversions used to be called, if you're using it to judge lead volume?
Skipping this check is how a business owner ends up cutting a campaign or doubting a landing page based on a number that was never measuring what they thought it measured. Google Analytics 4 events are precise about what they count. That precision only helps once you know exactly what each one is counting before you read the graph.
The model behind GA4 is more flexible than Universal Analytics ever was, but flexibility means the tool no longer makes assumptions on your behalf. It counts whatever you tell it to count, exactly as you defined it. That's a better system once you understand it. It's a confusing one if you're still expecting it to behave like the tool it replaced.
