JS-трекер
- JS-трекер
- Логика работы трекера
- Создание скрипта и получение сниппета
- Подключение трекера
- Настройка трекера
- Пакетная отправка событий
- Переопределение метода отправки данных
- Кастомная очистка буфера
- Прогрессивная шкала отправки запросов при ошибках запросов
- Обработка полученных данных
- Сбор кастомных событий
- Настройка cors_policy для междоменного обмена данным
- Несовместимость типов при получении Null в активности
JS-трекер собирает статистику о действиях посетителей на сайте. Он позволяет отслеживать события, такие как клики, просмотры страниц, заполнение форм и другие взаимодействия с веб-страницей. Эта информация полезна для аналитики, выявления пользовательских сценариев и оптимизации работы сайта.
Полученные трекером данные автоматически передаются в систему Proceset, где объединяются с данными из других систем.
Логика работы трекера
Отслеживание пользовательского пути на сайте обеспечивают четыре компонента:
- Сниппет — небольшой фрагмент кода, в котором содержатся настройки подключения трекера
- Трекер — js-скрипт, который собирает данные и передает их на сервер
- Модуль трекинга на платформе Proceset — часть системы, которая принимает данные от трекера
- Модуль автоматизации — часть системы, в которой настраивается блок-триггер Новые события для получения событий от трекера и скрипт для обработки полученных данных
Схема работы трекера:
- В код сайта встраивается сниппет.
- При открытии сайта сниппет начинает загружать скрипт трекера. В случае ошибки загрузки сниппет делает повторные попытки через заданный интервал времени.
- Трекер собирает информацию о событиях в буфер и передает ее на сервер либо через определенные интервалы времени, либо при достижении заданного объема. Если события происходят до загрузки трекера, сниппет перехватывает их и временно сохраняет, чтобы позже передать в трекер. В случае ошибки при отправке данных трекер повторяет попытки отправки либо с каждым новым событием, либо через установленные интервалы.
- Сервер аккумулирует полученные запросы и далее запускает скрипт автоматизации для обработки данных.
Подробное описание параметров настройки трекера представлено в разделе Настройка трекера.
Создание скрипта и получение сниппета
Для сбора данных и их дальнейшей обработки необходимо создать скрипт.
В качестве триггера для запуска скрипта установите блок Новые события.
В левой панели веб-интерфейса Proceset представлены следующие параметры блока:
- Имя веб-приложения — по умолчанию в качестве имени используется текущий домен
- UUID — идентификатор данных трекера, используется в качестве публичного ID данных
- Адрес сервера сбора аналитики — по умолчанию используется текущий домен, сервер используется для передачи событий
- Встраиваемый код (сниппет)
Если при настройке блока добавить имя веб-приложения, оно также отобразится во встраиваемом коде. Встраиваемый код можно просмотреть и скопировать, но он недоступен для редактирования.
- В системе не может быть двух одинаковых UUID: они уникальны для каждого трекера.
- Для корректной работы скрипта имя веб-приложения и UUID должны совпадать в блоке и на сайте.
Блок Новые события запускает скрипт при получении новых событий с сервера и возвращает следующие поля:
Поле | Тип | Описание |
---|---|---|
event | Информация о событии | |
event.name | string | Имя события |
event.props | array (string) | Словарь с пользовательскими данными |
event.time | number | Временная метка вызова метода (количество миллисекунд, прошедших с 1 января 1970 года 00:00:00 по UTC) |
event.element | Информация о DOM-элементе, на котором сработало событие: кнопка, ссылка, поле и другие | |
event.element.id | string null | Идентификатор элемента (берется только атрибут id ) |
event.element.name | string null | Имя/данные элемента. Вычисляется индивидуально для каждого типа элемента |
event.element.webctrl_selector | string null | Способ идентификации элемента на странице https://docs.uipath.com/studio/docs/about-selectors#webctrl |
person | Информация о пользователе | |
person.user_id | string null | Идентификатор зарегистрированного пользователя |
person.anonymous_id | string | Сгенерированный анонимный UUID v4 идентификатор |
person.ids | array (string) | Словарь идентификаторов, полученных из сторонних трекеров, подключенных к странице |
app | Информация о сайте, подключающем трекер | |
app.name | string | Имя приложения. Указывается в конфигурационном файле, по умолчанию используется текущий домен |
lib | Информация о трекере | |
lib.version | string | Номер версии трекера |
campaign | UTM-метки, полученные из URL | |
campaign.source | string null | Источник перехода, рекламная площадка |
campaign.medium | string null | Тип рекламы |
campaign.name | string null | Название рекламной кампании |
campaign.term | string null | Ключевая фраза |
campaign.content | string null | Дополнительная информация по объявлению |
page | Информация о web-странице | |
page.title | string | Заголовок вкладки браузера |
page.referrer | string | URL, с которого произошел переход на текущую страницу |
page.url | string | URL текущей страницы |
page.path | string | Часть URL между хостом и параметрами |
screen | Информация об экране | |
screen.width | number | Ширина экрана в пикселях |
screen.height | number | Высота экрана в пикселях |
navigator | Состояние и особенности (свойства) пользовательского агента | |
navigator.user_agent | string | Строка агента пользователя для данного браузера |
navigator.language | string | Предпочитаемый пользователем язык, как правило, это язык пользовательского интерфейса браузера |
time_zone | string | Временная зона |
Общая информация по запросам на стороне сайта, такая как время загрузки страницы, длительность работы отдельных элементов на странице, не сохраняется.
Трекер также не собирает данные по местоположению пользователя.
Чтобы исключить сбор некоторых событий трекером, добавьте в сниппет предикат filterFn
. Подробную информацию о предикате можно найти в разделе Настройка трекера.
Дальнейшая настройка скрипта описана в разделе Обработка полученных данных.
Подключение трекера
Для подключения трекера к странице сайта скопируйте код сниппета в параметрах блока-триггера Новые события и вставьте его в код страницы.
При открытии сайта сниппет начинает загружать скрипт трекера согласно заданным параметрам сниппета.
Настройка трекера
Настройка параметров трекера производится внутри сниппета.
Запуск трекера можно сконфигурировать следующими параметрами:
app
— имя web-приложения. По умолчанию в качестве имени используется текущий доменserverUrl
— адрес сервера сбора аналитикиuuid
— идентификатор данных трекера. Используется в качестве публичного ID данных. UUID используется для сопоставления конфигурации трекера и ID скрипта, в котором будут обрабатываться данныеsend
— метод отправки данных трекера. Позволяет настроить кастомизацию метода отправки данных, например, зафиксировать формат передачи данных или изменить заголовки запросаbufferLifetime
— интервал времени в миллисекундах между отправками накопленных событий. По истечении указанного времени накопленные данные автоматически отправляются на сервер. Значение по умолчанию —Infinity
.bufferLimit
— максимальное количество событий, которое может храниться в буфере. Когда количество событий достигает этого лимита, накопленные данные отправляются на сервер. Значение по умолчанию —1
bufferMaxSize
— максимальный размер памяти в байтах, по достижению которого буфер будет очищен. По умолчанию — 1 МбerrorSendTimeout
— определяет интервал между повторными попытками отправки событий на сервер, если предыдущая попытка завершилась с ошибкой. По умолчанию — 15000 мс (15 секунд)filterFn
— предикат, позволяющий исключить из сбора ненужные события. Отфильтрованные с его помощью события не будут сохраняться в буфере на отправкуinterceptors
— пользовательские конфигурации для автоматического сбора собственных событий
Подробная информация о параметрах bufferLifetime
, bufferLimit
и bufferMaxSize
представлена в разделе Пакетная отправка событий.
Подробное описание параметра interceptors
представлено в разделе Сбор кастомных событий.
Пример настройки параметра filterFn
для исключения событий из сбора:
filterFn: (data) => {
if (data.event.name === 'Page') {
return false;
}
return true;
}
Где:
data
— событие, которое необходимо отфильтроватьdata.event.name === 'Page'
— условие, по которому происходит фильтрация
При успешном подключении трекера в консоли разработчика (F12) можно увидеть сообщение о дате сборки трекера.
Пример сниппета:
(function(w,d,s,t,u,i,q,e){
q=[];w[t]=function(){q.push([arguments,new Date()]);};w[t].q=q;
(function l(){e=d.createElement(s);e.async=1;e.src=u;
e.onerror=function(){e.parentNode.removeChild(e);setTimeout(l,i);};
b=d.getElementsByTagName(s)[0];b.parentNode.insertBefore(e,b);})();
w[t]({
app: "My site",
serverUrl: "https://example.ru",
uuid: "qwertyuiopasdfghjklzxcvbnm123456"
});
})(window,document,"script","tracker","tracker.js",15000);
Пакетная отправка событий
Трекер собирает события и сохраняет их в буфере до тех пор, пока не выполнится одно из условий для отправки данных на сервер.
Логика отправки событий определяется следующими параметрами, которые настраиваются в сниппете:
bufferLifetime
— интервал времени в миллисекундах между отправками накопленных событий. По истечении указанного времени накопленные данные автоматически отправляются на сервер. Значение по умолчанию —Infinity
bufferLimit
— максимальное количество событий, которое может храниться в буфере. Когда количество событий достигает этого лимита, накопленные данные отправляются на сервер. Значение по умолчанию —1
bufferMaxSize
— максимальный размер буфера в байтах. По достижении указанного значения буфер будет автоматически очищен. По умолчанию — 1 Мб
Принцип работы:
- Данные отправляются, когда выполняется одно из следующих условий:
- Достигается лимит накопленных событий, заданный параметром
bufferLimit
. - Истекает время, определенное параметром
bufferLifetime
, после последней успешной отправки данных.
- Достигается лимит накопленных событий, заданный параметром
- Отправка данных происходит в тот момент, когда наступит одно из этих условий, в зависимости от того, какое из них произойдет раньше.
- После успешной отправки данных отправленные события удаляются из буфера и таймер перезапускается.
- Если буфер достигает максимального размера, заданного параметром
bufferMaxSize
, он очищается. Все накопленные в нем данные будут утрачены
Переопределение метода отправки данных
Для реализации пользовательской логики отправки данных в трекере предусмотрена возможность переопределить метод отправки с помощью параметра send
. Метод, передаваемый в качестве значения этого параметра, принимает в себя два аргумента:
- Первый — массив событий
- Второй — UUID, переданный в конфигурацию трекера
Метод, передаваемый через параметр send
, можно использовать для реализации нестандартной логики преобразования данных трекера или очистки буфера.
Пример:
(function(w,d,s,t,u,i,q,e){
q=[];w[t]=function(){q.push([arguments,new Date()]);};w[t].q=q;
(function l(){e=d.createElement(s);e.async=1;e.src=u;
e.onerror=function(){e.parentNode.removeChild(e);setTimeout(l,i);};
b=d.getElementsByTagName(s)[0];b.parentNode.insertBefore(e,b);})();
w[t]({
app: "My site",
uuid: "qwertyuiopasdfghjklzxcvbnm123456",
send(data, uuid) {
return fetch(`https://example.ru/webhook/${uuid}`, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
}
});
})(window,document,"script","tracker","tracker.js",15000);
Кастомная очистка буфера
Автоматическую очистку данных буфера после их успешной отправки на сервер можно реализовать с помощью переопределения метода отправки данных трекера через параметр send
.
Для очистки буфера:
- Реализуйте возврат объекта
Promise
из метода отправки данных через параметрsend
. - В колбэке
Promise
вызовите методresolve
с параметром{ ok: true }
.
Пример:
w[t]({
app: "My site",
serverURL: "https://address.ru"
uuid: "script",
send(items, url) {
if (JSON.parse(localStorage.getItem("im_buf")).length > 3) {
return Promise.resolve({ok: true})
}
return fetch(url, {
method: "POST",
mode: "cors",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(items),
});
}
});
Прогрессивная шкала отправки запросов при ошибках запросов
Прогрессивный таймаут отправки ошибочных запросов можно реализовать с помощью переопределения метода send
.
Пример:
w[t]({
app: "My site",
serverUrl: "https://address.ru",
uuid: "script",
send: (items, url) => {
function fetchWithRetry(url, options = {}, delays) {
let attempt = 0;
function makeRequest() {
return fetch(url, options)
.then(response => {
if (!response.ok) {
throw new Error(response.status);
}
return response;
})
.catch(error => {
if (attempt < delays.length) {
return new Promise(resolve =>
setTimeout(resolve, delays[attempt])
).then(() => {
attempt++;
return makeRequest();
});
} else {
throw error;
}
});
}
return makeRequest();
}
return fetchWithRetry(url, {
method: "POST",
mode: "cors",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(items)
}, [1000, 2000, 3000, 4000, 5000, 7000]);
}
});
Обработка полученных данных
Для обработки событий, полученных с помощью трекера Новые события добавьте в скрипт другие блоки автоматизации. Например, вы можете настроить автоматическую загрузку собранных данных в таблицу, чтобы затем использовать их для анализа.
Подробное описание блоков для работы с полученными данными представлено в разделе Редактирование скрипта.
Сбор кастомных событий
Трекер имеет 2 метода — trackEvent
и identify
. Оба доступны разработчикам приложения через глобальный объект window.tracker
или экземпляр tracker
.
Чтобы отследить произвольное событие, необходимо добавить ручной вызов метода trackEvent
трекера при возникновении нужного события. Метод позволяет передать на сервер событие с произвольным именем event.name
и необязательным объектом со свойствами типа ключ-значение
. Вызов метода осуществляется в момент совершения события, например, в обработчике onClick элемента.
Пример использования при подключении через сниппет:
tracker("trackEvent", "product catalog is opened");
tracker("trackEvent", "purchase", { product: "test item", price: "1$" });
Если в необязательный объект со свойствами типа ключ-значение (event.props
в структуре события) передать ключ element
со значением типа Element
и/или ключ elementName
со значением типа String
, то эти ключи удалятся из передаваемых данных, сформировав elementData
. Остальные поля остаются в передаваемых данных.
Пример использования при подключении через сниппет:
tracker("trackEvent", "some event", {
element: document.getElementById("container"),
elementName: "name",
otherProp: "value",
});
Для идентификации пользователя у трекера есть событие identify
. identify
позволяет связать с анонимным пользователем произвольный числовой или строковый идентификатор — логин, email, ID в системе и другие. Предполагается, что он будет предоставлен приложением при авторизации пользователя.
Необходимо делать вызов события в момент уточнения идентификатора.
При попытке вызова identify
с идентификатором, который уже сохранен в браузере, событие на сервер отправлено не будет.
Пример использования при подключении через сниппет:
tracker("identify", 1, { name: "Dmitry" });
Данный вызов добавляет в контекст пользователя идентификатор «1», который записывается в localStorage
и будет отправляться на сервер аналитики с каждым последующим запросом.
Далее происходит автоматическое делегирование вызова методу trackEvent
с именем события identify
с отправкой события на сервер. Для примера выше вызов будет следующим:
tracker("trackEvent", "identify", { name: "Dmitry" });
В контекст будет сохранен только идентификатор пользователя, но не объект. Например, такой как { name: "Dmitry" }
.
Кастомные события автоматически собираются с помощью параметра interceptor. В качестве значения параметра передается массив объектов.
Чтобы JS-трекер собирал кастомные события, дополните встраиваемый код пользовательской конфигурации interceptors
:
interceptors: [
{
action: "Click" | "FieldChange",
interceptor: (target: EventTarget) => {
eventName: string,
elementName: string,
element: Element,
eventProps: object
} | null
}
]
Где:
action
— тип события, по которому будет вызванinterceptor
. Возможные значения:Click
— подписка на событиеclick
FieldChange
— подписка на событиеfocusin
,focusout
interceptor
— обработчик события. Принимает элемент, по которому произошло событие, и возвращает структуру, описывающую кастомное событие. В качестве возвращаемого значения в коде обработчика можно указатьnull
, а в реализации — элементы, с которыми стоит фиксировать действия. Фиксируются только кастомные события с прописанными в сниппете элементами. Если кастомное событие будет связано с другими элементами, будет возвращатьсяnull
.
В зависимости от того, какие данные необходимо получать, у параметра могут быть указаны следующие поля:
eventName
elementName
element
eventProps
Сбор информации осуществляется по указанным полям.
Настройка cors_policy для междоменного обмена данным
В случаях, когда JS-трекер находится в домене отличном от того, на котором располагается Proceset, необходимо настроить политику cors, предоставляющую доступ к этому домену. Для этого необходимо в конце конфигурационного файла Proceset com.infomaximum.subsystem.frontend.json добавить перед последней фигурной скобкой:
"cors_policy": "*"
Файл расположен на сервере Proceset в каталоге: C:\ProgramData\Infomaximum\config\com.infomaximum.subsystem.frontend.json.
Если система установлена на OC Linux, при запуске службы в переменной FE_CORS_POLICY
укажите *
. По умолчанию cors-политика выключена.
Несовместимость типов при получении Null в активности
При возникновении несовместимости типов при получении Null в активности, собираемой JS-трекером, необходимо привести колонки целевой таблицы в скрипте к типу Nullable. Если таблица была создана ранее, то можно воспользоваться следующим способом устранения данной проблемы:
- Добавьте блок SQL-запрос в целевой скрипт.
- Введите SQL-запрос
ALTER TABLE NAME_TABLE(название таблицы) MODIFY COLUMN person_user_id Nullable(String)
. - Измените тип целевой колонки.
- Удалите блок SQL-запрос, созданный в п.1 и п.2.
- Используйте обновленную таблицу с типом колонок Nullable и ранее созданным скриптом.
Способ подходит для решения любой подобной ситуации, связанной с несовместимостью типов.
Была ли статья полезна?