MarTechQuick
Intermediate

GA4 Architecture

12 min read

Learn
Quick Reading
Estimated 12 mins
Prereq
Intermediate
Basic ML concepts helpful
Interactive
Static Playbook
Static guide & reference tables

The Shift: Universal Analytics vs GA4

For over a decade, Google Universal Analytics (UA) was the standard for web measurement. Built on a conceptual model from the early web era, UA organized data around sessions and pageviews. A session was a container for user interactions (hits like pageviews, events, or ecommerce actions) occurring within a set timeframe.

Universal Analytics was deprecated because sessions are an outdated construct. In a modern landscape of single-page apps (SPAs), mobile apps, and multi-device journeys, session boundaries are arbitrary and brittle. GA4 replaces this old paradigm with a unified, event-based data model.

GA4's Data Model: Everything is an Event

In GA4, there is only one fundamental unit of interaction: the Event.

Unlike UA, where events had a rigid Category, Action, Label, and Value structure, a GA4 event is simply a named interaction that carries a payload of key-value parameters. User metadata is stored as User Properties attached to the user record.

The administrative hierarchy simplifies data streaming:
- Account: The master organization container.
- Property: The logical reporting boundary representing a brand or business.
- Data Stream: The actual source of data (e.g., a website, iOS app, or Android app) flowing into the property.

No More Special Hits

In GA4, a 'page view' is just another event called page_view. There is no special status. A click, a purchase, a pageview, and an app crash are all identical structural events carrying different key-value parameter payloads.

Understanding Event Categories

GA4 breaks events into four structural categories:

1. Automatically Collected Events: Captured by default when the GA4 tag loads (e.g., first_visit, session_start).
2. Enhanced Measurement Events: Optional toggleable events captured automatically by the base tag (e.g., scroll, click, file_download).
3. Recommended Events: Events pre-defined by Google for specific industries (e.g., purchase, add_to_cart, login). You must implement these yourself, but using Google's naming standard unlocks automated retail reports.
4. Custom Events: Unique events you define when recommended ones do not fit. Requires custom dimension registration.

ga4_event_payload.json
json
{
  "client_id": "123456789.171123456",
  "events": [
    {
      "name": "purchase",
      "params": {
        "transaction_id": "T_98765",
        "value": 149.50,
        "currency": "USD",
        "shipping": 10.00,
        "items": [
          {
            "item_id": "SKU_001",
            "item_name": "Premium MarTech Consulting Hour",
            "price": 149.50,
            "quantity": 1
          }
        ]
      }
    }
  ]
}

The BigQuery Export Integration

Google Analytics 4 provides a native, free connection to Google BigQuery. This allows you to stream your raw, unsampled, event-level data directly into a SQL warehouse daily or in near-real-time.

Every day, GA4 creates a table named events_YYYYMMDD in your BigQuery project. Inside this table, every row is a single event, and complex metadata (like items and event parameters) is stored in nested arrays of structures. This schema avoids giant database tables by packing parameters into key-value pairs.

Unsampled Row-Level Access

The BigQuery export is the only way to get unsampled, row-level data from GA4. Without it, you are bounded by the GA4 UI's query limits, API thresholds, and lookback windows. If you're not using BigQuery, you're missing 80% of GA4's analytics power.

Querying the GA4 Schema

Because event parameters are stored in nested fields, you cannot query them using standard flat SQL. You must use UNNEST operations to flatten the arrays. The query below shows how to extract the nested page_location parameter to list pageviews by event count:

pageview_counts.sql
sql
SELECT
  event_name,
  event_date,
  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_url,
  COUNT(*) as event_count
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20260101' AND '20260131'
  AND event_name = 'page_view'
GROUP BY 1, 2, 3
ORDER BY event_count DESC
LIMIT 50

Common Architectural Mistakes

Implementing GA4 incorrectly is extremely common. Here are the main traps to avoid:

- Casing & Naming: Event names are case-sensitive. Mixing page_View and page_view creates two separate events. Always use snake_case.
- Cardinality Limits: Passing high-cardinality values (like user IDs or raw timestamps) as custom event parameters causes reports to aggregate values under an '(other)' row.
- Custom Dimension Delay: If you add custom parameters to events, you must explicitly register them in the GA4 admin panel to query them in standard UI reports.

Register Your Custom Dimensions

If you don't register custom dimensions in the GA4 interface, the parameters are collected and available in BigQuery, but they will be completely invisible and unselectable in the Google Analytics UI and Looker Studio reports.

Interactive Visualization

An interactive event flow diagram showing how events journey from browser variables through GTM into the GA4 and BigQuery schema is coming soon.

What's Next?

Now that you understand the event-driven model of GA4, the next step is learning how to trigger, capture, and structure these events on your website.

Next: Google Tag Manager (GTM) Deep Dive →

I build these systems professionally.

Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.

Need custom AI or MarTech setup? Let's build together.