Analytics

Аналитика в Mapbox GL JS строится вокруг событийной модели карты, состояния вьюпорта и взаимодействий пользователя с рендерингом WebGL-сцены. Библиотека не навязывает единый аналитический стек, но предоставляет набор низкоуровневых событий и API, на основе которых выстраиваются системы трекинга поведения, тепловые карты взаимодействий, продуктовые метрики и мониторинг производительности.

Карта в Mapbox GL JS генерирует поток событий, отражающих весь жизненный цикл рендера и пользовательских действий. Эти события являются базой для построения аналитических систем.

Ключевые категории событий:

  • события загрузки карты (load, style.load)
  • события рендеринга (render, idle, data)
  • пользовательские взаимодействия (click, mousemove, drag, zoom, rotate)
  • события источников данных (sourcedata, sourcedata)

Типовая регистрация событий:

map.on('load', () => {
  console.log('Карта загружена');
});

map.on('click', (e) => {
  console.log('Клик по карте', e.lngLat);
});

Каждое событие несёт контекст: координаты, пиксельные позиции, состояние камеры и список объектов под курсором.

Аналитика пользовательских взаимодействий

Основной слой аналитики строится вокруг пользовательских действий. Карта становится интерактивным интерфейсом, где каждое действие можно интерпретировать как событие продукта.

Клики и выбор объектов

map.on('click', (e) => {
  const features = map.queryRenderedFeatures(e.point);

  analytics.track('map_click', {
    coordinates: e.lngLat,
    featuresCount: features.length,
    featureTypes: features.map(f => f.layer.id)
  });
});

Функция queryRenderedFeatures позволяет извлечь объекты, которые визуально находятся под курсором. Это ключевой механизм связывания UI-событий с геоданными.

Наведение и микровзаимодействия

map.on('mousemove', (e) => {
  const features = map.queryRenderedFeatures(e.point);

  if (features.length) {
    analytics.track('map_hover_feature', {
      layer: features[0].layer.id
    });
  }
});

Из-за высокой частоты mousemove обычно применяется дебаунсинг или семплирование событий.

Аналитика состояния вьюпорта

В Mapbox GL JS камера описывает текущее состояние карты: центр, масштаб, поворот и наклон. Эти параметры используются для анализа поведения пользователя.

function getViewportState(map) {
  return {
    zoom: map.getZoom(),
    center: map.getCenter(),
    bearing: map.getBearing(),
    pitch: map.getPitch(),
    bounds: map.getBounds()
  };
}

Типовые сценарии аналитики вьюпорта:

  • глубина зума как индикатор интереса к деталям
  • частота панорамирования как показатель исследовательского поведения
  • возвращение к одному региону как сигнал высокой значимости области
  • наклон карты (pitch) как индикатор 3D-исследования данных

Отслеживание изменения камеры:

map.on('moveend', () => {
  analytics.track('viewport_change', getViewportState(map));
});

События рендеринга и производительности

Аналитика производительности карты строится вокруг событий render, idle и времени между интеракциями.

  • render — вызывается при каждом кадре WebGL
  • idle — карта завершила рендеринг и не имеет активных задач
  • load — завершение загрузки стиля

Пример измерения времени интерактивности:

const start = performance.now();

map.on('load', () => {
  const t = performance.now() - start;

  analytics.track('map_load_time', {
    duration: t
  });
});

Отдельный интерес представляет метрика time-to-idle:

map.on('idle', () => {
  analytics.track('map_idle_state', {
    timestamp: Date.now()
  });
});

Аналитика слоёв и данных

Слои в Mapbox GL JS являются основными единицами визуализации. Их можно использовать как аналитические сегменты.

map.on('click', (e) => {
  const features = map.queryRenderedFeatures(e.point);

  features.forEach(f => {
    analytics.track('layer_interaction', {
      layerId: f.layer.id,
      source: f.source,
      geometryType: f.geometry.type
    });
  });
});

Типовые метрики:

  • частота взаимодействий с конкретным слоем
  • распределение кликов по типам геометрии
  • популярность источников данных
  • вклад слоя в пользовательский путь

Feature-state как инструмент поведенческой аналитики

Feature State позволяет хранить состояние объектов на стороне клиента, что даёт возможность строить интерактивные метрики.

map.setFeatureState(
  { source: 'places', id: 123 },
  { selected: true }
);

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

  • подсветка часто выбираемых объектов
  • отслеживание «избранных» географических точек
  • динамическая агрегация поведения

Аналитика может извлекать частоту изменений состояния:

analytics.track('feature_state_change', {
  featureId: 123,
  state: 'selected'
});

Геоаналитика через bounding box и кластеризацию

В Mapbox GL JS можно анализировать не только действия, но и пространственное распределение интереса.

const bounds = map.getBounds();

analytics.track('region_view', {
  northEast: bounds.getNorthEast(),
  southWest: bounds.getSouthWest(),
  zoom: map.getZoom()
});

Применения:

  • определение популярных регионов просмотра
  • анализ плотности кликов по территории
  • построение heatmap активности пользователей

Интеграция с внешними системами аналитики

Mapbox GL JS легко интегрируется с системами продуктовой аналитики.

Google Analytics / GA4

map.on('click', (e) => {
  gtag('event', 'map_click', {
    event_category: 'map',
    event_label: `${e.lngLat.lng},${e.lngLat.lat}`
  });
});

Segment

map.on('moveend', () => {
  analytics.track('map_move', {
    zoom: map.getZoom()
  });
});

Собственные event pipelines

Часто используется промежуточный слой:

function track(eventName, payload) {
  fetch('/analytics', {
    method: 'POST',
    body: JSON.stringify({
      event: eventName,
      payload,
      timestamp: Date.now()
    })
  });
}

Семплирование и контроль объёма данных

Из-за высокой частоты событий (особенно mousemove и render) применяются стратегии снижения нагрузки:

  • throttling событий камеры
  • батчинг событий перед отправкой
  • агрегирование кликов по тайм-окнам

Пример:

let buffer = [];

map.on('mousemove', (e) => {
  buffer.push(e.lngLat);

  if (buffer.length > 20) {
    analytics.track('mouse_path', { path: buffer });
    buffer = [];
  }
});

Телеметрия Mapbox GL JS

Библиотека включает встроенную телеметрию использования, которая может быть отключена:

mapboxgl.setTelemetryEnabled(false);

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

Аналитика взаимодействий с источниками данных

Источники (sources) позволяют отслеживать загрузку и использование данных:

map.on('sourcedata', (e) => {
  if (e.isSourceLoaded) {
    analytics.track('source_loaded', {
      sourceId: e.sourceId
    });
  }
});

Метрики:

  • время загрузки источника
  • частота обновлений данных
  • количество запросов к тайлам

Поведенческие паттерны навигации по карте

Комбинация событий move, zoom, rotate позволяет восстанавливать пользовательские сценарии:

  • линейное приближение к объекту (zoom-in funnel)
  • циклическое перемещение по региону
  • резкие прыжки между координатами как индикатор поиска

Пример фиксации навигационного шага:

map.on('moveend', () => {
  analytics.track('navigation_step', {
    zoom: map.getZoom(),
    center: map.getCenter()
  });
});

QueryRenderedFeatures как источник аналитического контекста

Этот метод является центральным для связывания визуального слоя и данных:

const features = map.queryRenderedFeatures(point, {
  layers: ['cities', 'roads']
});

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

  • определение наиболее «кликабельных» объектов
  • анализ популярности слоёв
  • построение модели интереса к типам объектов

Построение аналитики на основе временных окон

События карты часто агрегируются по временным интервалам:

  • 1 секунда — интерактивные действия
  • 10 секунд — навигационные паттерны
  • 1 минута — сессии исследования карты

Пример агрегации:

setInterval(() => {
  analytics.track('viewport_snapshot', getViewportState(map));
}, 10000);

Геометрическая аналитика взаимодействий

Координаты событий позволяют строить пространственные распределения:

  • heatmap кликов
  • density map движения курсора
  • кластеризация интересных зон
map.on('click', (e) => {
  geoAnalytics.addPoint(e.lngLat);
});

Такие данные часто используются для оптимизации UI: перераспределения подписей, улучшения кластеров и настройки визуальной плотности объектов.