diff --git a/ANALYTICS_IMPLEMENTATION.md b/ANALYTICS_IMPLEMENTATION.md
new file mode 100644
index 0000000..46d71b2
--- /dev/null
+++ b/ANALYTICS_IMPLEMENTATION.md
@@ -0,0 +1,123 @@
+# Analytics System Implementation
+
+## Обзор
+
+В проект `witlab-app` была добавлена система аналитики на основе Yandex Metrika по аналогии с `witlab-funnel`:
+
+- **Yandex Metrika** - отслеживание просмотров страниц и событий
+- **PageViewTracker** - автоматическая отслежка переходов между страницами
+- **AnalyticsService** - управление параметрами пользователя и событиями
+
+## Структура файлов
+
+```
+src/
+├── components/analytics/
+│ ├── PageViewTracker.tsx # Отслеживание переходов
+│ ├── YandexMetrika/
+│ │ ├── YandexMetrika.tsx # Компонент Яндекс Метрики
+│ │ └── index.ts
+│ └── index.ts # Экспорты аналитики
+├── providers/
+│ └── analytics-provider.tsx # Провайдер аналитики
+├── services/analytics/
+│ ├── analyticsService.ts # Сервис аналитики
+│ └── index.ts
+└── shared/constants/
+ └── analytics.ts # Константы ID счетчиков
+```
+
+## Конфигурация
+
+### Статичные константы
+
+```typescript
+// src/shared/constants/analytics.ts
+export const YANDEX_METRIKA_ID = "103412914";
+```
+
+## Использование
+
+### Автоматическая отслежка страниц
+
+Система автоматически отслеживает все переходы между страницами через `PageViewTracker`.
+
+### Параметры пользователя
+
+При инициализации система автоматически загружает данные пользователя через `/users/me` и устанавливает параметры в Yandex Metrika:
+
+- `user_id` - ID пользователя
+- `email` - email пользователя
+- `locale` - язык пользователя
+- `timezone` - часовой пояс
+- `profile_name`, `profile_gender`, `profile_age`, `profile_sign` - данные профиля
+- `partner_gender`, `partner_age`, `partner_sign` - данные партнера
+- `country`, `region`, `city` - геолокация
+
+### Отслеживание событий
+
+```typescript
+import { analyticsService } from "@/services/analytics";
+
+// Отправить событие в Yandex Metrika
+analyticsService.trackEvent("button_click", {
+ button_name: "subscribe_now",
+ screen: "retaining"
+});
+```
+
+### Доступ к данным пользователя
+
+```typescript
+import { analyticsService } from "@/services/analytics";
+
+if (analyticsService.isReady()) {
+ const user = analyticsService.getUser();
+ console.log("Current user:", user);
+}
+```
+
+## Логирование
+
+Система предоставляет детальное логирование в консоли:
+
+```
+✅ [YM] Page View Event Sent
+✅ [Analytics] Service initialized with user data
+✅ [YM] User parameters set
+```
+
+## Интеграция в layout
+
+Компоненты аналитики добавлены в `src/app/[locale]/layout.tsx`:
+
+```tsx
+
+
+ {/* ... */}
+
+ {/* ... */}
+
+```
+
+## Отличия от witlab-funnel
+
+1. **Только Yandex Metrika** - без Google Analytics
+2. **Статичный ID** - Яндекс Метрика использует статичный ID вместо динамического из воронки
+3. **Параметры пользователя** - Автоматическая загрузка и установка параметров из `/me`
+4. **Унифицированный сервис** - Единый `AnalyticsService` для управления
+
+## Проверка работы
+
+1. Откройте консоль разработчика в браузере
+2. Перейдите между страницами приложения
+3. Вы увидите сообщения об отправке событий в YM
+4. Проверьте наличие cookies `_ym_uid`
+
+## Совместимость
+
+- ✅ TypeScript
+- ✅ ESLint (без ошибок, только предупреждения о существующих `any`)
+- ✅ Next.js 15
+- ✅ Server-side rendering
+- ✅ Динамические маршруты
diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx
index f9b67b4..fda543d 100644
--- a/src/app/[locale]/layout.tsx
+++ b/src/app/[locale]/layout.tsx
@@ -9,10 +9,11 @@ import { hasLocale, NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import clsx from "clsx";
-import YandexMetrika from "@/components/analytics/YandexMetrika";
+import { PageViewTracker,YandexMetrika } from "@/components/analytics";
import { loadChatsList } from "@/entities/chats/loaders";
import { loadUser, loadUserId } from "@/entities/user/loaders";
import { routing } from "@/i18n/routing";
+import { AnalyticsProvider } from "@/providers/analytics-provider";
import { AppUiStoreProvider } from "@/providers/app-ui-store-provider";
import { AudioProvider } from "@/providers/audio-provider";
import { ChatsInitializationProvider } from "@/providers/chats-initialization-provider";
@@ -68,24 +69,29 @@ export default async function RootLayout({
return (
+ {/* Analytics Components */}
-
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+
);
diff --git a/src/components/analytics/PageViewTracker.tsx b/src/components/analytics/PageViewTracker.tsx
new file mode 100644
index 0000000..d8770ef
--- /dev/null
+++ b/src/components/analytics/PageViewTracker.tsx
@@ -0,0 +1,54 @@
+"use client";
+
+import { useEffect } from "react";
+import { usePathname, useSearchParams } from "next/navigation";
+
+/**
+ * Wait for Yandex Metrika to be loaded
+ * Retry mechanism with timeout to handle async script loading
+ */
+async function waitForYandexMetrika(maxAttempts = 10, delayMs = 100): Promise {
+ for (let i = 0; i < maxAttempts; i++) {
+ if (typeof window !== "undefined" &&
+ typeof window.ym === "function" &&
+ window.__YM_COUNTER_ID__) {
+ return true;
+ }
+ await new Promise(resolve => setTimeout(resolve, delayMs));
+ }
+ return false;
+}
+
+/**
+ * Page View Tracker Component
+ *
+ * Tracks page views in Yandex Metrika
+ * when route changes occur (client-side navigation).
+ *
+ * Must be included in the app layout or root component.
+ */
+export function PageViewTracker() {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+
+ useEffect(() => {
+ const url = pathname + (searchParams?.toString() ? `?${searchParams.toString()}` : "");
+
+ // Track page view in Yandex Metrika (with retry logic)
+ const trackYandexMetrika = async () => {
+ const isYmAvailable = await waitForYandexMetrika();
+
+ if (isYmAvailable && typeof window.ym === "function") {
+ const counterId = window.__YM_COUNTER_ID__;
+ if (counterId) {
+ window.ym(counterId, "hit", url);
+ }
+ }
+ };
+
+ // Execute YM tracking
+ trackYandexMetrika();
+ }, [pathname, searchParams]);
+
+ return null;
+}
diff --git a/src/components/analytics/YandexMetrika/YandexMetrika.tsx b/src/components/analytics/YandexMetrika/YandexMetrika.tsx
index 0b4cdcb..0b54592 100644
--- a/src/components/analytics/YandexMetrika/YandexMetrika.tsx
+++ b/src/components/analytics/YandexMetrika/YandexMetrika.tsx
@@ -1,79 +1,52 @@
"use client";
-import { useEffect } from "react";
import Script from "next/script";
-const YANDEX_METRIKA_ID = 103412914;
-
-export default function YandexMetrika() {
- useEffect(() => {
- // Initialize Yandex.Metrika after script loads
- const initializeYandexMetrika = () => {
- if (typeof window.ym === "function") {
- try {
- window.ym(YANDEX_METRIKA_ID, "init", {
- webvisor: true,
- clickmap: true,
- accurateTrackBounce: true,
- trackLinks: true,
- });
- } catch {
- // Silently handle initialization errors
- }
- }
- };
-
- // Check if ym is already available or wait for it
- if (typeof window.ym === "function") {
- initializeYandexMetrika();
- } else {
- // Wait for script to load
- const checkYm = setInterval(() => {
- if (typeof window.ym === "function") {
- initializeYandexMetrika();
- clearInterval(checkYm);
- }
- }, 100);
-
- // Cleanup interval after 10 seconds
- setTimeout(() => {
- clearInterval(checkYm);
- }, 10000);
-
- return () => clearInterval(checkYm);
- }
- }, []);
+import { YANDEX_METRIKA_ID } from "@/shared/constants/analytics";
+/**
+ * Yandex Metrika Integration Component
+ *
+ * Loads Yandex Metrika tracking script dynamically using static counter ID.
+ *
+ * Initializes with: clickmap, trackLinks, accurateTrackBounce, webvisor.
+ * Page views are tracked by PageViewTracker component on route changes.
+ */
+export function YandexMetrika() {
return (
<>
- {/* Yandex.Metrika counter */}
-
- {/* Noscript fallback */}