Модуль определения источников посетителей сайта для Ruby on Rails

в 10:18, , рубрики: ruby on rails, веб-аналитика, метки: ,

Этот пост в основном о веб-аналитике: о том, как корректно определять источники посетителей вашего сайта, и о моём модуле для Ruby on Rails, который помогает в этом нелёгком деле. В конце есть небольшая часть, на которую я попрошу обратить внимание участников Rails сообщества: она обо мне и Rails. Но давайте по порядку.

Часть первая. О веб-аналитике и определении источников посетителей

Проблема

Есть довольно тривиальная задача: определить источник посетителя, пришедшего на наш сайт. Не знаю как вы, а мы довольно долго паразитировали на теле кук Google Analytics: брали utmz, потрошили её на сорсы да медиумы и жили-не-тужили. Analytics за нас решал вопросы перезаписи источников, учета сессий и вобще избавлял от всяких головняков парсинга рефереров. Но всё хорошее когда-нибудь заканчивается.

Когда гугл выкатил бету Universal стало понятно, что рано или поздно с гугловской печенькой придется попрощаться и научиться всё делать самому. Но поскольку тогда он заявлял о несовместимости Classic и Universal, то пока сидеть можно было ровно: Classic будет поддерживаться ещё долго.

В новой версии GA кука осталась всего одна — с id пользователя. Analytics отправляет её на свой сервер и уже там производит все вычисления. И ни через куки, ни через js информацию об источнике из него теперь не вытянешь.

Но недавно Google начал аккуратно тыкать пользователей палочкой: он выкатил конвертер профилей — Classic → Universal. И вот тут надо начинать шевелить булками: классическому Analytics придет окончательный Reader в момент, когда в Universal придут списки ремаркетингов. А это, думаю, не за горами.

В связи с этим я разродился на самопальный генератор печеньки utmz. И назвал его sourcebuster.

Сначала о форме

Генератор выполнен в формате Mountable engine для Ruby on Rails. Его можно довольно шустро приладить ко всем вашим Rails приложениям в качестве gem’а и обновлять одной командой из консоли. Модуль независимый и делает всё сам. Данные об источнике можно использовать для подмены номеров телефонов, контента на сайте, сохранять их вместе с заявками и использовать для дальнейшей аналитики. По определённым правилам модуль вычисляет источник (и ещё ряд параметров) и сохраняет их в куках посетителя.

Сразу ссылка на GitHub: https://github.com/alexfedoseev/sourcebuster
Я пока не разобрался с оформлением README.rdoc, в процессе, скоро исправлюсь.

Теперь о содержании

Большая часть логики повторяет логику GA, но есть некоторые отличия.
Начнем со структуры данных.

Структура данных

Всего у нас есть 4 главных типа трафика:

  1. utm — трафик, размеченый utm-метками
  2. organic — трафик из органической выдачи поисковых систем
  3. referral — реферальный трафик (ссылки со сторонних ресурсов)
  4. typein — прямые переходы

Логика фильтрации на изображении ниже:
image

Таким образом мы расфасовываем посетителей по этим 4 корзинам.
Далее нам нужно сформировать правили перезаписи источников, поскольку один посетитель может переходить на сайт в разное время с разных источников.

Логика перезаписи источников

Логика перезаписи повторяет логику Google Analytics:
image

Обратите внимание, что в рамках текущей сессии реферальные переходы ничего не перезаписывают. Почему — поясню на примере: часто посетитель в рамках текущего визита переходит на сайт со стороннего ресурса, который реальным источником не является — например из почтового сервиса, где у него была ссылка на активацию регистрации.
В данной системе я решил помимо перезаписанных данных о текущем визите хранить данные о самом первом посещении. То есть в момент совершения конверсии у нас будут данные о первом и текущем источниках посетителя.

Что конкретно можно вытащить с помощью модуля:

  • Данные о самом первом источнике:
    utm_source, utm_medium, utm_campaign, utm_content, utm_term
  • Те же данные о текущем источнике
    (если пользователь совершил повторный переход из другого источника)
  • Дата первого посещения
  • Точка входа
  • Полный реферер, при котором произошла перезапись источника
  • ip и user agent пользователя
Установка модуля

Закладываемся, что вас уже есть rails-приложение, к которому вы хотите прикрутить модуль.

В Gemfile приложения добавляем:

gem 'sourcebuster', :git => "git@github.com:alexfedoseev/sourcebuster.git"

Устанавливаем:

bundle install

Поскольку это Mountable engine, он существует в изолированном пространстве имён.
Монтируем его в приложение, добавляя в routes.rb:

mount Sourcebuster::Engine => "/sourcebuster"

Далее нам нужно скопировать и выполнить все миграции.
Копируем:

bundle exec rake sourcebuster:install:migrations

И исполняем:

bundle exec rake db:migrate

В вашей базе данных появились 3 новых таблицы:

  • sourcebuster_referer_sources
    Данные о настраиваемых источниках.
  • sourcebuster_referer_types
    Данные о типах рефераллов (по сути utm_medium для referral трафика).
  • sourcebuster_settings
    Настройки приложения (продолжительность сессии и обработка поддоменов).

С ними ничего делать не надо, там уже есть данные «из коробки» и для них есть интерфейсы.

Более подробно о Mountable engines — http://guides.rubyonrails.org

Модуль почти подключён, остался последний штрих: позволить ему ставить куки в любом месте вашего приложения. Для этого в application_controller.rb вашего приложения добавляем:

class ApplicationController < ActionController::Base
  include Sourcebuster::CookieSettersHelper
  before_filter :set_sourcebuster_data
  helper_method :extract_sourcebuster_data

  # some code

  private

    def set_sourcebuster_data
      set_sourcebuster_cookies
    end

end

Вроде готово. Engine использует шаблоны главного приложения, поэтому стили вы можете настраивать сами (возможно, я это изменю). Я мог что-то упустить, если что-то не работает — пишите.

Использование

Модуль даёт следующие методы (точнее метод один, но вытасивает разные данные):

Методы модуля

# Cамый первый тип источника (utm / organic / referral / typein)
extract_sourcebuster_data(:sb_first, :typ)

# Cамый первый utm_source
extract_sourcebuster_data(:sb_first, :src)

# Cамый первый utm_medium
extract_sourcebuster_data(:sb_first, :mdm)

# Cамый первый utm_campaign
extract_sourcebuster_data(:sb_first, :cmp)

# Cамый первый utm_content
extract_sourcebuster_data(:sb_first, :cnt)

# Cамый первый utm_term
extract_sourcebuster_data(:sb_first, :trm)


# Текущий тип источника (utm / organic / referral / typein)
extract_sourcebuster_data(:sb_current, :typ)

# Текущий utm_source
extract_sourcebuster_data(:sb_current, :src)

# Текущий utm_medium
extract_sourcebuster_data(:sb_current, :mdm)

# Текущий utm_campaign
extract_sourcebuster_data(:sb_current, :cmp)

# Текущий utm_content
extract_sourcebuster_data(:sb_current, :cnt)

# Текущий utm_term
extract_sourcebuster_data(:sb_current, :trm)


# Дата первого посещения сайта
extract_sourcebuster_data(:sb_first_add, :fd)

# Точка входа
extract_sourcebuster_data(:sb_first_add, :ep)

# Полный реферер, при котором произошла перезапись источника
extract_sourcebuster_data(:sb_referer, :ref)

# ip пользователя
extract_sourcebuster_data(:sb_udata, :uip)

# И его user agent
extract_sourcebuster_data(:sb_udata, :uag)

Тестовая страница модуля: http://sandbox.alexfedoseev.com/sourcebuster/showoff
На неё можно переходить с разных источников и смотреть, что наопределял модуль.

Также модуль позволяет настраивать ряд дополнительных параметров.

Стандартные настройки

Интерфейс: http://sandbox.alexfedoseev.com/sourcebuster/settings

Продолжительность сессии
Через какое время после последней активности пользователя его визит считается завершённым. Указывается в минутах, по умолчанию — 30 минут.

Обработка поддоменов
Это по сути аналог _setDomainName в GA. Поясню на примере.
Допустим у вас есть сайт, на котором есть поддомены:

  • site.com
  • blog.site.com
  • shop.site.com

И вы хотите, чтобы переходы со страниц site.com на blog.site.com считались внутренними не-реферальными переходами (то есть при переходе с одного поддомена на другой источник не перезаписывается). Для этого в настройках нужно выставить галочку «I have subdomains and traffic between them should not be a referral» и в поле «Main host» добавить корневой хост сайта, все поддомены которого будут расцениваться модулем как один сайт. В нашем случае там указывается «site.com».

Если в поле указать blog.site.com, то переходы с alex.blog.site.com на blog.site.com будет не-реферальными, а переход с alex.blog.site.com на shop.site.com будет уже реферальным трафиком.

Дополнительные источники

Интерфейс: http://sandbox.alexfedoseev.com/sourcebuster/custom_sources

У системы есть возможность настроить обработку ряда дополнительных источников.
Настройка производится по следующим параметрам:

  • Домен
    По нему матчится источник, который будем обрабатывать.
  • Алиас
    Красивое / понятное имя источника.
  • Канал
    Можно задать referral, organic или social
  • Параметр запроса
    Параметр ключевого слова в url’е поисковой машины.

Нафига эта таблица нужна проще всего объяснить на примерах.

Пример 1
Вы хотите, чтобы система считала переходы с поиска Bing — органическим трафиком (что вполне справедливо).
Если вы зайдете на bing.com и вобъёте в поисковую строку запрос «apple», то попадёте на страницу выдачи с адресом вида:
www.bing.com/search?q=apple&go=&qs=n&form=QBLH&pq=apple&sc=8-5&sp=-1&sk=&cvid=718ad07527244c319ecebf44aa261f64

На его базе мы создаем новый особый источник:

  • Домен: bing.com
  • Алиас: bing
    Или как вы захотите, можете вобще ничего не писать, тогда будет подставляться хост реферера.
  • Канал: organic
  • Параметр ключевого слова: q
    Это символ между конструкциями «?» и «=ваш_запрос» в урле страницы с поисковой выдачей.

Теперь всё, что будет приходить с подобных страниц, будет считаться органическим трафиком.

Пример 2
Вы хотите выделить переходы из соц. сетей в отдельную группу.
Действуем по аналогичной схеме:

  • Домен: facebook.com
  • Алиас: facebook
  • Канал: social
  • Параметр ключевого слова: не нужен

Готово. Теперь все переходы по ссылкам из facebook (кроме размеченных utm-метками) будут со значением канала social.

В поле домен необходимо полностью указать зону (.com, .com.ru и т.д.). Если вы укажите значение facebook.com, то под этот фильтр не попадёт трафик с домена facebook.com.ru. А с домена m.facebook.com — попадёт.

Тесты

Исходники: https://github.com/alexfedoseev/sourcebuster/blob/master/test/integration/navigation_test.rb
Львиная доля тестов — это Selenium-тесты для проверки правильности определения и перезаписи источников. Написаны они на Ruby, но реализованы таким образом, чтобы можно было проверить не только код моего модуля, но в принципе любой его реализации (например, если кто-то будет портировать его на php или js). То есть они тестируют не методы, а результат их работы. Кроме того тут не используются суррогатные рефереры, а тестируются реальные переходы с реальных ресурсов. И если Яндекс что-то изменит в выдаче (например, перейдет на https, чем убъёт реферер), то тесты это покажут. Всё по-настоящему короче.

Сейчас в тестах довольно мясо и написаны они скорее под себя, но при желании разобраться можно.
Для того, чтобы протестировать переписанный код, нужно иметь:

  • страницу, свёрстанную по определенным правилам
    (см. в код тестовой страницы, находите id блоков с данными, если что — задавайте вопросы)
  • проиндексированную в поисковиках
    (яндекс, гугл, третий дополнительный (например, рамблер))
  • и находящуюся в топ-5 по определенному запросу
  • + ссылки на эту страницу из соц. сети и стороннего (реферального) сайта

В верхнем блоке кода указаны константы, которые нужно настроить перед запуском тестов. Из них понятно, что именно нужно подготовить.

И да, прогон тестов занимает около 20-30 минут.

Часть вторая. Обо мне и Rails

Вот уже 3,5 года я занимаюсь интернет-маркетингом, и не так давно я пришёл к тому, что генерация трафика — это не моё. Хочется генерить смысл, а не трафик. И я начал писать код. Случилось это около 9 месяцев назад. У меня нет никакого айтишно-математического бэкграунда, вникать во всё приходилось с нуля и самому. Помогли мне в этом книги Криса Пайна, Майкла Хартла и прочие интернеты.

В результате я написал себе блог, но около 5 месяцев назад я вынужден был сделать перерыв, и этот модуль — первое, что я написал после простоя. Я прошу участников Rails сообщества покритиковать реализацию и указать на явные и не очень косяки. За всё это время мне так и не удалось ни разу встретить живого человека, который пишет на Ruby, и довольно тяжело самому постигать всё и вся.

Заранее спасибо за критику и надеюсь этот пост будет кому-то полезен. Удач.

Автор: alexfedoseev

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js