diff --git a/ANALYTICS_EVENTS.md b/ANALYTICS_EVENTS.md new file mode 100644 index 0000000..10dd606 --- /dev/null +++ b/ANALYTICS_EVENTS.md @@ -0,0 +1,187 @@ +# Документация по аналитическим событиям + +В этом документе представлен полный список событий для отслеживания в приложении с использованием сервиса `customAnalyticsService.ts`. События сгруппированы по экранам и функциональным блокам. + +## 1. Общие события приложения + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Открытие мини-приложения | `app` | `app_open` | - | - | + +## 2. Навигация + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Открытие экрана Главная | `navigation` | `view_home` | - | - | +| Открытие экрана Галерея | `navigation` | `view_gallery` | - | - | +| Открытие экрана Стикерпаки | `navigation` | `view_sticker_packs` | - | - | +| Открытие экрана Профиль | `navigation` | `view_profile` | - | - | +| Открытие экрана Обрезка фото | `navigation` | `view_crop_photo` | - | - | +| Открытие экрана Создание стикерпака | `navigation` | `view_create_sticker_pack` | - | - | +| Открытие экрана Добавление стикера в пак | `navigation` | `view_add_sticker_to_pack` | - | - | +| Открытие экрана Политика конфиденциальности | `navigation` | `view_terms_and_conditions` | - | - | +| Открытие экрана Инструкция | `navigation` | `view_how_to` | - | - | + +## 3. Политика конфиденциальности + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на ссылку политики | `terms` | `policy_link_click` | - | `link_url` | +| Принятие политики | `terms` | `accept` | - | - | +| Отклонение политики | `terms` | `decline` | - | - | + +## 4. Главный экран (Home) + +### 4.1 Верхний блок кнопок + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на кнопку обратной связи | `ui_interaction` | `feedback_button_click` | - | - | +| Нажатие на кнопку инструкции | `ui_interaction` | `instruction_button_click` | - | - | +| Нажатие на кнопку другого бота | `ui_interaction` | `other_bot_button_click` | - | `bot_url` | + +### 4.2 Хедер + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на кнопку баланса | `ui_interaction` | `balance_button_click` | - | - | + +### 4.3 Загрузка и обработка фото + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на загрузить фото | `photo` | `upload_photo_click` | - | - | +| Применение обрезки фото | `photo` | `crop_photo_apply` | - | - | + +### 4.4 Выбор стиля и параметров + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие кнопки Чиби стиль | `style` | `chibi_style_click` | - | - | +| Нажатие кнопки Эмодзи стиль | `style` | `emoji_style_click` | - | - | +| Выбор подкатегории Мем | `style` | `meme_subcategory_select` | - | `meme_id` | +| Выбор подкатегории Коллекция | `style` | `collection_subcategory_select` | - | `collection_id` | + +### 4.5 Генерация стикера + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Удачная отправка на генерацию | `generation` | `generation_success` | 1 | `preset_name` | +| Неудачная отправка на генерацию | `generation` | `generation_failure` | - | `error_type` | + +### 4.6 Футер + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на кнопку Главная | `footer` | `home_button_click` | - | - | +| Нажатие на кнопку Галерея | `footer` | `gallery_button_click` | - | - | +| Нажатие на кнопку Стикерпаки | `footer` | `sticker_packs_button_click` | - | - | +| Нажатие на кнопку Профиль | `footer` | `profile_button_click` | - | - | + +## 5. Экран Галерея + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Долгое удерживание на изображении | `gallery` | `image_long_press` | - | `image_id` | +| Удаление изображения | `gallery` | `image_delete` | - | `image_id` | +| Нажатие кнопки "Создать стикерпак" | `gallery` | `create_sticker_pack_click` | - | `from_gallery` | + +## 6. Экран Стикерпаки + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие кнопки "Создать стикерпак" | `sticker_packs` | `create_sticker_pack_click` | - | `from_sticker_packs` | +| Создание стикерпака | `sticker_packs` | `sticker_pack_created` | - | `pack_url` | +| Ошибка создания стикерпака | `sticker_packs` | `sticker_pack_creation_error` | - | `error_type` | +| Удаление стикерпака | `sticker_packs` | `sticker_pack_deleted` | - | `pack_id` | + +## 7. Экран Профиль и попап с офферами + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Нажатие на оффер на экране профиля | `offers` | `profile_offer_click` | - | `offer_id` | +| Нажатие на оффер в попапе | `offers` | `popup_offer_click` | - | `offer_id` | +| Успешная покупка | `payment` | `purchase_success` | `stars_amount` | `star` | + +## 8. Экраны онбординга + +### 8.1 Экран приветствия (OnboardingWelcome) + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Открытие экрана приветствия | `navigation` | `view_onboarding_welcome` | - | - | +| Нажатие кнопки "Далее" | `onboarding` | `welcome_next_click` | - | - | +| Нажатие кнопки "Пропустить" | `onboarding` | `welcome_skip_click` | - | - | + +### 8.2 Экран инструкции (OnboardingHowTo) + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Открытие экрана инструкции | `navigation` | `view_onboarding_how_to` | - | - | +| Нажатие кнопки "Далее" | `onboarding` | `how_to_next_click` | - | - | +| Нажатие кнопки "Назад" | `onboarding` | `how_to_back_click` | - | - | +| Нажатие кнопки "Пропустить" | `onboarding` | `how_to_skip_click` | - | - | +| Переключение слайда инструкции | `onboarding` | `how_to_slide_change` | - | `slide_index` | + +### 8.3 Экран стикерпаков (OnboardingStickerPacks) + +| Событие | Категория | Название события | Значение | Единица измерения | +|---------|-----------|------------------|----------|-------------------| +| Открытие экрана стикерпаков | `navigation` | `view_onboarding_sticker_packs` | - | - | +| Нажатие кнопки "Начать" | `onboarding` | `sticker_packs_start_click` | - | - | +| Нажатие кнопки "Назад" | `onboarding` | `sticker_packs_back_click` | - | - | + +## Примеры использования + +### Отслеживание открытия приложения + +```typescript +import customAnalyticsService from '../services/customAnalyticsService'; + +// В компоненте App.tsx при монтировании +useEffect(() => { + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'app', + event_name: 'app_open' + }); +}, []); +``` + +### Отслеживание навигации + +```typescript +import customAnalyticsService from '../services/customAnalyticsService'; + +// В компоненте страницы +useEffect(() => { + customAnalyticsService.trackNavigation('home'); +}, []); +``` + +### Отслеживание генерации стикера + +```typescript +import customAnalyticsService from '../services/customAnalyticsService'; + +// При успешной генерации стикера +const handleGenerationSuccess = (presetName) => { + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'generation', + event_name: 'generation_success', + value: 1, + unit: presetName + }); +}; +``` + +### Отслеживание покупки + +```typescript +import customAnalyticsService from '../services/customAnalyticsService'; + +// При успешной покупке +const handlePurchaseSuccess = (starsAmount) => { + customAnalyticsService.trackPayment('purchase_success', starsAmount, 'star'); +}; diff --git a/src/App.tsx b/src/App.tsx index fac0fc3..002cb96 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,8 +2,9 @@ import React, { lazy, Suspense, useEffect } from 'react'; import { BrowserRouter, Routes, Route, Navigate, Outlet, useNavigate, useLocation } from 'react-router-dom'; import Layout from './components/layout/Layout'; import Home from './screens/Home'; -import { initializeUserId } from './constants/user'; +import { initializeUserId, getCurrentUserId } from './constants/user'; import { trackScreenView } from './services/analyticsService'; +import customAnalyticsService from './services/customAnalyticsService'; import { BalanceProvider } from './contexts/BalanceContext'; // Ленивая загрузка компонентов @@ -39,9 +40,18 @@ const AppContent: React.FC = () => { useEffect(() => { // Инициализируем ID пользователя при запуске приложения - initializeUserId().catch(error => { - console.error('Ошибка при инициализации пользователя:', error); - }); + initializeUserId() + .then(() => { + // Отправляем событие открытия приложения после успешной инициализации + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'app', + event_name: 'app_open' + }); + }) + .catch(error => { + console.error('Ошибка при инициализации пользователя:', error); + }); // Стабилизируем окно и отключаем вертикальные свайпы if (window.Telegram?.WebApp) { @@ -98,6 +108,9 @@ const AppContent: React.FC = () => { // Отправляем событие просмотра экрана trackScreenView(screenName); + + // Отправляем событие навигации в нашу новую аналитику + customAnalyticsService.trackNavigation(location.pathname.replace('/', '')); }, [location.pathname]); return ( diff --git a/src/components/generation/EmotionTypeSelector.tsx b/src/components/generation/EmotionTypeSelector.tsx index 5f718ac..5dc3d6f 100644 --- a/src/components/generation/EmotionTypeSelector.tsx +++ b/src/components/generation/EmotionTypeSelector.tsx @@ -1,6 +1,8 @@ import React from 'react'; import BlockRenderer from '../blocks/BlockRenderer'; import { homeScreenConfig } from '../../config/homeScreen'; +import customAnalyticsService from '../../services/customAnalyticsService'; +import { getCurrentUserId } from '../../constants/user'; interface EmotionTypeSelectorProps { selectedEmotionTypeButtonId?: string; @@ -30,6 +32,14 @@ const EmotionTypeSelector: React.FC = ({ // Обработчик выбора типа эмоций const handleAction = (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => { if (actionType === 'selectEmotionType') { + // Отслеживаем событие выбора типа эмоций + const eventName = actionValue === 'memes' ? 'memes_category_click' : 'prompts_category_click'; + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'emotion_type', + event_name: eventName + }); + onEmotionTypeSelect(actionValue as 'memes' | 'prompts', buttonId); } }; diff --git a/src/components/generation/GenerationButton.tsx b/src/components/generation/GenerationButton.tsx index e2914c7..5e6babc 100644 --- a/src/components/generation/GenerationButton.tsx +++ b/src/components/generation/GenerationButton.tsx @@ -2,6 +2,8 @@ import React from 'react'; import BlockRenderer from '../blocks/BlockRenderer'; import { homeScreenConfig } from '../../config/homeScreen'; import styles from '../../screens/Home.module.css'; +import customAnalyticsService from '../../services/customAnalyticsService'; +import { getCurrentUserId } from '../../constants/user'; interface GenerationButtonProps { onStartGeneration: () => void; @@ -25,6 +27,13 @@ const GenerationButton: React.FC = ({ // Обработчик нажатия на кнопку генерации const handleAction = (actionType: string, actionValue: string) => { if (actionType === 'function' && actionValue === 'startGeneration' && !isGenerating) { + // Отслеживаем событие нажатия на кнопку генерации + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'generation', + event_name: 'generate_button_click' + }); + onStartGeneration(); } }; diff --git a/src/components/generation/MainActions.tsx b/src/components/generation/MainActions.tsx index 0a03290..1d96c50 100644 --- a/src/components/generation/MainActions.tsx +++ b/src/components/generation/MainActions.tsx @@ -1,6 +1,8 @@ import React from 'react'; import BlockRenderer from '../blocks/BlockRenderer'; import { homeScreenConfig } from '../../config/homeScreen'; +import customAnalyticsService from '../../services/customAnalyticsService'; +import { getCurrentUserId } from '../../constants/user'; interface MainActionsProps { onSendFeedback: () => void; @@ -26,8 +28,21 @@ const MainActions: React.FC = ({ const handleAction = (actionType: string, actionValue: string) => { if (actionType === 'function') { if (actionValue === 'sendFeedback') { + // Отслеживаем событие нажатия на кнопку обратной связи + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'ui_interaction', + event_name: 'feedback_button_click' + }); onSendFeedback(); } else if (actionValue === 'openTelegramBot') { + // Отслеживаем событие нажатия на кнопку другого бота + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'ui_interaction', + event_name: 'other_bot_button_click', + unit: 'https://t.me/youtube_s_loader_bot' + }); onOpenTelegramBot(); } } diff --git a/src/components/generation/PhotoUpload.tsx b/src/components/generation/PhotoUpload.tsx index b1faeb2..6a67e11 100644 --- a/src/components/generation/PhotoUpload.tsx +++ b/src/components/generation/PhotoUpload.tsx @@ -1,6 +1,8 @@ import React from 'react'; import BlockRenderer from '../blocks/BlockRenderer'; import { homeScreenConfig } from '../../config/homeScreen'; +import customAnalyticsService from '../../services/customAnalyticsService'; +import { getCurrentUserId } from '../../constants/user'; interface PhotoUploadProps { onImageDataChange: (imageData: string) => void; @@ -22,8 +24,17 @@ const PhotoUpload: React.FC = ({ // Обработчик загрузки фото const handleAction = (actionType: string, actionValue: string, blockId?: string, buttonId?: string, extraData?: any) => { - if (actionType === 'uploadPhoto' && extraData?.imageData) { - onImageDataChange(extraData.imageData); + if (actionType === 'uploadPhoto') { + // Отслеживаем событие нажатия на загрузить фото + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'photo', + event_name: 'upload_photo_click' + }); + + if (extraData?.imageData) { + onImageDataChange(extraData.imageData); + } } }; diff --git a/src/components/generation/StyleSelector.tsx b/src/components/generation/StyleSelector.tsx index 2264633..23c2181 100644 --- a/src/components/generation/StyleSelector.tsx +++ b/src/components/generation/StyleSelector.tsx @@ -1,6 +1,8 @@ import React from 'react'; import BlockRenderer from '../blocks/BlockRenderer'; import { homeScreenConfig } from '../../config/homeScreen'; +import customAnalyticsService from '../../services/customAnalyticsService'; +import { getCurrentUserId } from '../../constants/user'; interface StyleSelectorProps { selectedStyleButtonId?: string; @@ -25,6 +27,14 @@ const StyleSelector: React.FC = ({ // Обработчик выбора стиля const handleAction = (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => { if (actionType === 'selectStyle') { + // Отслеживаем событие выбора стиля + const eventName = actionValue === 'chibi' ? 'chibi_style_click' : 'emoji_style_click'; + customAnalyticsService.trackEvent({ + telegram_id: getCurrentUserId(), + event_category: 'style', + event_name: eventName + }); + onStyleSelect(actionValue, buttonId); } }; diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 386760c..4c36820 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -8,6 +8,7 @@ import { paymentService } from '../../services/paymentService'; import { tokenPacks } from '../../constants/tokenPacks'; import NotificationModal from '../shared/NotificationModal'; import { useBalance } from '../../contexts/BalanceContext'; +import customAnalyticsService from '../../services/customAnalyticsService'; import styles from './Header.module.css'; const Header: React.FC = () => { @@ -70,7 +71,15 @@ const Header: React.FC = () => { {/* Баланс токенов */}