Find the internal site search terms that lead to conversion

Written by
Jules Stuifbergen
Reading progress

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_results event 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_outputs with 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.

Jules Stuifbergen

Published at March 30, 2026

Continue Reading