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 / medium | Sessions | Share of sessions | Share of key events | Key event index | Revenue |
|---|---|---|---|---|---|
| google / organic | 9,741 | 37.8% | 29.4% | 0.78 | 13,281.70 |
| (direct) / (none) | 3,825 | 14.8% | 17.9% | 1.21 | 9,041.53 |
| google / cpc | 3,729 | 14.5% | 20.2% | 1.39 | 11,362.49 |
| facebook / paid_social | 2,026 | 7.9% | 3.0% | 0.38 | 1,357.39 |
| instagram / paid_social | 1,480 | 5.7% | 1.7% | 0.30 | 617.65 |
| newsletter / email | 1,380 | 5.4% | 10.4% | 1.94 | 3,364.58 |
| bing / organic | 730 | 2.8% | 3.0% | 1.06 | 1,499.39 |
| chatgpt.com / referral | 658 | 2.6% | 4.7% | 1.85 | 2,263.91 |
| promo-oct / email | 553 | 2.1% | 5.6% | 2.63 | 3,142.96 |
| reddit.com / referral | 440 | 1.7% | 0.9% | 0.55 | 386.80 |
| bing / cpc | 414 | 1.6% | 1.5% | 0.94 | 803.80 |
| l.facebook.com / referral | 407 | 1.6% | 0.8% | 0.48 | 293.66 |
| duckduckgo / organic | 263 | 1.0% | 0.9% | 0.92 | 304.59 |
| (not set) / (not set) | 145 | 0.6% | 0.0% | 0.00 | 0.00 |
Rolled up by medium
| Medium | Sessions | Share of sessions | Engagement rate | Key events | Key events per session | Revenue per session |
|---|---|---|---|---|---|---|
| organic | 10,734 | 41.6% | 65.0% | 177 | 1.6% | 1.41 |
| cpc | 4,143 | 16.1% | 58.3% | 115 | 2.8% | 2.94 |
| (none) | 3,825 | 14.8% | 58.3% | 95 | 2.5% | 2.36 |
| paid_social | 3,506 | 13.6% | 39.0% | 25 | 0.7% | 0.56 |
| 1,933 | 7.5% | 74.1% | 85 | 4.4% | 3.37 | |
| referral | 1,505 | 5.8% | 63.6% | 34 | 2.3% | 1.96 |
| (not set) | 145 | 0.6% | 20.0% | 0 | 0.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
- In Google Analytics, open Reports > Acquisition > Traffic acquisition.
- Change the primary dimension (the table's first column header) to Session source / medium, and pick the date range.
- Click Share this report, then Download File > Download CSV. The file holds up to 100,000 rows.
- 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
- Session-scoped attribution: each session is credited to the source that started it. A newsletter click that leads to a purchase on a later direct visit counts for
(direct) / (none). Google's Advertising reports use a different model, so their numbers won't match this file. - Key events are counted, not converting sessions. A source whose visitors fire several key events per session looks stronger than one with more converting sessions.
- Small sources swing. An index of 2.0 on 150 sessions can be a handful of key events. Read the index next to Sessions.
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.