How does GA4's event-and-parameter data model differ from Universal Analytics' session model?
answer
- one primitive, not several hit types
- a name plus a bag of parameters
- a pageview is just an event name
- sessions are computed from the stream
- ga_session_id stamped on every event
basics
~20 sGA4 records every interaction as one named event carrying key-value parameters, so a pageview is simply the event page_view. Universal Analytics collected typed hits — pageview, event, transaction, timing — and treated pageviews and sessions as first-class objects.
solid answer
~40 sGA4 has a single primitive: the **event**. An event is a name plus a bag of parameters — `page_view` with `page_location` and `page_title`, `purchase` with `transaction_id`, `value`, `currency` and an `items` array, or any custom name you choose with any parameters you attach. Universal Analytics instead had several hit types with fixed slots: an event hit was exactly category / action / label / value, and pageviews and sessions were counted natively by the platform. GA4 still reports sessions, but they are *derived* — a `session_start` event, plus a `ga_session_id` parameter stamped onto every event in that session, cut by an inactivity timeout. For a data engineer the practical consequence is that GA4's raw data is a flat event stream with a nested parameter array; you reconstruct sessions, funnels and pageview counts yourself.
code
javascript · 16 linesgtag('config', 'G-XXXXXXXXXX');
// a recommended event: Google defines the name and parameter names
gtag('event', 'purchase', {
transaction_id: 'T_12345',
value: 42.5,
currency: 'USD',
items: [{ item_id: 'SKU_9', item_name: 'Annual plan', price: 42.5, quantity: 1 }]
});
// a custom event: any name, any parameters
gtag('event', 'plan_upgrade_clicked', {
from_tier: 'free',
to_tier: 'pro',
placement: 'sidebar_banner'
});go deeper
Be able to say that GA4 collects named events with parameters and that a pageview is just the event page_view. Naming two or three real events, such as session_start, page_view and purchase, is enough at this stage.
Explain the mechanics: the four event families, that custom parameters need registering as custom dimensions to show in reports, and that sessions are reconstructed from session_start plus the ga_session_id parameter rather than being collected directly.
Show you have operated this. Talk about naming discipline and a tracking plan, what breaks when web and app send the same parameter with different types, and why you would model from the raw event stream instead of trusting UI-configured dimensions.
Own the taxonomy across teams: who may mint an event name, how a change to the schema is reviewed, and how you avoid a long tail of near-duplicate events that makes every downstream metric a negotiation.
## One primitive instead of many Google Analytics 4 (GA4) collects exactly one kind of thing: an **event**. An event is a name plus a set of **parameters** — key/value pairs that describe it. Viewing a page is the event `page_view` with parameters such as `page_location`, `page_title` and `page_referrer`. Completing a checkout is the event `purchase` with `transaction_id`, `value`, `currency` and a nested `items` array. Clicking your own in-app button is whatever event name you pick — `plan_upgrade_clicked` — with whatever parameters you attach. There is no other shape. Everything GA4 knows is a row in that stream. ## What Universal Analytics did instead Universal Analytics (UA), the now-sunset predecessor, collected typed **hits**: a pageview hit, an event hit, a transaction hit, a timing hit, a social hit, a screenview hit. Each type had fixed slots. An event hit carried exactly `eventCategory`, `eventAction`, `eventLabel` and an optional numeric `eventValue`; anything else had to be squeezed into numbered custom dimensions and metrics configured in the property. Pageviews and sessions were primitives the platform counted for you, and metrics like "Pages / Session" or "Bounce Rate" fell out of that model directly. That is why a mechanical port of a UA tracking plan into GA4 produces bad data. Mapping category/action/label onto three generic GA4 parameters preserves the letters and throws away the point: in GA4 the *event name* is the thing being reported on, and parameters are meant to be named for what they actually contain (`plan_tier`, `search_term`, `method`), not for their position in an old fixed schema. ## Sessions became derived GA4 does report sessions, but they are computed from the event stream rather than declared by the client. GA4 emits a `session_start` event, and every event in that session carries a `ga_session_id` parameter (an identifier assigned when the session starts) and `ga_session_number`. A session ends after an inactivity timeout that you configure in the property's settings; the next event then gets a new `ga_session_id`. Critically, `ga_session_id` is only unique *within a visitor* — to key a session in SQL you concatenate it with the visitor identifier, not use it alone. ## The families of events Four groups, and interviewers like the distinction: - **Automatically collected** — GA4 emits them with no work from you: `first_visit`, `session_start`, `user_engagement`. - **Enhanced measurement** — toggled on the data stream, collected by the tag without extra code: `scroll`, `click` (outbound), `file_download`, `video_start`, `form_start`, `view_search_results`. - **Recommended** — you must send them, but Google defines the name and parameters so standard reports and ecommerce dashboards understand them: `purchase`, `login`, `sign_up`, `add_to_cart`, `begin_checkout`. - **Custom** — anything you invent. Names beginning `ga_`, `google_` and `firebase_` are reserved, so a custom event or parameter cannot use those prefixes. ## Registration versus collection A custom parameter is *collected* the moment you send it, but it does not appear as a dimension in most GA4 UI reports until you register it as a custom dimension or metric in the property's admin section. This trips people up: the parameter is missing from a report while being perfectly present in the raw data. The BigQuery export contains every parameter regardless of registration, which is one reason data teams prefer to model from the export. ## Why the model suits a data team A flat, self-describing event stream maps cleanly onto a warehouse events table, and adding a new parameter needs no schema migration in GA4 itself. The flip side is that nothing enforces the schema: a typo in an event name silently creates a new event, a parameter that is a string on web and an integer in the app produces two differently-typed columns downstream, and casing is significant. The discipline that used to live in the UA property configuration now lives in a tracking plan and in whatever validation you build around ingestion. ## Common traps Porting category/action/label one-to-one; expecting a ready-made sessions table in the raw data; assuming a newly sent parameter shows up in reports automatically; and putting personally identifying values (email, name, raw user id in a parameter meant for display) into GA4, which its terms of service prohibit.
- Where do events like scroll and file_download come from if you never wrote code for them?They are enhanced measurement events, toggled on the data stream in the GA4 admin, and the tag emits them without any extra code. Together with automatically collected events such as first_visit, session_start and user_engagement they mean a fresh GA4 property already produces traffic before you write a single custom event.
- Why can a custom event not be named ga_checkout or firebase_signup?The prefixes ga_, google_ and firebase_ are reserved by the platform for its own event and parameter names, so events or parameters using them are rejected or ignored. Pick a plain snake_case name in your own namespace, and keep casing consistent — GA4 event names are case-sensitive, so PlanUpgrade and plan_upgrade are two different events.
- You sent a new parameter plan_tier but it does not appear in any GA4 report. What happened?Collection and reporting are separate. The parameter is in the data, but a custom parameter has to be registered as a custom dimension (event-scoped) in the property's admin before most UI reports can use it, and registration is not retroactive for standard reports. The BigQuery export, by contrast, contains the parameter from the moment it was first sent.
- How does GA4 decide that one session ended and another began?By inactivity. After a configurable period with no events from that visitor, the session is closed; the next event triggers a new session_start and a new ga_session_id value that is then stamped on subsequent events. Because that id is only unique within a visitor, session-level SQL must key on the visitor identifier combined with ga_session_id.
Universal Analytics was a paper form with fixed boxes to tick; GA4 hands you a blank envelope with a label on the front and lets you put whatever you like inside.
saying these in an interview costs you the question
- Says GA4 still has separate pageview and event hit types
- Maps UA category, action and label straight onto GA4 parameters
- Treats sessions as raw collected data rather than derived
- Assumes a custom parameter appears in reports without registration
- Believes event names are case-insensitive or that ga_ prefixes are allowed