Skip to content

Commit c1a2297

Browse files
committed
Добавлены функции отслеживания событий для аналитики в избранных пресетах, включая добавление и удаление из избранного. Создана документация по событиям аналитики для Google Analytics и Яндекс.Метрики. Оптимизирован код для определения окружения приложения.
1 parent cef3102 commit c1a2297

File tree

6 files changed

+262
-9
lines changed

6 files changed

+262
-9
lines changed

app/favorites/page.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ export default function FavoritesPage(): ReactElement {
1616
favorites.includes(preset.id),
1717
);
1818

19-
// Отслеживаем просмотр страницы избранного
20-
useEffect(() => {
21-
if (isLoaded) {
22-
trackViewFavorites(favoritePresets.length);
23-
}
24-
}, [isLoaded, favoritePresets.length]);
25-
2619
return (
2720
<div className="min-h-screen flex flex-col bg-gray-900 text-white">
2821
<Header />

app/layout.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import "../styles/globals.css";
22
import { Metadata } from "next";
33
import YandexMetrika from "../components/YandexMetrika";
44
import { GoogleTagManager } from "../components/GoogleTagManager";
5+
import { isProduction } from "../lib/env";
56

67
export const metadata: Metadata = {
78
title: "NXRIG",
@@ -15,8 +16,6 @@ export default function RootLayout({
1516
}: {
1617
children: React.ReactNode;
1718
}) {
18-
const isProduction = process.env.NODE_ENV === "production";
19-
2019
return (
2120
<html lang="en">
2221
<head>

components/FavoriteButton.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import { useFavorites } from "hooks/useFavorites";
44
import { ReactElement } from "react";
5+
import { trackAddToFavorites, trackRemoveFromFavorites } from "lib/analytics";
6+
import { presets } from "lib/public/presets";
57

68
interface FavoriteButtonProps {
79
presetId: string;
@@ -18,6 +20,12 @@ export function FavoriteButton({
1820

1921
const isInFavorites = isFavorite(presetId);
2022

23+
// Получаем информацию о пресете для аналитики
24+
const preset = presets.find((p) => p.id === presetId);
25+
const presetName = preset
26+
? `${preset.origin.artist.title} - ${preset.origin.song} ${preset.origin.part}`
27+
: presetId;
28+
2129
// Не показываем кнопку пока не загрузились данные из localStorage
2230
if (!isLoaded) {
2331
return (
@@ -30,6 +38,14 @@ export function FavoriteButton({
3038
const handleClick = (e: React.MouseEvent) => {
3139
e.preventDefault(); // Предотвращаем навигацию если кнопка внутри Link
3240
e.stopPropagation();
41+
42+
// Отправляем событие в аналитику перед изменением состояния
43+
if (isInFavorites) {
44+
trackRemoveFromFavorites(presetId, presetName);
45+
} else {
46+
trackAddToFavorites(presetId, presetName);
47+
}
48+
3349
toggleFavorite(presetId);
3450
};
3551

docs/google-analytics-events.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Analytics Events Documentation
2+
3+
Система отслеживания событий для Google Analytics (через GTM) и Яндекс.Метрики.
4+
5+
**Важно:** События отправляются только в production режиме (`NODE_ENV === "production"`). В режиме разработки события логируются в консоль браузера.
6+
7+
## Настройка в Google Tag Manager
8+
9+
Для правильного отслеживания событий в Google Analytics через Google Tag Manager нужно настроить следующие триггеры и теги:
10+
11+
### 1. Триггер для пользовательских событий
12+
13+
**Название:** Custom Event Trigger
14+
**Тип:** Пользовательское событие
15+
**Имя события:** `custom_event`
16+
17+
### 2. Теги для отправки в Google Analytics
18+
19+
**Название:** GA4 - Custom Events
20+
**Тип:** Google Analytics: GA4 Event
21+
**Event Name:** `{{event_action}}`
22+
**Parameters:**
23+
24+
- `event_category`: `{{event_category}}`
25+
- `event_label`: `{{event_label}}`
26+
- `value`: `{{event_value}}`
27+
28+
### 3. Переменные dataLayer
29+
30+
Создайте следующие переменные типа "Переменная уровня данных":
31+
32+
- `event_action``event_action`
33+
- `event_category``event_category`
34+
- `event_label``event_label`
35+
- `event_value``event_value`
36+
37+
## Отслеживаемые события
38+
39+
### Избранные пресеты
40+
41+
#### add_to_favorites
42+
43+
- **Категория:** engagement
44+
- **Действие:** add_to_favorites
45+
- **Метка:** Название пресета (например, "Metallica - Master of Puppets Rhythm")
46+
- **Значение:** 1
47+
48+
#### remove_from_favorites
49+
50+
- **Категория:** engagement
51+
- **Действие:** remove_from_favorites
52+
- **Метка:** Название пресета
53+
- **Значение:** 1
54+
55+
## Примеры событий в dataLayer
56+
57+
```javascript
58+
// Добавление в избранное
59+
window.dataLayer.push({
60+
event: "custom_event",
61+
event_category: "engagement",
62+
event_action: "add_to_favorites",
63+
event_label: "Metallica - Master of Puppets Rhythm",
64+
event_value: 1,
65+
});
66+
67+
// Удаление из избранного
68+
window.dataLayer.push({
69+
event: "custom_event",
70+
event_category: "engagement",
71+
event_action: "remove_from_favorites",
72+
event_label: "Metallica - Master of Puppets Rhythm",
73+
event_value: 1,
74+
});
75+
```
76+
77+
## Яндекс.Метрика
78+
79+
События также отправляются в Яндекс.Метрику через метод `reachGoal`:
80+
81+
```javascript
82+
// Пример отправки цели в Яндекс.Метрику
83+
ym(103809700, "reachGoal", "add_to_favorites", {
84+
category: "engagement",
85+
label: "Metallica - Master of Puppets Rhythm",
86+
value: 1,
87+
});
88+
```
89+
90+
### Настройка целей в Яндекс.Метрике
91+
92+
В интерфейсе Яндекс.Метрики создайте цели типа "JavaScript-событие":
93+
94+
1. **add_to_favorites** - добавление в избранное
95+
2. **remove_from_favorites** - удаление из избранного
96+
97+
## Аналитика в Google Analytics 4
98+
99+
После настройки GTM, события будут автоматически отправляться в GA4. Вы можете найти их в отчетах:
100+
101+
1. **Realtime** → Events (для проверки в реальном времени)
102+
2. **Engagement** → Events (для анализа популярных событий)
103+
3. **Conversions** (если настроите события как конверсии)
104+
105+
### Рекомендуемые конверсии
106+
107+
Рекомендуется настроить как конверсии следующие события:
108+
109+
- `add_to_favorites` - показатель вовлеченности пользователей
110+
111+
### Настройка аудиторий
112+
113+
Можно создать аудитории на основе событий:
114+
115+
- Пользователи, которые добавляли пресеты в избранное
116+
- Активные пользователи (добавляли или удаляли из избранного)

lib/analytics.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { isProduction, isDevelopment } from "./env";
2+
3+
// Типы для Google Analytics событий
4+
interface GAEvent {
5+
action: string;
6+
category: string;
7+
label?: string;
8+
value?: number;
9+
}
10+
11+
// Расширяем интерфейс Window для gtag и Яндекс.Метрики
12+
declare global {
13+
interface Window {
14+
gtag: (
15+
command: string,
16+
action: string,
17+
parameters?: Record<string, any>,
18+
) => void;
19+
dataLayer: any[];
20+
ym: (counterId: number, method: string, ...params: any[]) => void;
21+
}
22+
}
23+
24+
/**
25+
* Отправляет событие в Google Analytics через Google Tag Manager и Яндекс.Метрику
26+
*/
27+
export function trackEvent({ action, category, label, value }: GAEvent): void {
28+
// Проверяем, что мы в браузере
29+
if (typeof window === "undefined") return;
30+
31+
try {
32+
if (isProduction) {
33+
// Отправляем событие через dataLayer (GTM)
34+
if (typeof window.dataLayer !== "undefined") {
35+
window.dataLayer.push({
36+
event: "custom_event",
37+
event_category: category,
38+
event_action: action,
39+
event_label: label,
40+
event_value: value,
41+
});
42+
}
43+
44+
// Также отправляем через gtag, если доступен
45+
if (typeof window.gtag !== "undefined") {
46+
window.gtag("event", action, {
47+
event_category: category,
48+
event_label: label,
49+
value: value,
50+
});
51+
}
52+
53+
// Отправляем в Яндекс.Метрику
54+
if (typeof window.ym !== "undefined") {
55+
window.ym(103809700, "reachGoal", action, {
56+
category: category,
57+
label: label,
58+
value: value,
59+
});
60+
}
61+
}
62+
} catch (error) {
63+
// В продакшене не показываем ошибки аналитики
64+
if (isDevelopment) {
65+
console.warn("Analytics tracking error:", error);
66+
}
67+
}
68+
69+
// В режиме разработки логируем события в консоль
70+
if (isDevelopment) {
71+
console.log("🔍 Analytics Event:", {
72+
action,
73+
category,
74+
label,
75+
value,
76+
timestamp: new Date().toISOString(),
77+
note: "Events are only sent in production mode",
78+
});
79+
}
80+
}
81+
82+
/**
83+
* Отправляет событие добавления в избранное
84+
*/
85+
export function trackAddToFavorites(
86+
presetId: string,
87+
presetName?: string,
88+
): void {
89+
trackEvent({
90+
action: "add_to_favorites",
91+
category: "engagement",
92+
label: presetName || presetId,
93+
value: 1,
94+
});
95+
}
96+
97+
/**
98+
* Отправляет событие удаления из избранного
99+
*/
100+
export function trackRemoveFromFavorites(
101+
presetId: string,
102+
presetName?: string,
103+
): void {
104+
trackEvent({
105+
action: "remove_from_favorites",
106+
category: "engagement",
107+
label: presetName || presetId,
108+
value: 1,
109+
});
110+
}

lib/env.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Единый источник истины для определения окружения
3+
* Single source of truth for environment detection
4+
*/
5+
6+
/**
7+
* Определяет, работает ли приложение в production режиме
8+
*/
9+
export const isProduction = process.env.NODE_ENV === "production";
10+
11+
/**
12+
* Определяет, работает ли приложение в development режиме
13+
*/
14+
export const isDevelopment = !isProduction;
15+
16+
/**
17+
* Определяет, работает ли приложение в test режиме
18+
*/
19+
export const isTest = process.env.NODE_ENV === "test";

0 commit comments

Comments
 (0)