Лучший способ ответить на вопросы о поведении пользователей - часто собирать данные. Распространенным шаблоном является отслеживание кликов пользователей по продукту с последующим выполнением аналитических запросов по полученным данным для получения целостного представления о поведении пользователей.

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

  • собирает данные JSON в свободной форме
  • запрашивает живые данные с помощью SQL
  • не имеет внутренних серверов

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

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

Сохраняя дух простоты, мы будем использовать ванильный HTML / CSS / JS с небольшим количеством jQuery для создания внешнего интерфейса приложения. Начнем с макета HTML-структуры страницы.

Обратите внимание, что мы оставили элемент #body пустым - мы добавим сюда вопросы, используя Javascript:

Добавляя вопросы с помощью Javascript, нам нужно только один раз написать HTML и обработчики событий. Мы даже можем изменить список вопросов в любое время, просто отредактировав глобальную переменную QUESTIONS.

Сбор пользовательских данных JSON

Теперь у нас есть веб-страница, на которой мы хотим отслеживать клики пользователей - классический случай продуктовой аналитики. Фактически, если бы мы инструментировали существующее веб-приложение, а не создавали его с нуля, мы бы просто начали с этого шага.

Сначала мы выясним, как моделировать данные, которые мы хотим собирать, в виде объектов JSON, а затем мы сможем сохранить их в серверной части данных. Для нашего уровня данных мы будем использовать Rockset, службу, которая принимает данные JSON и обслуживает запросы SQL через REST API.

Модель данных

Поскольку в нашем опросе есть вопросы только с двумя вариантами ответа, мы можем смоделировать каждый ответ как логическое «ложь» для выбора слева и истина для выбора справа. Посетитель может ответить на любое количество вопросов, поэтому посетитель, который предпочитает пробелы и использует vim, должен создать запись, которая выглядит так:

С помощью этой модели мы можем реализовать обработчики кликов сверху, чтобы создать и отправить этот пользовательский объект JSON в Rockset:

На практике ROCKSET_APIKEY следует установить равным значению, полученному при входе в консоль Rockset. Коллекцию Rockset, в которой будут храниться документы (в данном случае demo.binary_survey), также можно создавать и управлять ими в консоли.

Обновление существующих ответов

У нашего кода пока есть недостаток: подумайте, что происходит, когда посетитель нажимает «пробелы», а затем «vim». Сначала мы отправим документ с ответом на первый вопрос. Затем мы отправим еще один документ с ответами на два вопроса. Они сохраняются как два отдельных документа! Вместо этого мы хотим, чтобы второй документ был обновлением первого.

С Rockset мы можем решить эту проблему, придав нашим документам согласованность, которая в Rockset рассматривается как первичный ключ документа. Мы сгенерируем это поле как случайный идентификатор посетителя при загрузке страницы:

Теперь давайте снова рассмотрим предыдущий сценарий. Когда веб-страница загружается, объект «голосование» получает идентификатор:

Когда посетитель выбирает один из вопросов, добавляется логическое поле:

Посетитель может продолжать добавлять ответы:

Или даже обновите предыдущие ответы:

Каждый раз, когда ответ изменяется, JSON сохраняется как документ Rockset, и, поскольку поле _id совпадает, любой предыдущий ответ для текущего посетителя перезаписывается.

Сохранение состояния между сеансами

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

Давайте изменим наш код Javascript, чтобы реализовать этот механизм:

Приложение на основе данных: агрегирование на лету

На данный момент мы создали статическую страницу и оснастили ее инструментами для сбора пользовательских данных о кликах. Теперь давайте воспользуемся этим! Обычно это принимает одну из двух форм:

  • внутренняя панель инструментов, информирующая о решениях по продукту или запускающая предупреждения о необычном поведении
  • функция, ориентированная на пользователя, для улучшения продукта, управляемого данными

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

Чтобы реализовать это, мы напишем код Javascript для вызова API запросов Rockset. Мы хотим отправить SQL-запрос, который выглядит так:

Ответом будет объект JSON с подсчетом для каждого вопроса (количество «истинных» ответов и общее количество ответов), а также количество уникальных посетителей.

Мы можем проанализировать эти данные и установить атрибуты для элементов HTML, чтобы передать результаты посетителю. Запишем это на Javascript:

Даже с десятками тысяч точек данных этот вызов AJAX возвращается примерно через 20 мс, поэтому нет необходимости выполнять запрос в реальном времени. Фактически, мы можем обновлять результаты, скажем, каждую секунду, чтобы числа выглядели живыми:

Последние штрихи

Контроль доступа

Мы написали всю логику для отправки и получения данных из Rockset на стороне клиента нашего приложения. Однако при этом наш полностью привилегированный ключ API Rockset становится общедоступным, что, конечно же, является большим запретом. Это дало бы любому полный доступ к нашей учетной записи Rockset, а также, возможно, допустило бы DoS-атаку. Мы можем добиться разрешений с ограниченной областью действия и регулирования запросов одним из двух способов:

  • использовать ограниченный ключ API Rockset
  • использовать лямбда-функцию в качестве прокси

Первое - это функция, которая все еще находится в разработке в Rockset, поэтому для этого приложения нам придется использовать второе.

Давайте переместим список вопросов и логику, которая взаимодействует с Rockset, в простой обработчик на Python, который мы развернем как лямбда на AWS:

Наш клиентский Javascript теперь может просто выполнять вызовы конечных точек лямбда, которые будут действовать как ретранслятор с Rockset API.

Добавление дополнительных вопросов

Преимущество способа создания приложения в том, что мы можем произвольно добавлять вопросы, а все остальное будет работать!

Точно так же, если посетитель отвечает только на часть вопросов, проблем нет - клиентское приложение и Rockset могут корректно обрабатывать отсутствующие значения.

Фактически, эти обстоятельства обычно характерны для продуктовой аналитики, когда вы можете захотеть начать отслеживание дополнительного атрибута в существующем событии или если у пользователя отсутствуют определенные атрибуты. Поскольку мы создали это приложение с использованием бессхемного подхода, у нас есть гибкость, чтобы справиться с такими ситуациями.

Обработка и стиль

Мы еще не полностью рассмотрели логику рендеринга и стилизации элементов в DOM. Если вам интересно, вы можете увидеть полный исходный код здесь, но вот краткое изложение того, что осталось сделать:

  • добавить JS для отображения / скрытия результатов и подсказок по мере прохождения посетителем опроса
  • добавить CSS, чтобы приложение выглядело красиво, и адаптировать макет для мобильных посетителей
  • добавить поздравительное сообщение после завершения опроса

И вуаля, вот оно что! На установку этого приложения потребовалось всего несколько часов. Он не требовал раскрутки серверов или предварительной настройки баз данных, и его было легко адаптировать во время разработки, поскольку он просто записывал JSON в свободной форме. На данный момент ответы прислали более 2500 разработчиков, и на результаты как минимум интересно посмотреть.

Опрос в настоящее время здесь - не стесняйтесь проверять его и копаться! Результаты на момент написания этого блога находятся здесь. А исходный код доступен здесь.

Первоначально опубликовано на https://rockset.com 17 мая 2019 г.