Как посчитать Bounce Rate в SQL

Проверь себя · 1/3разбор после ответа
У пользователя first_name = ' Анна ' и last_name = ' Иванова ' (с лишними пробелами по краям). Что вернёт SELECT CONCAT(TRIM(first_name), ' ', TRIM(last_name))?

Зачем Bounce Rate

Маркетолог жалуется: «Я вливаю бюджет в Performance Max, трафик растёт, а конверсии стоят». Аналитик смотрит — bounce rate новых сессий 85%. Значит, пользователь заходит, видит лендинг и сразу уходит. Креатив привлекает «не тех» — деньги тратятся вхолостую.

Bounce rate — быстрый сигнал качества трафика, релевантности контента и UX лендинга. В статье — SQL для расчёта по разным определениям (single-page, engagement-based) и подводные камни.

Что такое Bounce Rate

Bounce rate — доля сессий, в которых пользователь не совершил действий (классически — посмотрел только одну страницу и ушёл).

Bounce rate = sessions с одной page view / all sessions

В GA4 — определение изменилось: bounce = «не engaged», где engaged = сессия >10 сек или с конверсией или с 2+ страницами.

Базовый расчёт

Данные: pageviews(session_id, page_url, timestamp).

Классический (single-page-bounce)

WITH session_pages AS (
    SELECT session_id, COUNT(*) AS page_count
    FROM pageviews
    GROUP BY session_id
)
SELECT
    COUNT(*) AS total_sessions,
    SUM(CASE WHEN page_count = 1 THEN 1 ELSE 0 END) AS bounced,
    SUM(CASE WHEN page_count = 1 THEN 1 ELSE 0 END) * 100.0
        / NULLIF(COUNT(*), 0) AS bounce_rate_pct
FROM session_pages;

Простой и понятный. Минус: засчитывает как bounce пользователя, который прочитал лендинг 5 минут и нажал кнопку «Связаться» (она открыла WhatsApp, а не следующую страницу).

Bounce по страницам и источникам

«На какой странице пользователи отваливаются чаще»:

WITH session_info AS (
    SELECT
        session_id,
        MIN(page_url) FILTER (WHERE rn = 1) AS landing_page,
        COUNT(*) AS page_count
    FROM (
        SELECT
            session_id,
            page_url,
            ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY TIMESTAMP) AS rn
        FROM pageviews
    ) ranked
    GROUP BY session_id
)
SELECT
    landing_page,
    COUNT(*) AS sessions,
    SUM(CASE WHEN page_count = 1 THEN 1 ELSE 0 END) * 100.0
        / NULLIF(COUNT(*), 0) AS bounce_rate_pct
FROM session_info
GROUP BY landing_page
HAVING COUNT(*) >= 100
ORDER BY bounce_rate_pct DESC;

HAVING COUNT(*) >= 100 — отсекаем страницы с микро-трафиком (10 заходов и 100% bounce ничего не говорят).

По источникам:

WITH session_summary AS (
    SELECT
        s.session_id,
        s.utm_source,
        COUNT(p.page_url) AS page_count
    FROM sessions s
    LEFT JOIN pageviews p ON p.session_id = s.session_id
    GROUP BY s.session_id, s.utm_source
)
SELECT
    utm_source,
    COUNT(*) AS sessions,
    SUM(CASE WHEN page_count <= 1 THEN 1 ELSE 0 END) * 100.0
        / NULLIF(COUNT(*), 0) AS bounce_rate_pct
FROM session_summary
GROUP BY utm_source
ORDER BY bounce_rate_pct DESC;
Закрепи формулу bounce rate в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать bounce rate в Telegram

Engaged-session bounce

Современное определение (GA4-style): bounce = сессия не engaged. Engaged = длительность >10 сек, ИЛИ конверсия, ИЛИ 2+ страницы.

WITH session_metrics AS (
    SELECT
        session_id,
        COUNT(*) AS page_count,
        EXTRACT(EPOCH FROM (MAX(TIMESTAMP) - MIN(TIMESTAMP))) AS duration_sec,
        BOOL_OR(event_type = 'conversion') AS had_conversion
    FROM events
    GROUP BY session_id
)
SELECT
    COUNT(*) AS total,
    SUM(CASE
        WHEN page_count >= 2 THEN 0
        WHEN duration_sec >= 10 THEN 0
        WHEN had_conversion THEN 0
        ELSE 1
    END) AS bounced,
    SUM(CASE
        WHEN page_count >= 2 THEN 0
        WHEN duration_sec >= 10 THEN 0
        WHEN had_conversion THEN 0
        ELSE 1
    END) * 100.0 / NULLIF(COUNT(*), 0) AS bounce_rate_pct
FROM session_metrics;

Этот bounce ниже классического — обычно на 10-30 п.п.

Частые ошибки

Ошибка 1. Считать bounce там, где это SPA

В Single Page App все «страницы» — это навигация по хешу. Если вы не отслеживаете смену маршрутов (route changes), все сессии окажутся одностраничными и bounce будет 95%+. Проверьте, что смена маршрута отправляет событие pageview.

Ошибка 2. Игнорировать время на странице

Пользователь прочитал блог-пост 8 минут и ушёл — это классический bounce, но по факту это позитивная вовлечённость. Используйте engaged-session bounce или глубину скролла (scroll-depth).

Ошибка 3. Сравнивать bounce лендинга и внутренней страницы

Bounce главной 30% и лендинга 60% — это нормально. Лендинг — пункт назначения для конкретного запроса. Сравнивайте однотипные страницы между собой.

Ошибка 4. Считать общий bounce без сегментации

Общий bounce 50% — бесполезный показатель. Сегментируйте по источнику, устройству, типу страницы — только так вы получите сигнал, по которому можно действовать.

Ошибка 5. Доверять bounce из бот-трафика

Если в данных нет фильтрации ботов — bounce будет завышен (боты часто заходят на одну страницу). Фильтруйте по user_agent или по флагу is_bot.

Ошибка 6. Bounce vs Exit rate

Bounce — доля сессий с одной страницы. Exit — доля сессий, где страница была последней. Это разные вещи.

Связанные темы

FAQ

Какой bounce rate считается нормальным?

Всё зависит от типа страницы. Для контент-блога 60–80% — это норма: человек прочитал статью и ушёл. Для главной e-commerce ориентир 30–50%, для лендинга с конкретным CTA — 40–60%, для SaaS-дашборда — 10–20%. Сравнивать bounce имеет смысл только между однотипными страницами.

Bounce 100% — что делать?

Почти всегда это проблема трекинга, а не поведения пользователей. Сначала проверьте, что смена маршрутов в SPA отправляет событие pageview. Если 100% bounce только на мобильных — проверьте, не блокирует ли баннер согласия (cookie consent) загрузку скриптов аналитики.

Bounce rate важнее или session duration?

Зависит от страницы. Для блога важнее длительность сессии — она показывает, дочитали ли контент. Для лендинга с CTA смотрите связку конверсии (CR) и bounce. Для каталога e-commerce ключевой сигнал — глубина просмотра, то есть число страниц за сессию.

Можно ли уменьшить bounce искусственно?

Технически да — например, добавив 10-секундный автоматический редирект или отправляя фейковый «второй pageview». Но делать так нельзя: вы обманываете себя и команду, а не решаете проблему. Работайте с реальной вовлечённостью, а не с цифрой в отчёте.

Bounce у моб vs десктопа отличаются?

Да, часто на мобильных bounce выше на 5–15 п.п.: экран меньше, страница грузится медленнее, пользователь чаще торопится. Это нормально — просто всегда сегментируйте bounce по устройству, а не смотрите усреднённую цифру.