diff --git a/package.json b/package.json
index ea410d2..89736de 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,8 @@
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start -p 3001",
- "lint": "next lint"
+ "lint": "next lint",
+ "lint:fix": "next lint --fix"
},
"dependencies": {
"@lottiefiles/dotlottie-react": "^0.14.1",
@@ -34,4 +35,4 @@
"prettier": "^3.5.3",
"typescript": "^5"
}
-}
+}
\ No newline at end of file
diff --git a/public/metrics-scripts/ym-script.js b/public/metrics-scripts/ym-script.js
new file mode 100644
index 0000000..1751cbc
--- /dev/null
+++ b/public/metrics-scripts/ym-script.js
@@ -0,0 +1,24 @@
+(function (m, e, t, r, i, k, a) {
+ m[i] =
+ m[i] ||
+ function () {
+ (m[i].a = m[i].a || []).push(arguments);
+ };
+ m[i].l = 1 * new Date();
+ for (var j = 0; j < document.scripts.length; j++) {
+ if (document.scripts[j].src === r) {
+ return;
+ }
+ }
+ (k = e.createElement(t)),
+ (a = e.getElementsByTagName(t)[0]),
+ (k.async = 1),
+ (k.src = r),
+ a.parentNode.insertBefore(k, a);
+})(
+ window,
+ document,
+ "script",
+ "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js",
+ "ym"
+);
\ No newline at end of file
diff --git a/src/app/[locale]/(core)/payment/success/Metrics.module.scss b/src/app/[locale]/(core)/payment/success/Metrics.module.scss
new file mode 100644
index 0000000..979775c
--- /dev/null
+++ b/src/app/[locale]/(core)/payment/success/Metrics.module.scss
@@ -0,0 +1,23 @@
+.button {
+ position: fixed;
+ bottom: calc(0dvh + 64px);
+ left: 50%;
+ transform: translate(-50%, 0);
+ opacity: 0;
+ pointer-events: none;
+ max-width: 400px;
+ width: calc(100dvw - 32px);
+ animation: fadeIn 0.5s ease-in-out 2s forwards;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ to {
+ opacity: 1;
+ pointer-events: auto;
+ }
+}
\ No newline at end of file
diff --git a/src/app/[locale]/(core)/payment/success/Metrics.tsx b/src/app/[locale]/(core)/payment/success/Metrics.tsx
new file mode 100644
index 0000000..51984bd
--- /dev/null
+++ b/src/app/[locale]/(core)/payment/success/Metrics.tsx
@@ -0,0 +1,185 @@
+"use client";
+
+import { useEffect, useState } from "react";
+import Script from "next/script";
+import { useTranslations } from "next-intl";
+
+import { Button, Typography } from "@/components/ui";
+import { ROUTES } from "@/shared/constants/client-routes";
+
+import styles from "./Metrics.module.scss";
+
+interface MetricsProps {
+ fbPixels: string[];
+ productPrice: string;
+ currency: string;
+}
+
+export default function Metrics({ fbPixels, productPrice, currency }: MetricsProps) {
+ const t = useTranslations("Payment.Success");
+
+ const [isButtonVisible, setIsButtonVisible] = useState(false);
+
+ const navigateToHome = () => {
+ window.location.href = ROUTES.home()
+ }
+
+ // Yandex Metrica
+ useEffect(() => {
+ const interval = setInterval(() => {
+ if (typeof window.ym === 'function' && typeof window.klaviyo === 'object' && typeof window.gtag === 'function') {
+ try {
+ window.gtag('event', 'PaymentSuccess')
+ window.klaviyo.push(['track', "PaymentSuccess"]);
+
+ window.ym(95799066, "init", {
+ clickmap: true,
+ trackLinks: true,
+ accurateTrackBounce: true,
+ webvisor: true,
+ });
+
+ window.ym(95799066, 'reachGoal', "PaymentSuccess", {}, () => {
+ console.log("Запрос отправлен");
+ // deleteYm()
+ setIsButtonVisible(true);
+ })
+
+ } catch (e) {
+ console.error('YM error:', e)
+ } finally {
+ clearInterval(interval);
+ }
+ }
+ }, 200);
+
+ return () => clearInterval(interval)
+ }, []);
+
+ return <>
+
+ {/* Klaviyo */}
+ {/* */}
+
+
+
+ {/* Yandex Metrica */}
+
+
+ {/* Google Analytics */}
+
+
+
+ {/* Facebook Pixel */}
+ {fbPixels.map((pixel) => (
+
+ ))}
+
+ {isButtonVisible &&
+
+ }
+ >;
+}
\ No newline at end of file
diff --git a/src/app/[locale]/(core)/payment/success/page.tsx b/src/app/[locale]/(core)/payment/success/page.tsx
index ec03e9d..81dfb50 100644
--- a/src/app/[locale]/(core)/payment/success/page.tsx
+++ b/src/app/[locale]/(core)/payment/success/page.tsx
@@ -1,20 +1,34 @@
import { getTranslations } from "next-intl/server";
import { AnimatedInfoScreen, LottieAnimation } from "@/components/widgets";
-import { ROUTES } from "@/shared/constants/client-routes";
import { ELottieKeys } from "@/shared/constants/lottie";
-export default async function PaymentSuccess() {
+import Metrics from "./Metrics";
+
+export default async function PaymentSuccess({ searchParams }: {
+ searchParams: Promise<{
+ [key: string]: string | undefined
+ }>;
+}) {
+ const params = await searchParams;
+
+ const fbPixels = params?.fb_pixels?.split(",") || [];
+ const productPrice = params?.price || "0";
+ const currency = params?.currency || "USD";
+
const t = await getTranslations("Payment.Success");
return (
- }
- title={t("title")}
- animationTime={0}
- animationTexts={[]}
- buttonText={t("button")}
- nextRoute={ROUTES.home()}
- />
+ <>
+ }
+ title={t("title")}
+ />
+
+ >
);
}
\ No newline at end of file
diff --git a/src/components/widgets/AnimatedInfoScreen/AnimatedInfoScreen.tsx b/src/components/widgets/AnimatedInfoScreen/AnimatedInfoScreen.tsx
index 7933e22..8b59ac1 100644
--- a/src/components/widgets/AnimatedInfoScreen/AnimatedInfoScreen.tsx
+++ b/src/components/widgets/AnimatedInfoScreen/AnimatedInfoScreen.tsx
@@ -8,10 +8,10 @@ import styles from "./AnimatedInfoScreen.module.scss";
interface AnimatedInfoScreenProps {
lottieAnimation: React.ReactNode;
title: string;
- animationTime: number;
+ animationTime?: number;
animationTexts?: string[];
- buttonText: string;
- nextRoute: string;
+ buttonText?: string;
+ nextRoute?: string;
}
export default async function AnimatedInfoScreen({
@@ -29,15 +29,15 @@ export default async function AnimatedInfoScreen({
{title}
- {!!animationTexts?.length && }
-
+ {nextRoute && buttonText &&
{buttonText}
-
+ }
)
}
\ No newline at end of file
diff --git a/src/types/index.ts b/src/types/index.ts
index 9e7a649..ec37068 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -20,4 +20,21 @@ export enum ERetainingFunnel {
Green = "green",
Purple = "purple",
Stay50 = "stay50",
+}
+
+declare global {
+ interface Window {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ym: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ymab: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ klaviyo: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ fbq: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ CollectJS: any;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ gtag: any;
+ }
}
\ No newline at end of file