From b4c4067b5edeaf13c20738381fcb7212704abee9 Mon Sep 17 00:00:00 2001 From: "dev.daminik00" Date: Wed, 24 Dec 2025 21:42:47 +0300 Subject: [PATCH] utm --- .../Payment/nmi/PaymentPage/index.tsx | 21 ++++- src/services/url/index.ts | 80 ++++++++++++++++++- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/components/Payment/nmi/PaymentPage/index.tsx b/src/components/Payment/nmi/PaymentPage/index.tsx index 4f0b1d9..a5d62e2 100644 --- a/src/components/Payment/nmi/PaymentPage/index.tsx +++ b/src/components/Payment/nmi/PaymentPage/index.tsx @@ -19,6 +19,8 @@ import { useNavigate } from "react-router-dom"; import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash"; import { IFunnelPaymentVariant } from "@/api/resources/Session"; import { useFunnel } from "@/hooks/funnel/useFunnel"; +import { getSourceByPathname } from "@/utils/source.utils"; +import { getStateParamForRedirect } from "@/services/url"; const environments = import.meta.env; @@ -197,11 +199,26 @@ function PaymentPage({ "," ); - let redirectUrl = `${paymentUrl}?paywallId=${paywallId}&placementId=${placementId}&productId=${ + // Build base params + const baseParams = `paywallId=${paywallId}&placementId=${placementId}&productId=${ activeProduct?.id }&jwtToken=${token}&price=${( (activeProduct?.trialPrice || 100) / 100 - ).toFixed(2)}¤cy=${currency}&${getTrackingCookiesForRedirect()}`; + ).toFixed(2)}¤cy=${currency}`; + + // Add sessionId + const source = getSourceByPathname(); + const currentSessionId = localStorage.getItem(`${source}_sessionId`); + const sessionParam = currentSessionId ? `&sessionId=${currentSessionId}` : ""; + + // Add state param with current UTM (base64 encoded JSON) + const stateParam = getStateParamForRedirect(); + const stateStr = stateParam ? `&state=${stateParam}` : ""; + + // Add tracking cookies + const trackingCookies = getTrackingCookiesForRedirect(); + + let redirectUrl = `${paymentUrl}?${baseParams}${sessionParam}${stateStr}&${trackingCookies}`; if (fbPixels.length) { redirectUrl += `&fb_pixels=${fbPixels}`; diff --git a/src/services/url/index.ts b/src/services/url/index.ts index 4e3f55a..37cb2b0 100644 --- a/src/services/url/index.ts +++ b/src/services/url/index.ts @@ -13,4 +13,82 @@ export const parseQueryParams = () => { } return result; -} \ No newline at end of file +} + +// Params that should NOT be included in state (they are passed separately) +const EXCLUDED_STATE_PARAMS = [ + "paywallId", + "placementId", + "productId", + "jwtToken", + "price", + "currency", + "fb_pixels", + "sessionId", + "state", + // Tracking cookies (passed separately) + "_fbc", + "_fbp", + "_ym_uid", + "_ym_d", + "_ym_isad", + "_ym_visorc", + "yandexuid", + "ymex", +]; + +/** + * Get current query params that should be passed between screens and to payment + * Includes ALL params except internal ones (productId, placementId, etc.) + * Works with utm_*, fbclid, gclid, and any other marketing params + */ +export const getCurrentQueryParams = (): Record => { + if (typeof window === "undefined") return {}; + + const params = parseQueryParams(); + const utmParams: Record = {}; + + for (const [key, value] of Object.entries(params)) { + const isExcluded = + EXCLUDED_STATE_PARAMS.includes(key) || + key.startsWith("_ga") || + key.startsWith("_gid"); + + if (!isExcluded && value) { + utmParams[key] = value; + } + } + + return utmParams; +}; + +/** + * Encode params as base64 JSON for state parameter + * Uses URL-safe base64 encoding + */ +export const encodeStateParam = (params: Record): string => { + if (Object.keys(params).length === 0) return ""; + + try { + const json = JSON.stringify(params); + // Use btoa for base64, replace unsafe chars for URL + const base64 = btoa(json) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=+$/, ""); + return base64; + } catch { + return ""; + } +}; + +/** + * Get base64-encoded state parameter with current query params + */ +export const getStateParamForRedirect = (): string => { + const params = getCurrentQueryParams(); + return encodeStateParam(params); +}; + +// Backward compatibility alias +export const getCurrentUtmParams = getCurrentQueryParams; \ No newline at end of file