Photo: by Marten Newhall on Unsplash
Most site search reports answer one question: what did people look for? You get a ranked list of terms, a count of searches, maybe a exit rate on the results page.
What they don’t tell you is whether those searches turned into money.
Someone types “blue plastic sunglasses”, views a few results, doesn’t buy, closes the tab.. comes back three days later and converts.
In GA4, in the UI, you need to work with segments and jump through a lot of hoops to extract that kind of behaviour.
In this post, a simple query that answers: Which search terms predict a purchase, even when that purchase happens days later in a different session?
That’s the gap. And it’s closable.
The pieces you need
Two tables: ga4_events for the search events, ga4_transactions for the purchases.
The join key is user_pseudo_id. GA4’s cookie-based identifier that persists across sessions (until the user clears cookies, switches devices, or goes incognito, but that’s a separate problem). That persistence is what makes this cross-session join work.
The logic:
- Find every
view_search_resultsevent per user, with the search term - Take the earliest date that user searched for each term
- Check if they bought anything within 7 days of that first search
- Sum the revenue, count the buyers, calculate a purchase rate
“Attributed” is doing some work here. This isn’t proof that the search caused the sale. Someone might have searched “garden tools” and then bought a wheelbarrow already sitting in their cart from last week. But it’s a reasonable signal, and it’s a lot more useful than knowing nothing.
The query
WITH searches AS (
SELECT
user_pseudo_id,
event_params.search_term AS search_term,
MIN(event_date) AS first_search_date
FROM superform_outputs.ga4_events
WHERE event_name = 'view_search_results'
AND event_params.search_term IS NOT NULL
AND event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
GROUP BY ALL
),
purchases AS (
SELECT
user_pseudo_id,
transaction_date,
ecommerce.purchase_revenue AS purchase_revenue
FROM superform_outputs.ga4_transactions
WHERE transaction_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
),
search_purchases AS (
SELECT
s.search_term,
s.user_pseudo_id,
p.transaction_date,
p.purchase_revenue,
DATE_DIFF(p.transaction_date, s.first_search_date, DAY) AS days_to_purchase
FROM searches s
LEFT JOIN purchases p
ON p.user_pseudo_id = s.user_pseudo_id
AND p.transaction_date BETWEEN s.first_search_date
AND DATE_ADD(s.first_search_date, INTERVAL 7 DAY)
)
SELECT
search_term,
COUNT(DISTINCT user_pseudo_id) AS searchers,
COUNT(DISTINCT CASE WHEN purchase_revenue IS NOT NULL THEN user_pseudo_id END) AS buyers,
ROUND(
SAFE_DIVIDE(
COUNT(DISTINCT CASE WHEN purchase_revenue IS NOT NULL THEN user_pseudo_id END),
COUNT(DISTINCT user_pseudo_id)
) * 100, 1
) AS purchase_rate_pct,
ROUND(SUM(purchase_revenue), 2) AS attributed_revenue,
ROUND(AVG(days_to_purchase), 1) AS avg_days_to_purchase
FROM search_purchases
GROUP BY ALL
HAVING COUNT(DISTINCT user_pseudo_id) >= 10
ORDER BY attributed_revenue DESC NULLS LAST
Replace
superform_outputswith your actual dataset name.
The HAVING clause cuts out the long tail of one-off searches. Ten searchers is a reasonable minimum, but adjust it to your traffic volume.
avg_days_to_purchase only averages over users who actually bought, so it tells you the typical delay for each term. A value of 0 means the purchase happened same day. A value of 3.5 means people sleep on it. That difference matters.
What you’re looking at
Sorted by attributed_revenue DESC, this shows you which search terms are doing the most work. A few patterns worth looking for:
High searchers, low purchase rate. The term people search constantly but rarely buy from. Either your results page isn’t showing the right products, or the intent is research, not purchase. Worth checking what the search results page actually returns for these terms.
Low searchers, high purchase rate. These are the high-intent searches. Specific product names, SKU codes, exact model numbers. Someone searching at this level of detail usually knows what they want. If the result quality is bad here, you’re turning away buyers who are already ready.
High avg_days_to_purchase. These are the “sleep on it” terms. High-consideration items, gift purchases, things people compare before committing. If you run email retargeting or remarketing, these searchers are a natural audience: they looked, they didn’t buy, but they came back.
Terms with zero buyers. Might be totally fine (browsing intent), or might signal a gap in your catalogue or a broken search configuration. Filter to buyers = 0 and look at the top terms by searcher count.
One thing to keep in mind: view_search_results is the standard GA4 event for site search. If your site fires a custom event name instead, swap it out in the WHERE clause. Same for the 7-day window: extend it to 14 or 30 days for longer consideration cycles like furniture or outdoor gear.
Your turn
Run this against your last 90 days and sort by attributed_revenue. You’ll likely find a handful of terms responsible for a disproportionate share of revenue, and a much longer list that drives no purchases at all.
Start with the high-revenue terms: are the search results actually good? Is stock available? Is the price competitive? These are the searches where improving results quality has the most direct impact on revenue.
Try it and let us know what you find.



