Cart abandonment is one of those things everyone knows is a problem and nobody fully understands. The usual dashboard tells you the rate. It doesn’t tell you why.
A CRO manager worth their salt wants to know more than “68% of carts are abandoned.” They want to know: what did those people do right before they left? Was it the shipping page? The login prompt? Some random blog post that distracted them?
Which pages do users visit in a session where they added something to cart but never bought?
That’s the question. And there’s a bonus: if we can attach the net cart value to those sessions, we can prioritise by revenue impact, not just volume.
What you need
Three things:
Abandoned sessions — sessions that contain an add_to_cart event but no purchase. The ga4_sessions table has aggregated event counts per session, but we need to configure those counts first (more on that below).
Last pages visited — for each abandonment session, the page_view events closest to the end of the session, from ga4_events.
Cart value — the sum of ecommerce.value on add_to_cart events. This gives you the (gross) value of what was actually added to the cart when the user disappeared.
Step 1: configure session totals (Premium)
Out of the box, ga4_sessions doesn’t know how many add_to_cart or purchase events happened in a session. You need to tell GA4Dataform to count and sum them.
In includes/custom/modules/ga4/config.js, add this to your config:
CUSTOM_SESSION_TOTALS: {
eventsToCount: [
'add_to_cart',
'remove_from_cart',
'begin_checkout',
'purchase',
],
sumFields: [
{ name: 'event_params.value', eventFilter: 'add_to_cart', renameTo: 'cart_value_added' },
]
}
After a rebuild, ga4_sessions will have:
totals.count.add_to_cart— number of add-to-cart events in the sessiontotals.count.purchase— number of purchase eventstotals.sum.cart_value_added— total value added to cart
The query
WITH abandoned_sessions AS (
-- sessions with at least one add_to_cart and no purchase
SELECT
session_id,
user_pseudo_id,
session_date,
totals.count.add_to_cart AS add_to_cart_count,
totals.sum.cart_value_added AS cart_value_added,
session_source.default_channel_grouping AS channel,
FROM `superform_outputs.ga4_sessions`
WHERE totals.count.add_to_cart > 0
AND totals.count.purchase = 0
AND session_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
),
last_pages AS (
-- last 3 page_view events per abandoned session
SELECT
e.session_id,
ARRAY_AGG( e.page.path ORDER BY e.time.event_timestamp_utc DESC LIMIT 3 ) as last_3_pages,
FROM `superform_outputs.ga4_events` e
INNER JOIN abandoned_sessions a USING (session_id)
WHERE e.event_name = 'page_view'
AND e.event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
GROUP BY ALL
)
SELECT
lp.last_3_pages[SAFE_OFFSET(2)] as pre_pre_exit_page,
lp.last_3_pages[SAFE_OFFSET(1)] as pre_exit_page,
lp.last_3_pages[SAFE_OFFSET(0)] as exit_page,
COUNT(DISTINCT lp.session_id) AS abandoned_sessions,
ROUND(AVG(a.cart_value_added), 2) AS avg_abandoned_cart_value,
ROUND(SUM(a.cart_value_added), 2) AS sum_abandoned_cart_value
FROM last_pages lp
INNER JOIN abandoned_sessions a USING (session_id)
GROUP BY ALL
ORDER BY abandoned_sessions DESC
Replace
superform_outputswith your actual dataset name.
Each row contains 3 page path columsn, indicating the second-to-last, penultimate, and final page path of the session.
Then, aggregated: how many abandonment sessions followed this path, and the total and average cart value walking out the door with them.
Reading the results

Page sequences that appear often are the last route people took before leaving. That’s your friction sequence. Common culprits:
Shipping costs page — if this tops the list, your shipping costs are killing conversions. Test free shipping thresholds.
Login / register page — forced account creation is a classic abandonment trigger. Guest checkout is the fix.
Payment page — if people get this far and still bail, something about the payment experience is wrong. Limited payment methods, trust signals missing, or a confusing form.
You could filter or drill down by channel from the abandoned_sessions CTE to see if paid traffic abandons on different pages than organic. A paid traffic audience hitting the login wall especially hard is worth knowing.
Your turn
Run this against your last 90 days and look at the top paths by total_abandoned_value. That’s the ranked list of pages costing you the most revenue, right now.
If a single page keeps showing up with high abandoned cart values, that’s where your next CRO experiment should be.
Let us know what you find.



