diff --git a/package-lock.json b/package-lock.json index ac66e8f..480cf47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "react-dom": "^19.0.0", "react-hook-form": "^7.57.0", "react-hot-toast": "^2.5.2", + "react-yandex-metrika": "^2.6.0", "swiper": "^11.2.8", "zod": "^3.25.56" }, @@ -3957,7 +3958,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -4238,7 +4238,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4455,7 +4454,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4798,7 +4796,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -4895,9 +4892,18 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, + "node_modules/react-yandex-metrika": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-yandex-metrika/-/react-yandex-metrika-2.6.0.tgz", + "integrity": "sha512-8K4wExsNZtY3DTxh1G8a+zWH9Pg8fw23MJcoJ4I/562qrHRnh7L5nteq3lnNL58dnNQbuuHIRoGgMjIo+r1GjA==", + "license": "MIT", + "peerDependencies": { + "prop-types": "*", + "react": "*" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", diff --git a/package.json b/package.json index b2ff3b1..ac0c70d 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react-dom": "^19.0.0", "react-hook-form": "^7.57.0", "react-hot-toast": "^2.5.2", + "react-yandex-metrika": "^2.6.0", "swiper": "^11.2.8", "zod": "^3.25.56" }, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 716f773..c0e419c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,10 +1,11 @@ import type { Metadata } from 'next'; +import { ReactNode } from 'react'; import { Open_Sans } from 'next/font/google'; import '@core/styles/reset.scss'; import '@core/styles/globals.scss'; import { Toaster } from 'react-hot-toast'; import { ModalProvider } from '@core/providers/modal-provider'; -import { CookieNotice } from '@/widgets'; +import { CookieNotice, YandexMetrika } from '@/widgets'; const openSans = Open_Sans({ subsets: ['cyrillic'], @@ -32,10 +33,11 @@ export const metadata: Metadata = { export default function RootLayout({ children, -}: Readonly<{ children: React.ReactNode }>) { +}: Readonly<{ children: ReactNode }>) { return ( + {children} diff --git a/src/core/constants/tracking-service.ts b/src/core/constants/tracking-service.ts new file mode 100644 index 0000000..372c588 --- /dev/null +++ b/src/core/constants/tracking-service.ts @@ -0,0 +1,3 @@ +const YM_COUNTER_ID = 102875868; // ID счетчика YM + +export { YM_COUNTER_ID }; diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 49ca156..8c78942 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -6,3 +6,4 @@ export { OfferForm } from './offer-form'; export { OfferRequestForm } from './offer-request'; export { AdvancedPhoneInput } from './advanced-phone-input'; export { CookieNotice } from './cookie-notice'; +export { YandexMetrika } from './yandex-metrika'; diff --git a/src/widgets/yandex-metrika/index.ts b/src/widgets/yandex-metrika/index.ts new file mode 100644 index 0000000..70bad2d --- /dev/null +++ b/src/widgets/yandex-metrika/index.ts @@ -0,0 +1 @@ +export { default as YandexMetrika } from './ui'; diff --git a/src/widgets/yandex-metrika/ui.tsx b/src/widgets/yandex-metrika/ui.tsx new file mode 100644 index 0000000..c9b2033 --- /dev/null +++ b/src/widgets/yandex-metrika/ui.tsx @@ -0,0 +1,31 @@ +'use client'; + +import { usePathname } from 'next/navigation'; +import { useEffect } from 'react'; +import ym, { YMInitializer } from 'react-yandex-metrika'; +import { YM_COUNTER_ID } from '@core/constants/tracking-service'; + +export default function YandexMetrika() { + const pathname = usePathname(); + + // Отправляем событие "hit" при изменении маршрута + useEffect(() => { + if (pathname) { + ym('hit', pathname); + } + }, [pathname]); + + return ( + + ); +}