User analytics

Stencil — это прогрессивный фреймворк для создания веб-компонентов с использованием современных стандартов Web Components и TypeScript. Одной из важных задач при разработке сложных интерфейсов является сбор и обработка данных о действиях пользователей для последующей аналитики. Рассмотрим, как реализовать систему пользовательской аналитики внутри компонентов Stencil.


Организация сбора данных

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

  • клики по кнопкам и ссылкам;
  • взаимодействие с формами (заполнение, отправка);
  • прокрутка страницы и навигация между разделами;
  • время, проведённое на отдельных элементах.

В Stencil это удобно делать с использованием декораторов и слушателей событий.

import { Component, h, Listen } from '@stencil/core';

@Component({
  tag: 'user-tracker',
  styleUrl: 'user-tracker.css',
  shadow: true,
})
export class UserTracker {

  @Listen('click', { capture: true })
  handleClick(event: MouseEvent) {
    const target = event.target as HTMLElement;
    console.log('Click on:', target.tagName, target.id || target.className);
    this.sendAnalytics({ type: 'click', element: target.tagName });
  }

  sendAnalytics(data: Record<string, any>) {
    fetch('https://analytics.example.com/track', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    });
  }

  render() {
    return <slot />;
  }
}

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


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

Stencil-компоненты могут отправлять данные на сторонние аналитические платформы, такие как Google Analytics, Mixpanel или Amplitude. Для этого достаточно обернуть вызовы API в отдельный сервис:

export class AnalyticsService {
  static trackEvent(eventName: string, payload: Record<string, any>) {
    // Пример для Google Analytics 4
    if ((window as any).gtag) {
      (window as any).gtag('event', eventName, payload);
    }
  }
}

В компоненте можно подключать сервис:

import { AnalyticsService } from './analytics-service';

handleClick(event: MouseEvent) {
  const target = event.target as HTMLElement;
  AnalyticsService.trackEvent('click', { element: target.tagName });
}

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


Отслеживание состояний компонентов

Для анализа пользовательского поведения важно фиксировать не только события DOM, но и изменения состояния компонентов. В Stencil для этого удобно использовать декоратор @Watch:

import { Component, h, State, Watch } from '@stencil/core';

@Component({
  tag: 'toggle-switch',
  styleUrl: 'toggle-switch.css',
  shadow: true,
})
export class ToggleSwitch {
  @State() isOn: boolean = false;

  @Watch('isOn')
  onToggleChange(newValue: boolean, oldValue: boolean) {
    console.log(`Toggle changed from ${oldValue} to ${newValue}`);
    AnalyticsService.trackEvent('toggle_change', { newValue, oldValue });
  }

  toggle() {
    this.isOn = !this.isOn;
  }

  render() {
    return <button onCl ick={() => this.toggle()}>{this.isOn ? 'ON' : 'OFF'}</button>;
  }
}

Использование @Watch позволяет отслеживать любые изменения состояния, что критично для компонентов с интерактивным поведением.


Производительность и оптимизация аналитики

При внедрении аналитики важно учитывать производительность:

  1. Дебаунс и троттлинг событий. Например, события прокрутки страницы следует отправлять с интервалом, чтобы не перегружать сервер:
let scrollTimeout: number;
window.addEventListener('scroll', () => {
  clearTimeout(scrollTimeout);
  scrollTimeout = window.setTimeout(() => {
    AnalyticsService.trackEvent('scroll', { position: window.scrollY });
  }, 200);
});
  1. Пакетная отправка данных. Для высокой нагрузки можно собирать события в массив и отправлять пакетами раз в N секунд.

  2. Асинхронная отправка. Использование navigator.sendBeacon или асинхронных fetch-запросов предотвращает блокировку основного потока рендеринга.


Настройка пользовательских идентификаторов

Для точной аналитики требуется идентификация пользователей. В Stencil это реализуется через локальное хранение идентификатора:

function getUserId(): string {
  let userId = localStorage.getItem('userId');
  if (!userId) {
    userId = crypto.randomUUID();
    localStorage.setItem('userId', userId);
  }
  return userId;
}

Все события можно привязывать к этому идентификатору:

AnalyticsService.trackEvent('click', { userId: getUserId(), element: 'button' });

Интеграция с Shadow DOM

Stencil часто использует Shadow DOM, что усложняет глобальный поиск элементов. Для аналитики:

  • События можно слушать на host-компоненте, а не на document.
  • Для делегирования событий внутри Shadow DOM используется composedPath(), чтобы получить путь события через shadow root:
@Listen('click', { capture: true })
handleShadowClick(event: MouseEvent) {
  const path = event.composedPath() as HTMLElement[];
  const target = path.find(el => el.tagName === 'BUTTON');
  if (target) {
    AnalyticsService.trackEvent('shadow_click', { element: target.tagName });
  }
}

Визуализация и анализ данных

Данные, собранные через Stencil-компоненты, можно использовать для:

  • построения графиков посещаемости и конверсий;
  • анализа поведения пользователей на отдельных компонентах;
  • A/B тестирования интерфейсов.

Для визуализации удобно экспортировать события в JSON и подключать библиотеки вроде Chart.js, D3.js или Recharts.


Практические рекомендации

  • Выделение аналитики в отдельные сервисы повышает модульность компонентов.
  • Строгое соблюдение типов с TypeScript помогает избежать ошибок при сборе и отправке данных.
  • Тестирование событий с использованием Jest и Stencil Testing Library гарантирует корректность работы аналитики.
  • Обработка ошибок сети должна быть встроена, чтобы потеря одного события не прерывала работу компонентов.

Этот подход обеспечивает полную и гибкую систему user analytics на основе Stencil, позволяя отслеживать клики, состояния, события Shadow DOM, а также интегрироваться с внешними сервисами и визуализировать данные.