Билетный агрегатор на весь мир: 48 сайтов на 9 языках, импорт от партнёров и нейросеть, которая раскладывает события по полкам
Задача
Ticketeria задумывалась как международная витрина билетов: концерты, спектакли, футбол, фестивали, музеи и экскурсии во всех странах, где есть что посмотреть. Своих билетов у агрегатора нет: события мы брали у партнёров, с которыми заключали официальные договоры. Каждый отдавал данные по-своему: одни через API, другие выгрузками, третьи присылали таблицы на почту. Из этого потока нужно было собрать аккуратную витрину: отдельный сайт для каждой страны, на языке и в валюте посетителя, с поиском событий по всему миру. Главным каналом трафика должен был стать поиск, а не реклама.
Масштаб
Это один из самых больших проектов, которые мы делали. Мы прошли весь путь: от прототипов и дизайна до серверного кластера. Сделали интерфейс всего сайта и его AMP-версию, админку с системой импорта данных от партнёров, механизм карт сайта для Google, сквозную аналитику продаж и сводную отчётность по поиску сразу по всем странам. Над кодом работало больше десятка разработчиков, в GitLab проекта больше сорока репозиториев.
Сначала прототип, потом дизайн
Каждый экран сначала собирали прототипом: серые блоки и оранжевые пометки для разработчика. Что происходит по клику, откуда берутся данные, какие у блока состояния, что делать, если данных нет. Отдельными документами шли требования по SEO и схема адресов страниц. Только когда логика была согласована, экран уходил в дизайн. В итоге 13 разделов, и каждый экран нарисован в семи ширинах: от 320 пикселей телефона до 1800 большого монитора.

48 стран — одна платформа
Все 48 сайтов работают на одном коде. По домену сайт определяет страну, язык и валюту по умолчанию, а посетитель может переключить любое из трёх, не теряя фильтров. Витрина каждой страны показывает свои события, но поиск находит события других стран и городов. Выдача никогда не бывает пустой: сначала события в радиусе от выбранных городов, потом по стране, потом по всему миру.
Два бренда под разные рынки: Ticketeria для Испании, Франции, Великобритании, Мексики, Кореи и двадцати с лишним стран Европы и Азии на поддоменах вида finland.ticketeria.eu, и Entradaria для Германии, Италии, России, Канады, Австралии, Японии, Бразилии и ещё нескольких стран. Цены пересчитываются в 19 валют по курсам, которые обновляются каждый день.
Откуда берутся события: система импорта
Своих билетов у агрегатора нет: события мы брали у партнёров, с которыми заключали официальные договоры. Это билетные операторы и партнёрские сети, через которые подключаются десятки продавцов. Каждый отдавал данные по-своему: одни через API, другие выгрузками, третьи присылали таблицы на почту. Поля, категории, форматы дат, часовые пояса и валюты у всех разные.
Первые интеграции писали под каждого партнёра отдельно. Когда стало понятно, что источников будут десятки, мы спроектировали в админке универсальную систему импорта. Новый источник теперь подключается настройкой, а не разработкой: к осени 2020 года через неё работало 59 источников. Большие выгрузки читаются потоком, не целиком, а запросы к партнёру идут по очереди, с паузами, чтобы его сервер не принял их за атаку.
- Шлюз
Откуда и как забирать данные: адрес, формат, авторизация, постраничная выдача. Настраивается в админке, без программиста
- Склад
Сырые данные партнёра лежат на своей «полке». Их можно переобработать новыми правилами без повторной выгрузки
- Поток
Сопоставление полей, чистка, правила категорий, проверка и предпросмотр по всей выгрузке до запуска
- Обогащение
Нейросеть ставит категории, сервис геокодинга уточняет адрес, описание переводится на 9 языков, картинки нарезаются под все экраны
- Витрина
Событие появляется на сайтах нужных стран и в картах сайта, прошедшие уходят с витрины сами



Нейросеть раскладывает события по полкам
Правила хорошо работают, пока партнёр присылает аккуратные категории. Но у каждого категории свои, у части их нет совсем, а событий десятки тысяч. Поэтому раскладку по категориям меню мы доверили нейросети.
Модели было две. Первая построена на BERT, той же технологии, на которой Google понимает поисковые запросы: она читает название, описание и площадку и называет главную категорию и ещё две подходящие. Вторая, лёгкая и быстрая, работала в ежедневном потоке вместе со словарём категорий партнёров. В админке у каждого события видны теги трёх цветов: от партнёра, из словаря и от нейросети. Спорные случаи вынесены в отдельный список, а переобучение запускается одной кнопкой.
Третья модель разбирает хаотичные названия. Из строки вроде «Concierto de X en Madrid» или «A vs B — Stadium, 11/11» она достаёт исполнителя, город, площадку и дату. Учили её на 318 тысячах реальных названий событий, и больше 200 тысяч из них разметили автоматически, правилами, без ручного труда. По выделенному названию шоу события из разных городов и дат собираются в одну страницу «все даты и города».
SEO, заложенное в архитектуру
Основной канал трафика — поиск, поэтому требования SEO легли в техническое задание раньше первой строчки кода: какие у страниц адреса, как устроены заголовки, пагинация, фильтры, что закрыто от индексации. Дальше это стало частью платформы, а не ручной работой над каждой из 48 версий сайта.
- Адреса на языке страны
- Категории переведены не только в меню, но и в адресах: концерты на испанском сайте лежат по адресу /entradas/concierto, на русском — /bilety/kontsert, на китайском — /menpiao/yinyue-hui. Старые адреса переводятся на новые постоянным редиректом, вес страниц не теряется
- Связь 48 сайтов между собой
- У каждой страницы пары hreflang «язык — страна» на все 9 языков, у события одна каноническая страница. Google понимает, какую версию показать испанцу, а какую немцу, и не считает их дублями
- Шаблоны заголовков
- Title, description, H1 и SEO-текст собираются по шаблонам с подстановкой города, месяца, года, площадки и даты. Четыре уровня: главная, листинг, категория, событие. Уникальные заголовки у миллионов страниц без ручной работы
- Расширенные сниппеты
- Микроразметка Schema.org: событие с площадкой, адресом, датой и ценой в валюте посетителя, хлебные крошки, поиск по сайту прямо из выдачи
- AMP-версия
- Облегчённые страницы событий по стандарту Google AMP собираются автоматически из основных и мгновенно открываются из мобильной выдачи
- Скорость
- Страницы рендерятся на сервере, ответы API кешируются, картинки нарезаются в пяти размерах, в том числе в WebP, с умным кропом и понятными поисковику именами файлов и раздаются с CDN
Карты сайта на 5 миллионов адресов
Когда у сайта миллионы страниц, а события появляются и заканчиваются каждый день, Google сам их не найдёт. Ему нужна правильная карта сайта, и отдельная у каждой страны. Мы сделали для этого отдельный сервис. Каждую ночь он делает следующее:
- 1В 02:00 сервис по очереди обходит все 48 доменов
- 2Берёт новые события страны и обновлённые группы «все даты и города»
- 3Режет их на файлы по 3 300 событий: каждое событие даёт 9 адресов на разных языках с полным набором hreflang, файл остаётся ниже лимита Google в 50 000 адресов
- 4Дописывает новые файлы в индекс с датой изменения, старые не пересобирает
- 5Отдельно собирает карту страниц категорий на 9 языках и robots.txt домена со ссылкой на индекс
Сквозная аналитика и сводный отчёт по всем странам
Аналитика видела весь путь посетителя: какие карточки ему показали, что он открыл, на какой билет кликнул, дошёл ли до оформления. Но продажа происходит на сайте партнёра, и обычная аналитика её не видит. Мы замкнули цепочку: вместе с переходом партнёрская сеть получает метку визита, а когда билет продан, присылает статус продажи. Сервер передаёт её в Google Analytics с суммой и привязкой к исходному визиту, а при возврате билета так же отменяет покупку. В отчётах видно, какой источник трафика и какая страница приносят реальные продажи, а не только клики.
У 48 сайтов 48 отдельных ресурсов в Google Search Console, и смотреть их по одному невозможно. Отдельный механизм собирал данные со всех консолей и складывал их в единый отчёт в Google Data Studio: в одном окне видно, как весь проект растёт в поиске.
Каждое утро команде в Telegram приходила сводка: сколько событий на каждом из 48 сайтов, сколько из них активных, сколько новых за сутки. А мониторинг сам писал в тот же чат, если сайт отвечал ошибкой, API работал дольше пяти секунд или у домена истекал сертификат.
Кластер из восьми серверов
Сорок восемь сайтов, поиск по всему миру, импорт и нейросети не помещаются на один сервер. Проект работал на кластере из восьми машин с внутренней сетью. Сайт и API запущены в двух копиях на разных серверах, плюс горячий резерв: если один сервер падает, посетитель этого не замечает. База данных реплицирована, поисковый движок работает на двух узлах.
Вход в кластер, балансировщик, реестр образов, логи, метрики, сборки
Боевой сайт, AMP, личный кабинет, API — первая копия
Боевой сайт, AMP, личный кабинет, API — вторая копия
Тестовая среда и горячий резерв сайта и API
Основная база данных и поисковый движок
Копия базы, импорт, переводы, картинки, нейросети, ночные задачи
Второй узел поиска, кеш, генерация карт сайта
Арбитр базы данных и защищённый вход для администраторов
Новая версия выкатывается из GitLab автоматически, без простоя, а если обновление не поднялось, система сама возвращает предыдущую. Для проверок есть отдельные тестовая и предрелизная среды. Логи всех серверов и метрики нагрузки собираются в одном месте, копии базы регулярно уходят в отдельное облачное хранилище.
Задел на собственную билетную платформу
Следующим шагом агрегатор должен был стать ещё и площадкой, где организатор продаёт билеты сам. Мы спроектировали кабинет организатора: мастер создания события, площадки со схемой зала, расписание по городам и часовым поясам, типы билетов с сервисным сбором, список участников, продажи и выплаты. Для покупателя — своя корзина с бронью мест на пять минут и оплата картой. Часть этого успели собрать в коде.
Взлёт и ковид
Первые полгода ушли на платформу: импорт, 48 доменов, переводы, индексацию. В декабре 2019 года поисковый трафик начал расти, а в январе-феврале 2020 пошёл вверх почти вертикально. Пик пришёлся на середину февраля.

Что мы сделали
- Спроектировали интерфейс всего сайта: прототипы каждого экрана с пометками для разработчика, требования по SEO и схему адресов страниц до начала вёрстки
- Нарисовали дизайн по прототипам: 13 разделов, каждый экран в семи ширинах от 320 до 1800 пикселей, заглушки-обложки для событий без картинок
- Сделали AMP-версию страниц событий для мгновенного открытия из мобильной выдачи Google
- Запустили 48 сайтов стран на одном коде: домен задаёт страну, язык и валюту, посетитель переключает любое из трёх; 9 языков, 19 валют с ежедневными курсами, автоматический перевод описаний
- Сделали поиск по всему миру: несколько городов сразу с радиусом до 250 км, затем страна, затем мир; события на карте
- Спроектировали и запустили систему импорта: источник подключается настройкой в админке, без программиста; к осени 2020 года работало 59 источников
- Научили систему находить одно шоу у разных партнёров, склеивать дубли и показывать цены продавцов рядом; адреса площадок уточняет геокодинг
- Обучили нейросети раскладывать события по категориям меню и доставать из хаотичного названия исполнителя, город, площадку и дату
- Заложили SEO в архитектуру: адреса на языке страны, hreflang между 48 сайтами, шаблоны заголовков, микроразметка событий с ценой
- Сделали сервис карт сайта: каждую ночь для каждого домена, около 5 млн адресов с языковыми парами и под лимиты Google
- Настроили сквозную аналитику: продажа на сайте партнёра возвращается в Google Analytics с суммой и привязкой к визиту; данные всех Search Console собрали в единый отчёт в Data Studio
- Развернули кластер из восьми серверов: две копии сайта и API, горячий резерв, реплицированная база, автоматическая выкладка с откатом, мониторинг с уведомлениями в Telegram
- Спроектировали кабинет организатора и собственную кассу как следующий шаг: события, схемы залов, типы билетов, бронь мест и выплаты
Дизайн: главные экраны





Результат
Платформа заработала на 48 доменах, на 9 языках и в 19 валютах. События 59 источников каждую ночь проходили импорт, склейку, перевод и раскладку по категориям без ручной работы, а карты сайта на 5 миллионов адресов обновлялись сами. После полугода подготовки проект пошёл вверх в поиске: с января по февраль 2020 года переходы из Google выросли примерно в 4 раза, показы в 6 раз. В марте 2020 года по всему миру отменили концерты, спектакли и матчи, и трафик рухнул вслед за самими событиями: к июню переходов стало на 94 % меньше, чем в феврале. Проект остановила пандемия, а не продукт. Опыт этого проекта — импорт данных, многоязычное SEO на десятки стран, сквозная аналитика — мы применяем в проектах клиентов.















