В этой статье речь пойдет о том, как правильно анализировать источники трафика, например, с помощью инструментов Google Analytics или Yandex Metrica. Отключив источники с низкой либо нулевой конверсией, можно существенно поднять общую конверсию, снизить стоимость заказа и улучшить рентабельность интернет-рекламы.
Цель этой статьи — получить отзывы и замечания по описанным ниже методам, описать способы принятия обоснованных решений по блокировке некачественных источников трафика.
Итак, предположим, что мы решили организовать свой маленький бизнес по продаже, например, книг, через интернет. Мы создали замечательный юзер-френдли сайт, зайдя на который просто невозможно что-либо не купить. Погуглив отзывы, мы выбрали одну из множества рекламных сетей как источник недорогого трафика для нашего магазина. Как правило, все рекламные сети не обладают собственным трафиком, а покупают его у различных источников. Качество трафика разных источников может быть крайне разнообразным. На каких-то источниках может быть самая наглая накрутка, от которой никакой конверсии ждать не придется. С других источников идут случайные клики, а не целевые переходы. На третьих источниках аудитория интересуется семками и битами, а не книгами. На четвертых источниках, напротив, сконцентрированы любители книг, для которых наш ресурс будет просто находкой, и конверсия превысит все ожидания.
Обычно все развитые рекламные сети предоставляют доступ к своим источникам посредством UTM-разметки и дают возможность блокировать источники, которые нам не нравятся. Нам остается только научиться правильно находить те некачественные источники, без отключения которых мы будем выбрасывать деньги на ветер, а то и вовсе обанкротимся. Кроме того, грамотная оптимизация источников позволит нам снизить затраты на рекламу, мы сможем понизить цену товара и стать значительно более конкурентоспособными на рынке.
Приходилось неоднократно сталкиваться с плохо обоснованным подходом к анализу источников, который называется «на глаз». В одной из разновидностей этого способа просто отключаются источники, которые не дают никакой конверсии, например, со 100 визитов (это число прикидывается в уме). Либо, например, это число визитов дают конверсию ниже 0.1% (число также прикидывается в уме). На самом деле это правильные подходы, кроме «прикидывания в уме», которое может привести к разным ошибкам. Особую остроту приобретает ситуация, когда приходится нести персональную ответственность за принятые решения. В этом случае очень важно уметь обосновать, почему эти источники были заблокированы, а те — не были. “Показалось” здесь будет крайне неуместным. В этой статье будет описано, как обосновать эти значения и минимизировать риски отключить вполне хороший источник.
Для начала нам следует определиться с допустимыми погрешностями. В статистике рассматривают ошибку первого рода и ошибку второго рода.
В нашем случае ошибка первого рода — это когда по случайно сложившимся обстоятельствам мы не отключим плохой источник. Для нас ошибка этого рода не критична: не заблокировали сегодня — заблокируем завтра, когда случайные обстоятельства подуют в правильную сторону.
Более критичной для нас является ошибка второго рода. В нашем случае это момент, когда мы из-за случайностей заблокируем хороший источник. Критично это потому, что после блокировки трафик с него остановится, и у него уже больше не будет шансов доказать, что на самом деле был хорошим.
Вероятность такой ошибки B обычно выбирают 5% или 1% в зависимости от ситуации. Если ситуация критична, реклама не окупается, уходят серьезные суммы, то можно вооружиться вероятностью блокировки хорошего источника в 5% или даже 10%. Если же ситуация стабильна, но просто хочется оптимизировать источники, то лучше выбрать 1%, чтобы минимизировать потери хороших источников. Уровень допустимых ошибок в 1% потребует от нас значительно больше трафика для статистики, чем уровень 5%.
Хотелось бы заметить, что если мы выбрали уровень ошибки, например, 5%, то это совсем не значит, что мы потеряем 5% хороших источников. Это означает, что при граничных (и маловероятных) ситуациях мы потеряем не более 5% хороших источников из тех, что заблокируем.
Следующим этапом следует определить критический уровень конверсии Ccr — трафик с конверсией, ниже которого мы не готовы покупать. Источники с конверсией ниже этого значения будут отключены. А вот источники с конверсией выше этого значения ни в коем случае не должны быть отключены (вернее, вероятность отключения таких источников не должна быть выше допустимой B). Если мы занимаемся оптимизацией источников, мы можем выбрать Ccr как 30% от текущего среднего значения конверсии.
После того как мы определились с базовыми значениями, мы можем запускать рекламу и наблюдать ситуацию в Аналитиксе или в Метрике. Для того чтобы собрать статистику, требуется заложить под это определенный бюджет.
Первый способ обнаружения некачественных источников особенно эффективен на первом этапе — это определение источников, которые не принесли ни одной конверсии, но уже набрали достаточное количество визитов. Рассчитаем пороговое значение количества визитов, выше которого уже можно блокировать источники (если они не принесли ни одной конверсии).
Предположим, что у некоторого источника как раз и есть тот критический уровень конверсии Сcr. Тогда вероятность того, что заказа не произойдет при визите, будет 1-Ccr. А вероятность того, что не произойдет ни одного заказа при N визитах, будет
Приравняем эту вероятность к допустимому уровню вероятности ошибки B, который мы определили в самом начале. Тогда при критическом значении Ncr мы как раз получим это значение.
Чтобы найти Ncr, нам следует логарифмировать обе части выражения и, собственно, найти Ncr
(1)
Вместо натурального логарифма в вычислениях можно использовать также двоичный или десятичный, если это проще. Итак, определив критическое значение числа визитов Ncr, мы можем смело отключать все источники, которые превысили это число визитов и не дали ни одной конверсии, и при этом можно не волноваться — риск того, что мы выключим хороший источник, не более того, что мы себе задали.
Отключив некачественные источники первым способом и ощутив радость улучшения конверта и горечь уменьшения объемов трафика, мы можем перейти ко второму, более сложному (в вычислительном отношении) способу поиска некачественных источников.
Предположим, что некоторые источники значительно превысили критическое значение Ncr, принесли заказы, но их конверсия кажется нам низкой. Мы их не можем заблокировать по первому способу, но, может быть, их истинная конверсия (которой мы не знаем) все-таки ниже той критической, которую мы для себя установили. Попробуем найти такие источники с допустимыми рисками B.
Мы не можем блокировать источники только потому, что их конверсия ниже Сcr, т.к. такую конверсию случайно могут показать и источники с конверсией выше Ccr. Чтобы исключить это, мы должны блокировать источники, у которых конверсия несколько ниже Ccr и должна быть меньше некоторой граничной величины Cx. Изменяя величину Cx, мы сможем добиться того, что вероятность блокировки источников, конверсия которых выше Ccr, будет не выше оговоренной нами B. Попробуем рассчитать эту граничную величину Cx.
Количество заказов на фиксированной выборке с фиксированной конверсией (а у нас как раз именно эти условия) будут подчиняться биномиальному распределению
Как известно, при значительных n (число визитов) биномиальное распределение стремится к нормальному с математическим ожиданием m=n*p и дисперсией D=s^2=n*p*q (p, в нашем случае это конверсия, а q = 1-p).
Предположим, что некоторый источник имеет критическое значение конверсии Ccr. Тогда вероятность К того, что при n визитах он покажет конверсию Cx или менее, равна:
По таблицам нормального распределения или с помощью пакета numpy в python находим соответствующие квантили K — такие значения нормальной функции, при которых вероятности будут соответствовать допустимым ошибкам B:
>>>from scipy.stats import norm
>>> norm.ppf(0.05)
-1.6448536269514729
>>> norm.ppf(0.01)
-2.3263478740408408
Тогда получаем:
Откуда:
(2)
Таким образом, если текущая конверсия источника при соответствующем количестве визитов ниже граничной Cx, то источник нужно блокировать.
Если n мало, то Cx может получится отрицательной. Это значит, что данного количества визитов недостаточно для оценки источников. Из формулы видно, что при увеличении числа визитов n Сx будет стремиться к Ccr снизу, что логически ожидаемо.
Вручную расчитывать для каждого источника его Cx весьма затруднительно, поэтому привожу исходный код простого python-скрипта, который обрабатывает csv выгрузку из Аналитикса и дописывает колонку с граничными Cx для последующего анализа и поиска источников для блокировки:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import csv
import math
from scipy.stats import norm
# Исходный файл, например, выгрузка из Аналитикса
file_in = 'in.csv'
# Файл в который будет записан результат
file_out = 'out.csv'
# Критическое значение конверсии !ВНИМАНИЕ! в % , ниже которого источник должен быть удален
Ccr = 1.0
# Погрешность - вероятность блокировки хорошего источника (конверт которого на самом деле выше критического)
B = 0.05
# Колонка, в которой находится название источника (первая колонка - 1)
column_source = 1
# Колонка, в которой находится количество визитов
column_n = 2
# Колонка, в которой находится процент конверсий источника
column_c = 4
K = norm.ppf(B)
Ccr = float(Ccr) / 100
# У компьютеров индексы массивов начинают считаются не как у людей, а с 0, поэтому:
column_source -=1
column_n -=1
column_c -=1
out_data = []
with open(file_in, 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
for i, row in enumerate(reader):
#Обрабатываем заголовки, которые всегда есть в выгрузках Аналитикса
if not i:
out_data.append([row[column_source], row[column_n], row[column_c], 'Cx, %'])
continue
n = row[column_n]
n = n.replace(' ', '')
n = int(n)
C = row[column_c]
# В выгрузках Аналитикса зачем-то в каждую ячейку записывают знак процента,
# вероятно для того, что бы усложнить использование формул
C.replace('%', '')
C.replace(',', '.')
Cx = Ccr + K * math.sqrt(Ccr * (1 - Ccr) / n)
Cx = round(Cx * 100, 3)
out_data.append([row[column_source], str(n), C, str(Cx)])
with open(file_out, 'wb') as csvfile:
writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
for row in out_data:
writer.writerow(row)
Рассмотрим ниже простой пример анализа источников. Предположим, у нас есть 8 источников с такими данными:
Источник | Визиты | Заказы | Конверсия, % |
---|---|---|---|
1 | 844 | 3 | 0.355 |
2 | 751 | 47 | 6.258 |
3 | 520 | 1 | 0.192 |
4 | 397 | 40 | 10.076 |
5 | 315 | 0 | 0 |
6 | 301 | 0 | 0 |
7 | 162 | 8 | 4.938 |
8 | 12 | 0 | 0 |
Возможно, пример выглядит несколько искусственным, потому что тут и “на глаз” видно, где что нужно блокировать. Это так, потому что, во-первых, здесь их мало, во-вторых, их свойства ярко выражены. На практике масса граничных случаев, когда даже самый опытный “глаз” обязательно примет неправильное решение.
Итак, общая конверсия этой системы = Сm = Сумма всех заказов / Сумма всех визитов = 2.998%
Выберем критическое значение как 0.3*Сm = 1%
По формуле (1) рассчитаем пороговое значение, которым можно отделить источники с нулевой конверсией.
Ncr = ln(0.05)/ln(1-0.01) = 298
Теперь ищем источники, у которых конверсия 0 и количество визитов более 298. Таких у нас 2 источника: 5 и 6. Их мы блокируем по первому признаку.
Источник 8 по этому признаку мы отключить не можем, потому что, несмотря на то, что там конверсия 0 — посетителей было очень мало, и мы не можем быть уверены, что ее истинная конверсия на самом деле ниже критической. Быть может, на самом деле ее конверсия еще выше, чем у источника 7, не смотря на то, что тот показывает очень неплохие результаты.
Теперь перейдем к второму признаку.
Посчитаем граничное значение конверсии для первого источника по формуле (2):
Cx = 0.01 + (-1.64) * sqrt(0.01*(1-0.01)/844) = 0.00438 = 0.438%
Таким образом, текущая конверсия этого источника ниже граничной, и мы можем с вероятностью ошибки не более 5% утверждать, что конверсия этого источника ниже критической. Таким образом, этот источник подлежит блокировке.
Чтобы не считать вручную оставшиеся 7 конверсий, я использую приведенный выше скрипт. Сохраняем исходные данные в файл in.csv. Внимательно просматриваем и настраиваем переменные в начале скрипта, запускаем calc.py и смотрим результаты в out.csv, который покажет нам следующий результат:
Источник | Визиты | Конверсия, % | Cx, % |
---|---|---|---|
1 | 844 | 0.355 | 0.437 |
2 | 751 | 6.258 | 0.403 |
3 | 520 | 0.192 | 0.282 |
4 | 397 | 10.076 | 0.179 |
5 | 315 | 0 | 0.078 |
6 | 301 | 0 | 0.057 |
7 | 162 | 4.938 | -0.286 |
8 | 12 | 0 | -3.724 |
Сравнив текущую и граничные конверсии, мы можем увидеть, что источник 3 также подлежит блокировке.
Интересно также отметить, что источники 5 и 6 снова попадают под блокировку. Это понятно, так как метод 2 не противоречит методу 1, но расширяет его на случай, когда текущая конверсия источника не 0.
Граничная конверсия источников 7 и 8 ниже нуля. Это значит, что при том количестве визитов, которые на данный момент имеют те источники, они не могут быть заблокированы ни при каком количестве заказов (ну, разве что при отрицательном). Их количества визитов недостаточно, чтобы делать какие-либо прогнозы с допустимой вероятностью ошибки.
Вот таким образом мы можем подвести математическое обоснование под свои решения по блокировке источников. Следует, конечно, заметить, что для успешного блокирования источников с вероятностью ошибки не выше заданной, необходимо достаточно высокое количество посетителей из анализируемого источника. Для примера, если Сcr задать в 0.38%, то отключения этого источника по отсутствию конверта потребуется уже не менее 787 переходов. А, к примеру, для граничной конверсии Cx=0.119 при тех же значениях требуется уже около 1500 визитов с этого источника. Но визиты, анализируются не за один день, иногда даже за месяц, поэтому такие трудности могут ожидать только недавно начавшиеся рекламные кампании. Кроме того, есть способы значительного улучшения чувствительности, но это тема, вероятно, уже другой статьи.
Буду признателен за указание ошибок и неточностей. Успешных рекламных кампаний!
Автор: eu-gen