xmetric / Use cases

Which traffic sources pull their weight, from a GA4 Traffic acquisition export

Compare each source's share of key events with its share of sessions. A source with 10% of sessions and 20% of key events converts twice as well as your average; one with 15% of sessions and 4% of key events brings visits that don't act. Both shares are FIXED expressions over the whole file: SUM([Key events]) / MIN({ FIXED : SUM([Key events]) }). Drop the CSV you downloaded from Acquisition > Traffic acquisition below; the # header lines and the totals row are skipped.

Drop your GA4 Traffic acquisition CSV

Traffic sources compared on share of sessions and key events

A made-up Traffic acquisition download for an outdoor shop, with Session source / medium as the primary dimension: 14 sources, with the # comment lines and totals row a typical download starts with. The sample is synthetic and uses the report's documented dimension and metric names. Computed from ga4-traffic-acquisition.csv (13 rows of made-up data). The Tableau calculation and the SQL below both produce these numbers.

Sources, by sessions

Session source / mediumSessionsShare of sessionsShare of key eventsKey event indexRevenue
google / organic9,74137.8%29.4%0.7813,281.70
(direct) / (none)3,82514.8%17.9%1.219,041.53
google / cpc3,72914.5%20.2%1.3911,362.49
facebook / paid_social2,0267.9%3.0%0.381,357.39
instagram / paid_social1,4805.7%1.7%0.30617.65
newsletter / email1,3805.4%10.4%1.943,364.58
bing / organic7302.8%3.0%1.061,499.39
chatgpt.com / referral6582.6%4.7%1.852,263.91
promo-oct / email5532.1%5.6%2.633,142.96
reddit.com / referral4401.7%0.9%0.55386.80
bing / cpc4141.6%1.5%0.94803.80
l.facebook.com / referral4071.6%0.8%0.48293.66
duckduckgo / organic2631.0%0.9%0.92304.59
(not set) / (not set)1450.6%0.0%0.000.00

Rolled up by medium

MediumSessionsShare of sessionsEngagement rateKey eventsKey events per sessionRevenue per session
organic10,73441.6%65.0%1771.6%1.41
cpc4,14316.1%58.3%1152.8%2.94
(none)3,82514.8%58.3%952.5%2.36
paid_social3,50613.6%39.0%250.7%0.56
email1,9337.5%74.1%854.4%3.37
referral1,5055.8%63.6%342.3%1.96
(not set)1450.6%20.0%00.0%0.00

Recompute it from your CSV

Download the Traffic acquisition report as CSV, with Session source / medium as the primary dimension, and drop it here. Lines that start with # are skipped, the table ends at the first blank line, and the totals row is left out. Match the columns if your report uses other names. The file is read in this browser; nothing is uploaded.

No file loaded yet. You can also drop a CSV on this box.

Never average the rate columns

The download has Engagement rate and Session key event rate columns, one value per source. Averaging them for a medium gives a source with 150 sessions the same weight as one with 9,800. Recompute rates from counts instead: engagement rate is SUM([Engaged sessions]) / SUM([Sessions]), which is how Google defines it. The medium table does that, so email is judged on all its email sessions together.

Medium is the part after the slash in Session source / medium, so google / cpc and bing / cpc roll up into cpc. If your report uses Session default channel group as its primary dimension instead, match that column to Session source / medium in the box; the shares and index still work, and the medium table simply repeats the channels.

Download the Traffic acquisition report from GA4

  1. In Google Analytics, open Reports > Acquisition > Traffic acquisition.
  2. Change the primary dimension (the table's first column header) to Session source / medium, and pick the date range.
  3. Click Share this report, then Download File > Download CSV. The file holds up to 100,000 rows.
  4. Drop it in the box above.

Menu path, dimensions and metric names from Google's help pages on the Traffic acquisition report and downloading report data, checked 2026-10-18. The sample has the report's metrics: Sessions, Engaged sessions, Engagement rate, Average engagement time per session, Events per session, Event count, Key events, Session key event rate and Total revenue.

Google doesn't document the file's layout. A typical download starts with # comment lines, then a blank line, the header row and a totals row; the box above skips them.

The Tableau calculation

Sources, by sessions

On Rows: [Session source / medium]. Each calculation below is one column.

// Sessions
SUM([Sessions])

// Share of sessions
SUM([Sessions]) / MIN({ FIXED : SUM([Sessions]) })

// Share of key events
SUM([Key events]) / MIN({ FIXED : SUM([Key events]) })

// Key event index: share of key events / share of sessions (1.00 = site average)
(SUM([Key events]) / MIN({ FIXED : SUM([Key events]) })) / (SUM([Sessions]) / MIN({ FIXED : SUM([Sessions]) }))

// Revenue
SUM([Total revenue])

Rolled up by medium

On Rows: [Medium]. Each calculation below is one column.

// Medium
TRIM(SPLIT([Session source / medium], '/', 2))

// Sessions
SUM([Sessions])

// Share of sessions
SUM([Sessions]) / MIN({ FIXED : SUM([Sessions]) })

// Engagement rate, recomputed from counts
SUM([Engaged sessions]) / SUM([Sessions])

// Key events
SUM([Key events])

// Key events per session
SUM([Key events]) / SUM([Sessions])

// Revenue per session
SUM([Total revenue]) / SUM([Sessions])

The equivalent SQL

Sources, by sessions

WITH sources AS (
  SELECT * FROM read_csv('ga4-traffic-acquisition.csv', comment = '#', header = true)
  WHERE "Session source / medium" IS NOT NULL AND "Session source / medium" NOT IN ('Grand total', 'Total', 'Totals')
), site AS (
  SELECT SUM("Sessions") AS site_sessions, SUM("Key events") AS site_key_events FROM sources
)
SELECT "Session source / medium",
       SUM("Sessions") AS sessions,
       SUM("Sessions") / MIN(site.site_sessions) AS share_of_sessions,
       SUM("Key events") / MIN(site.site_key_events) AS share_of_key_events,
       (SUM("Key events") / MIN(site.site_key_events)) / (SUM("Sessions") / MIN(site.site_sessions)) AS key_event_index,
       SUM("Total revenue") AS revenue
FROM sources, site
GROUP BY "Session source / medium"
ORDER BY sessions DESC;

Rolled up by medium

WITH sources AS (
  SELECT * FROM read_csv('ga4-traffic-acquisition.csv', comment = '#', header = true)
  WHERE "Session source / medium" IS NOT NULL AND "Session source / medium" NOT IN ('Grand total', 'Total', 'Totals')
), site AS (
  SELECT SUM("Sessions") AS site_sessions FROM sources
)
SELECT trim(split_part("Session source / medium", '/', 2)) AS medium,
       SUM("Sessions") AS sessions,
       SUM("Sessions") / MIN(site.site_sessions) AS share_of_sessions,
       SUM("Engaged sessions") / SUM("Sessions") AS engagement_rate,
       SUM("Key events") AS key_events,
       SUM("Key events") / SUM("Sessions") AS key_events_per_session,
       SUM("Total revenue") / SUM("Sessions") AS revenue_per_session
FROM sources, site
GROUP BY medium
ORDER BY sessions DESC;

Before you move budget

Google Analytics is a trademark of Google LLC. xmetric is not affiliated with Google. The sample file is synthetic: made-up sources and numbers in the layout of a typical GA4 Traffic acquisition download, using the report's dimension and metric names as documented on 2026-10-18.

Questions people ask

Why don't my key events add up to the GA4 total?

Check that the totals row is gone: the box drops rows whose first cell is empty or reads Grand total, and the SQL keeps only rows with a source / medium. Rows past 100,000 aren't in the download at all.

Can I add ad spend to get cost per key event?

Not from this file alone: the Traffic acquisition report has no cost column. Join the export to your spend by source / medium in SQL, or add a cost column to the CSV before you drop it.

Is my analytics data uploaded?

No. The CSV is read and calculated in this browser tab; nothing is sent anywhere.

Related: landing pages from a GA4 export, wasted spend in Google Ads search terms, weighted averages by group, FIXED expressions.