Google Analytics 4

GA4 without gtag.js

Deliver events to GA4 via Measurement Protocol with a self-generated client_id, server-set _ga cookie, and ITP-exempt 400-day expiry. Full GA4 reporting with zero Google JavaScript in the browser.

The problem with gtag.js

Google's client-side tracking has four fundamental problems that cannot be fixed with configuration changes. They are architectural limitations.

80KB+ Payload

gtag.js loads 80KB+ of JavaScript before a single event fires. Combined with GTM, total payload regularly exceeds 200KB — directly impacting Core Web Vitals and conversion rates.

ITP-Limited Cookies

Safari's Intelligent Tracking Prevention caps client-side JavaScript cookies at 7 days. Your _ga cookie expires weekly, fragmenting user sessions and inflating visitor counts.

Ad Blocker Blocked

EasyList blocks google-analytics.com and googletagmanager.com by default. 30-40% of technical audiences never register a single event. Your data has a permanent blind spot.

Consent Race Conditions

Client-side consent banners race against tag execution. gtag.js may fire before consent is granted, or consent may be revoked after events are already in flight.

How server-side GA4 works

Six steps from browser event to GA4 report. No Google JavaScript involved.

1

Datafly.js collects events

The 4.2KB collector captures page, track, and identify events via sendBeacon. No gtag.js, no Google Tag Manager, no 80KB+ payload.

2

Server generates client_id

The Ingestion Gateway generates a GA4-format client_id as {random_uint32}.{unix_timestamp} — the exact same format Google uses.

3

Server sets _ga cookie

The _ga cookie is set via Set-Cookie header with a 400-day expiry. Because it is server-set on your first-party subdomain, it is fully exempt from Safari ITP restrictions.

4

Pipeline Engine transforms to Measurement Protocol

Your YAML pipeline config maps event properties to GA4 Measurement Protocol parameters. Session data, user properties, and engagement metrics are enriched automatically.

5

Delivery Worker POSTs to GA4

A purpose-built delivery worker sends the formatted payload to google-analytics.com/mp/collect with your Measurement Protocol API secret. Exponential backoff retry on failure.

6

GA4 reports populate normally

Events appear in your GA4 property exactly as if they came from gtag.js. Real-time reports, explorations, BigQuery export — everything works as expected.

Pipeline as Code

Transformation configs you can read

Every GA4 event mapping is defined in version-controlled YAML. Review in pull requests, roll back with a commit revert.

ga4-pageview.yamlYAML
# ga4-pageview.yaml — Page view to Measurement Protocol
name: ga4_pageview
integration: google-analytics-4
trigger:
  event: page
  conditions:
    - field: context.page.url
      operator: exists

transform:
  mapping:
    - source: properties.title
      target: page_title
    - source: context.page.url
      target: page_location
    - source: context.page.referrer
      target: page_referrer
    - source: context.locale
      target: language

  enrichments:
    - type: session
      fields: [session_id, session_number]
    - type: vendor_id
      vendor: ga4
      cookie: _ga

output:
  format: ga4_measurement_protocol
  event_name: page_view
  endpoint: https://www.google-analytics.com/mp/collect
  validate: true
ga4-purchase.yamlYAML
# ga4-purchase.yaml — E-commerce purchase event
name: ga4_purchase
integration: google-analytics-4
trigger:
  event: track
  conditions:
    - field: event
      operator: equals
      value: Order Completed

transform:
  mapping:
    - source: properties.order_id
      target: transaction_id
    - source: properties.revenue
      target: value
    - source: properties.currency
      target: currency
      default: USD
    - source: properties.products
      target: items
      transform: array_map
      fields:
        - source: product_id
          target: item_id
        - source: name
          target: item_name
        - source: price
          target: price
        - source: quantity
          target: quantity
        - source: category
          target: item_category

  enrichments:
    - type: session
      fields: [session_id, session_number, engagement_time_msec]
    - type: vendor_id
      vendor: ga4
      cookie: _ga

output:
  format: ga4_measurement_protocol
  event_name: purchase
  endpoint: https://www.google-analytics.com/mp/collect
  validate: true

Full GA4 feature support

Everything you use in GA4 today works with server-side delivery. No compromises, no missing features, no manual workarounds.

  • Page views
  • Custom events
  • Session tracking
  • Engagement time
  • Scroll tracking
  • E-commerce: view_item
  • E-commerce: add_to_cart
  • E-commerce: begin_checkout
  • E-commerce: purchase
  • User properties
  • Cross-domain measurement
  • Debug mode validation
  • BigQuery export compatibility
  • Enhanced measurement events
  • Consent mode integration

BigQuery Export Compatibility

Events delivered via Measurement Protocol appear in your BigQuery export with the same schema as client-side events. Your existing queries, dashboards, and ML pipelines continue to work without modification.

See server-side GA4 in action

Book a technical walkthrough where we show you GA4 events flowing from Datafly.js through the pipeline to your GA4 property in real-time. No gtag.js required.