обавлена интеграция с аналитическим сервисом Graspil

This commit is contained in:
kazachilo 2025-03-27 11:22:15 +03:00
parent a366be55c7
commit c3e6a6b05d
6 changed files with 167 additions and 0 deletions

View File

@ -9,6 +9,12 @@
<meta name="description" content="Создавайте уникальные стикеры для Telegram" />
<title>Sticker Generator</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<script type="text/javascript">
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({key:i});
var f=d.getElementsByTagName(s)[0],j=d.createElement(s);
j.async=true;j.src="https://w.graspil.com";f.parentNode.insertBefore(j,f);
})(window,document,"script","graspil","3bb78a396b0aa436843d606d02abfe4c");
</script>
</head>
<body>
<div id="root"></div>

View File

@ -3,6 +3,7 @@ import { BrowserRouter, Routes, Route, Navigate, Outlet, useNavigate, useLocatio
import Layout from './components/layout/Layout';
import Home from './screens/Home';
import { initializeUserId } from './constants/user';
import { trackScreenView } from './services/analyticsService';
// Ленивая загрузка компонентов
const OnboardingWelcome = lazy(() => import('./screens/onboarding/OnboardingWelcome'));
@ -64,6 +65,38 @@ const AppContent: React.FC = () => {
}
}, [navigate, location.pathname]);
// Отслеживаем изменение маршрута для аналитики
useEffect(() => {
// Получаем название экрана из пути
let screenName = location.pathname;
if (screenName === '/') {
screenName = 'Главная';
} else {
// Преобразуем путь в более читаемое название
screenName = screenName
.replace('/onboarding/welcome', 'Онбординг: Приветствие')
.replace('/onboarding/how-to', 'Онбординг: Как использовать')
.replace('/onboarding/sticker-packs', 'Онбординг: Стикер-паки')
.replace('/onboarding/terms', 'Условия использования')
.replace('/create', 'Создание стикера')
.replace('/gallery', 'Галерея')
.replace('/packs', 'Стикер-паки')
.replace('/create-sticker-pack', 'Создание стикер-пака')
.replace('/profile', 'Профиль')
.replace('/history', 'История')
.replace('/crop-photo', 'Обрезка фото');
// Если это добавление стикера в пак, извлекаем название пака
if (screenName.includes('/add-sticker/')) {
const packName = screenName.split('/add-sticker/')[1];
screenName = `Добавление стикера в пак: ${packName}`;
}
}
// Отправляем событие просмотра экрана
trackScreenView(screenName);
}, [location.pathname]);
return (
<Routes>
{/* Онбординг */}

View File

@ -0,0 +1,105 @@
/**
* Сервис для работы с аналитикой Graspil
*/
/**
* Отслеживает пользовательское событие
* @param eventName - Название события
* @param category - Категория события (опционально)
* @param valueNum - Числовое значение (опционально)
* @param unit - Код валюты, максимальная длина 3 символа (опционально, обязательно если указан valueNum)
*/
export const trackEvent = (
eventName: string,
category?: string,
valueNum?: number,
unit?: string
): void => {
if (typeof window !== 'undefined' && window.graspil) {
const eventData: {
event: string;
category?: string;
value_num?: number;
unit?: string;
} = {
event: eventName,
};
if (category) {
eventData.category = category;
}
if (valueNum !== undefined) {
eventData.value_num = valueNum;
// Если есть числовое значение, но нет единицы измерения, используем 'unit' по умолчанию
if (unit) {
eventData.unit = unit;
}
}
window.graspil.push(eventData);
}
};
/**
* Отслеживает просмотр экрана
* @param screenName - Название экрана
*/
export const trackScreenView = (screenName: string): void => {
trackEvent(`Просмотр экрана: ${screenName}`, 'navigation');
};
/**
* Отслеживает клик по кнопке
* @param buttonName - Название кнопки
*/
export const trackButtonClick = (buttonName: string): void => {
trackEvent(`Клик: ${buttonName}`, 'interaction');
};
/**
* Отслеживает генерацию стикера
* @param prompt - Промпт для генерации
*/
export const trackStickerGeneration = (prompt: string): void => {
// Создаем объект события с дополнительными данными
const eventData: {
event: string;
category: string;
value_num: number;
prompt?: string;
} = {
event: 'Генерация стикера',
category: 'generation',
value_num: 1
};
// Добавляем промпт в данные события, если он предоставлен
if (prompt) {
eventData.prompt = prompt;
}
// Отправляем событие напрямую, чтобы включить дополнительные данные
if (typeof window !== 'undefined' && window.graspil) {
window.graspil.push(eventData);
}
};
/**
* Отслеживает создание стикер-пака
* @param packName - Название пака
*/
export const trackStickerPackCreation = (packName: string): void => {
trackEvent('Создание стикер-пака', 'creation', 1);
};
/**
* Отслеживает покупку токенов
* @param amount - Количество токенов
* @param price - Цена в валюте
* @param currency - Код валюты (максимум 3 символа)
*/
export const trackTokenPurchase = (amount: number, price: number, currency: string): void => {
trackEvent('Покупка токенов', 'purchase', price, currency);
};

View File

@ -3,6 +3,7 @@ import { baseWorkflow } from '../constants/baseWorkflow';
import { prompts } from '../assets/prompts';
import translateService from './translateService';
import { getCurrentUserId, isTelegramWebAppAvailable } from '../constants/user';
import { trackStickerGeneration } from './analyticsService';
const API_BASE_URL = 'https://stickerserver.gymnasticstuff.uk';
@ -276,6 +277,9 @@ const apiService = {
const result = await response.json() as GenerationResponse;
// Отслеживаем событие генерации стикера
trackStickerGeneration(usedPrompt);
// Возвращаем результат и использованный промпт
return {
result,

View File

@ -1,6 +1,7 @@
import { getCurrentUserId } from '../constants/user';
import { StickerPack, StickerSetResponse } from '../types/api';
import { normalizeImageUrl } from './api';
import { trackStickerPackCreation } from './analyticsService';
/**
* Сервис для работы со стикерпаками через Sticker API.
@ -125,6 +126,9 @@ export class StickerService {
}
}
// Отслеживаем событие создания стикер-пака
trackStickerPackCreation(title);
return createResult;
} catch (error) {
console.error('Ошибка при создании стикерпака:', error);

15
src/types/global.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
interface GraspilEvent {
event: string;
category?: string;
value_num?: number;
unit?: string;
key?: string;
}
interface GraspilInstance extends Array<GraspilEvent> {
push: (event: GraspilEvent) => void;
}
interface Window {
graspil: GraspilInstance;
}