Наша компания работает в сфере интернет рекламы. Около 2х лет назад мы окончательно разочаровались во встроенных в сети контекстной рекламы системах защиты от скликивания и решили делать свою, на тот момент еще для внутреннего пользования.

Под катом много технических подробностей функционирования системы, а также описания проблем, с которыми мы сталкивались в процессе работы и их решений. Если вам просто интересно посмотреть на систему — главная картинка кликабельна.

Первая задача, которую требовалось решить, это идентификация уникальных пользователей.
Т.е. нам необходимо идентифицировать пользователя даже если он меняет браузер или чистит cookies.
После недолгих раздумий и ряда экспериментов мы начали писать не только в cookies, а также в хранилища всех возможных плагинов для браузеров, у которых такие хранилища имеются, ну и прочее по мелочам, third-party cookies, различные JS storage.
В результате, мы не только в большинстве случаев идентифицируем пользователя, но и имеем некий цифровой слепок его компьютера(ОС, разрешение экрана, глубина цвета, наличие или отсутствие тех или иных плагинов, поддержка тех или иных JS storage и third-party cookies браузерами), который позволяет с высокой долей вероятности идентифицировать пользователя, даже если он умудрится почистить все, что мы ему поставили.
На данном этапе особых проблем, о которых стоило бы писать, не возникало.

Вторая задача — передача всех данных о пользователе на наш сервер.
Для получения наиболее полных данных мы используем 2 скрипта: серверный(PHP/Python/ASP.NET) и клиентский JS. Таким образом, мы имеем возможность получать информацию даже о тех пользователях, которые закрыли страницу, не дождавшись полной загрузки и, соответственно, отработки клиентского JS. Таких кликов по тизерной рекламе обычно не менее 30%, и других систем, которые их учитывают, мы не нашли. Следовательно, мы получаем существенно больше данных чем те же Метрика, Analytics и все прочие системы статистики с JS счетчиками.
Данные отправляются нам на сервер через кроссдоменный AJAX, а в случае, если браузер его не поддерживает — через iframe. Отправка производится при загрузке страницы, а также по ряду JS событий. Это позволяет нам анализировать поведение пользователей на сайте и отличать ботов от реальных пользователей по паттернам поведения на сайте, а также несовершенной имитации определенных событий Javascript. Например, очень многие боты имитируют событие onClick, но при этом не генерируют события onMouseDown, onMouseUp…

Вот мы плавно и подошли к третьей задаче — выбору железа.
Архитектурно в данный момент система состоит из 4х сегментов:
  • Фронтенд
  • Сбор и обработка данных
  • Индексация целевых страниц
  • Хранилище логинов/паролей к сторонним сервисам

Все домены подвязаны Amazon Route 53 с ttl 60 сек, что бы в случае любых возможных проблем с серверами оперативно мигрировать на резервные.
О фронтенде особо сказать нечего. Нагрузка на него небольшая — справится практически любой vps.
Со сбором и обработкой данных все несколько сложнее, так как необходимо работать с большими объемами данных. На сегодняшний день мы обрабатываем около 200 запросов каждую секунду.
Благодаря правильному изначальному выбору железа и софта, с этим объемом отлично справляется один сервер.
По железу — 8-ядерный AMD, RAID10 из SAS дисков, 16Gb RAM.
Сбор данных осуществляется оттюнингованой связкой nginx+php-fpm+mysql, обработка — скриптами на C++.
Вначале мы столкнулись с проблемой интенсивного потребления ресурсов CPU скриптом сбора данных. Решение нашлось совершенно неожиданно. Заменив все ereg_ функции php на их preg_ аналоги мы сократили потребление CPU примерно в 8 раз, чем были очень удивлены.
На случай проблем с текущим сервером или появления необходимости масштабирования, в другом ДЦ своего часа ждет второй сервер схожей конфигурации с возможностью введения в эксплуатацию в течение часа.
Индексацией целевых страниц у нас занимается отдельный сервер с выделенным блоком IP, довольно прожорливый по CPU и RAM, однако, абсолютно не требовательный к дисковой подсистеме. Индексация производится «поисковым ботом», написанным на Python.
Данный узел у нас не дублируется, однако, его замена или расширение занимает менее суток, и непосредственно на качество анализа трафика он не влияет, в худшем случае несколько рекламных кампаний не остановятся, если у клиента ляжет сайт или с сайта пропадет наш код.
Хранилище логинов/паролей к сторонним сервисам — вещь довольно специфичная и в общем-то с точки зрения безопасности нехорошая.
Однако, у большинства рекламных сетей API не дает всего необходимого функционала и приходится парсить их веб-интерфейс, что без пароля делать затруднительно. Например, в Google Adwords бан IP адресов возможен только через веб-интерфейс. Бонусом, пользователи имеют возможность из интерфейса нашей системы одним кликом переходить в свои аккаунты рекламных сетей.
Это четвертая задача — обеспечение безопасности данных при хранении их в открытом виде.
Для максимально безопасного хранения данных мы создали следующую схему:
  • Если пароль получается нами через веб-интерфейс
    • Мы кладем его в базу фронтенда, симметрично шифруя паролем клиента к нашему сервису
    • Также в базу фронтенда кладется пароль, асимметрично зашифрованный открытым ключом на сервере
    • Хранилище периодически делает запросы к базе сервера, забирая шифрованные пароли рекламных сетей, расшифровывает их закрытым ключом и кладет в свою базу
  • Если пароль генерируется нами на хранилище
    • Мы кладем его в базу хранилища
    • При следующем логине пользователя в базу фронтенда кладется его пароль, асимметрично зашифрованный открытым ключом на сервере
    • Хранилище периодически делает запросы к базе сервера, забирая шифрованные пароли, расшифровывает их закрытым ключом
    • Затем хранилище симметрично шифрует пароли из своей базы полученными паролями пользователя и кладет их в шифрованном виде на фронтенд
  • При логине пользователя на наш сервис его пароль специфическим методом сохраняется внутри JSа и используется для дешифрации на стороне клиента паролей от рекламных сетей и логина в них по клику
  • Доступ на хранилище разрешен только с ряда ИП, к которым у нас есть доступ.
  • IP хранилища держится в секрете, входящие запросы к хранилищу отсутствуют

Ввиду того, что парсить некоторые веб-интерфейсы без применения полной эмуляции браузера у нас пока не получается, хранилище требовательно к RAM и CPU. В другом ДЦ на случай непредвиденных обстоятельств также ждет резервный сервер хранилища, готовый начать работу в течение часа.

Пятой и последней задачей стала интеграция с рекламными сетями для автоматического бана «плохих» IP и площадок.
С условно небольшими сетями, такими как Бегун и МаркетГид, проблем не возникало, все взаимодействие работает по API, если каких-то методов не хватает, партнеры их оперативно дописывают.
А вот с Директом и, особенно, AdWords проблем хватает. Получение API в AdWords превращается в целый квест. Сначала месяц его получаешь, потом оказывается, что половины функций там нет и все равно надо парсить веб-интерфейс. Затем оказывается, что даже те функции, которые есть, жестко лимитированы юнитами, которых в Basic API и докупить то нельзя. И начинается новый квест с получением API следующего уровня доступа, с расширенным количество юнитов. Как видите, поисковые гиганты делают все, что бы максимально усложнить рекламодателям возможности оптимизации рекламных затрат. Впрочем, на данный момент, мы тем не менее успешно анализируем их трафик и очищаем его в автоматическом режиме.

В сухом остатке, в данный момент наша система не имеет реальных конкурентов, сходных по возможностям и, что самое главное, сопоставимых по качеству детекции некачественного трафика. В отдельных случаях, мы видим на 40-45% больше трафика, чем другие аналитические системы.
Стоимость аудита трафика, в среднем, примерно в 100 раз меньше стоимости покупаемой рекламы, а для отдельных рекламных систем услуга и вовсе бесплатна. При этом экономия составляет от 10 до 50% рекламного бюджета, а иногда даже до 90%.
В данный момент в полностью автоматическом режиме система работает с Яндекс.Директ, Google AdWords, Begun и МаркетГид. С любыми другими рекламными системами сервис работает в режиме аудита трафика с последующим ручным добавлением мошеннических IP и площадок в их блеклисты.

Присоединяйтесь!