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

Закрепи формулу arpdau в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать arpdau в Telegram

Зачем ARPDAU

В мобильной игре revenue 100 000$ в день. Радует. Аналитик копает: DAU выросло с 500 тыс. до 800 тыс. за месяц, а revenue — только с 90 тыс. до 100 тыс. ARPDAU упал с 0,18$ до 0,125$. Новые юзеры пришли менее платящие — органика или плохие источники.

ARPDAU — рабочая метрика mobile gaming, freemium-приложений и медиа: показывает «качество» каждого активного пользователя в день. В статье — SQL и нюансы (не путать с ARPU).

Что такое ARPDAU

ARPDAU (Average Revenue Per Daily Active User) — средняя выручка с одного активного пользователя в день.

ARPDAU(day) = Revenue(day) / DAU(day)

ARPDAU обычно усредняют за период (неделя/месяц) как:

Period ARPDAU = Total revenue / Sum of DAU per day

Не делите period revenue / period unique users — это будет ARPU, а не ARPDAU.

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

Данные: events(user_id, event_date), transactions(user_id, amount, paid_at).

WITH daily_dau AS (
    SELECT
        event_date,
        COUNT(DISTINCT user_id) AS dau
    FROM events
    WHERE event_date >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY event_date
),
daily_revenue AS (
    SELECT
        paid_at::DATE AS day,
        SUM(amount) AS revenue
    FROM transactions
    WHERE paid_at::DATE >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY 1
)
SELECT
    d.event_date AS day,
    d.dau,
    COALESCE(r.revenue, 0) AS revenue,
    COALESCE(r.revenue, 0)::NUMERIC / NULLIF(d.dau, 0) AS arpdau
FROM daily_dau d
LEFT JOIN daily_revenue r ON r.day = d.event_date
ORDER BY d.event_date;

Важно: LEFT JOIN с DAU как ведущей таблицей — иначе дни без транзакций потеряются (а они валидны: ARPDAU = 0).

ARPDAU по сегментам

По платформе (iOS / Android)

WITH daily AS (
    SELECT
        e.event_date,
        u.platform,
        COUNT(DISTINCT e.user_id) AS dau
    FROM events e
    JOIN users u ON u.user_id = e.user_id
    WHERE e.event_date >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY e.event_date, u.platform
),
revenue AS (
    SELECT
        t.paid_at::DATE AS day,
        u.platform,
        SUM(t.amount) AS revenue
    FROM transactions t
    JOIN users u ON u.user_id = t.user_id
    WHERE t.paid_at::DATE >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY 1, u.platform
)
SELECT
    d.platform,
    SUM(COALESCE(r.revenue, 0))::NUMERIC
        / NULLIF(SUM(d.dau), 0) AS arpdau_30d
FROM daily d
LEFT JOIN revenue r ON r.day = d.event_date AND r.platform = d.platform
GROUP BY d.platform
ORDER BY arpdau_30d DESC;

Обычно iOS ARPDAU в 2-4 раза выше Android.

По стране

Агрегируем каждую сторону отдельно, чтобы JOIN не множил строки:

WITH daily_dau AS (
    SELECT u.country, e.event_date, COUNT(DISTINCT e.user_id) AS dau
    FROM events e
    JOIN users u ON u.user_id = e.user_id
    WHERE e.event_date >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY u.country, e.event_date
),
daily_revenue AS (
    SELECT u.country, t.paid_at::DATE AS day, SUM(t.amount) AS revenue
    FROM transactions t
    JOIN users u ON u.user_id = t.user_id
    WHERE t.paid_at::DATE >= CURRENT_DATE - INTERVAL '30 days'
    GROUP BY u.country, t.paid_at::DATE
)
SELECT
    d.country,
    SUM(COALESCE(r.revenue, 0))::NUMERIC / NULLIF(SUM(d.dau), 0) AS arpdau_30d
FROM daily_dau d
LEFT JOIN daily_revenue r ON r.country = d.country AND r.day = d.event_date
GROUP BY d.country
ORDER BY arpdau_30d DESC;

Tier-1 (US, JP, KR, UK, AU) обычно даёт ARPDAU в 5-10 раз выше Tier-3.

Закрепи формулу arpdau в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать arpdau в Telegram

ARPDAU vs ARPU vs ARPPU

Метрика Что считаем Когда используют
ARPDAU Revenue / DAU за день mobile gaming, freemium с ежедневной активностью
ARPU Period revenue / period unique users subscription, SaaS — реже daily активность
ARPPU Period revenue / period paying users оценка качества платящей базы

В одной игре могут быть: ARPDAU = 0,25$, ARPU = 1,80$, ARPPU = 40$. Каждая метрика отвечает на свой вопрос.

-- За месяц апрель 2026
WITH stats AS (
    SELECT
        COUNT(DISTINCT user_id) AS mau,
        COUNT(DISTINCT CASE WHEN amount > 0 THEN user_id END) AS paying_users,
        SUM(amount) AS total_revenue,
        COUNT(DISTINCT user_id || '|' || event_date::TEXT) AS total_active_days
    FROM combined_events_transactions
    WHERE event_date >= '2026-04-01' AND event_date < '2026-05-01'
)
SELECT
    total_revenue::NUMERIC / NULLIF(total_active_days, 0) AS arpdau,
    total_revenue::NUMERIC / NULLIF(mau, 0) AS arpu_30d,
    total_revenue::NUMERIC / NULLIF(paying_users, 0) AS arppu_30d
FROM stats;

Динамика ARPDAU

Снова агрегируем каждую сторону до JOIN, иначе SUM revenue умножится на число events_per_user_per_day:

WITH daily_dau AS (
    SELECT event_date AS day, COUNT(DISTINCT user_id) AS dau
    FROM events
    WHERE event_date >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY 1
),
daily_revenue AS (
    SELECT paid_at::DATE AS day, SUM(amount) AS revenue
    FROM transactions
    WHERE paid_at::DATE >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY 1
),
daily AS (
    SELECT d.day, d.dau, COALESCE(r.revenue, 0) AS revenue
    FROM daily_dau d
    LEFT JOIN daily_revenue r ON r.day = d.day
)
SELECT
    day,
    dau,
    revenue,
    revenue::NUMERIC / NULLIF(dau, 0) AS arpdau,
    AVG(revenue::NUMERIC / NULLIF(dau, 0)) OVER (
        ORDER BY day
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS arpdau_7d_avg
FROM daily
ORDER BY day;

7-day rolling смягчает дневной шум — выходные и события (релизы, акции) дают +30-50% к ARPDAU.

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

Ошибка 1. Делить period revenue на period unique users

Это даёт ARPU (per user за период), а не ARPDAU. Если revenue 1М$ за месяц при 100К уникальных юзеров = ARPU 10$. ARPDAU для тех же данных мог быть 0,3$.

Ошибка 2. Не учитывать users с нулевой revenue

Если делать SUM(amount) / COUNT(DISTINCT user_id) только по платящим — это ARPPU, не ARPDAU. ARPDAU включает всех активных, даже неплатящих.

Ошибка 3. Дни без транзакций пропадают

INNER JOIN dau и revenue потеряет дни с 0 revenue. Нужен LEFT JOIN с COALESCE.

Ошибка 4. Дабл-каунт user × day

Если пользователь активен в этот день и в этот же день купил — он одна activity-точка. Не суммировать его как 2 events.

Ошибка 5. ARPDAU без timezone-нормализации

В Tier-1 регионах день начинается в разное время. Стандартизуйте по UTC или по timezone каждого юзера, чтобы границы дней не плыли.

Ошибка 6. Сравнивать ARPDAU mobile vs PC

ARPDAU в гипер-кэжуал мобайле — 0,05-0,10$. В midcore PC — 0,80-1,50$. Это разные продукты, бенчмарки разные.

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

FAQ

Какой ARPDAU считается хорошим?

Hyper-casual mobile — 0,05-0,15$. Mid-core mobile — 0,30-0,80$. AAA mobile — 1-3$. Подписочный media — 0,15-0,40$. Сравнивайте только в своей категории.

ARPDAU или LTV — что важнее?

LTV — это «сколько юзер принесёт за весь жизненный цикл». ARPDAU — «сколько приносит сегодня». LTV — стратегия, ARPDAU — операционная метрика. Обе важны.

ARPDAU включает рекламу или только in-app purchases?

Зависит от продукта. В hyper-casual обычно вся монетизация — реклама → ARPDAU = ads revenue / DAU. В midcore — IAP + ads. Уточните, что считаете.

Что делать, если ARPDAU падает?

Декомпозируйте: 1) Состав DAU изменился? (новые vs возвращающиеся, страны). 2) Платящая база? (paying users / DAU). 3) Средний платёж? (ARPPU). 4) Цены/набор продуктов изменился? Найдите конкретный сегмент с провалом.

ARPDAU вырос, а revenue упал — как такое?

DAU упал быстрее, чем revenue: меньше активных юзеров, но оставшиеся платят больше. Часто после оттока casual-аудитории остаются «киты». Хорошо для unit-экономики, но плохо для общего бизнеса.