utm
This commit is contained in:
parent
331b9d8547
commit
654e8899a8
@ -18,6 +18,8 @@ import { getFormattedPrice } from "@/shared/utils/price";
|
||||
import { formatPeriod, formatPeriodHyphen } from "@/shared/utils/period";
|
||||
import { useState } from "react";
|
||||
import { getTrackingCookiesForRedirect } from "@/shared/utils/cookies";
|
||||
import { getClientSessionId } from "@/shared/session/sessionId";
|
||||
import { getStateParamForRedirect } from "@/shared/utils/url";
|
||||
|
||||
interface SpecialOfferProps {
|
||||
funnel: FunnelDefinition;
|
||||
@ -70,9 +72,25 @@ export function SpecialOfferTemplate({
|
||||
return;
|
||||
}
|
||||
setIsLoadingRedirect(true);
|
||||
const redirectUrl = `${paymentUrl}?paywallId=${paywallId}&placementId=${placementId}&productId=${productId}&jwtToken=${token}&price=${(
|
||||
|
||||
// Build redirect URL with payment params
|
||||
const baseParams = `paywallId=${paywallId}&placementId=${placementId}&productId=${productId}&jwtToken=${token}&price=${(
|
||||
(trialPrice || 100) / 100
|
||||
).toFixed(2)}¤cy=${currency}&${getTrackingCookiesForRedirect()}`;
|
||||
).toFixed(2)}¤cy=${currency}`;
|
||||
|
||||
// Add sessionId
|
||||
const sessionId = getClientSessionId();
|
||||
const sessionParam = sessionId ? `&sessionId=${sessionId}` : "";
|
||||
|
||||
// Add state param with current UTM (base64 encoded JSON)
|
||||
const stateParam = getStateParamForRedirect();
|
||||
const stateStr = stateParam ? `&state=${stateParam}` : "";
|
||||
|
||||
// Add tracking cookies
|
||||
const trackingCookies = getTrackingCookiesForRedirect();
|
||||
const trackingStr = trackingCookies ? `&${trackingCookies}` : "";
|
||||
|
||||
const redirectUrl = `${paymentUrl}?${baseParams}${sessionParam}${stateStr}${trackingStr}`;
|
||||
return window.location.replace(redirectUrl);
|
||||
};
|
||||
|
||||
|
||||
@ -41,6 +41,8 @@ import { getFormattedPrice } from "@/shared/utils/price";
|
||||
import { useClientToken } from "@/hooks/auth/useClientToken";
|
||||
import { formatPeriod, formatPeriodHyphen } from "@/shared/utils/period";
|
||||
import { getTrackingCookiesForRedirect } from "@/shared/utils/cookies";
|
||||
import { getClientSessionId } from "@/shared/session/sessionId";
|
||||
import { getStateParamForRedirect } from "@/shared/utils/url";
|
||||
|
||||
interface TrialPaymentTemplateProps {
|
||||
funnel: FunnelDefinition;
|
||||
@ -94,9 +96,25 @@ export function TrialPaymentTemplate({
|
||||
return;
|
||||
}
|
||||
setLoadingButtonIndex(buttonIndex);
|
||||
const redirectUrl = `${paymentUrl}?paywallId=${paywallId}&placementId=${placementId}&productId=${productId}&jwtToken=${token}&price=${(
|
||||
|
||||
// Build redirect URL with payment params
|
||||
const baseParams = `paywallId=${paywallId}&placementId=${placementId}&productId=${productId}&jwtToken=${token}&price=${(
|
||||
(trialPrice || 100) / 100
|
||||
).toFixed(2)}¤cy=${currency}&${getTrackingCookiesForRedirect()}`;
|
||||
).toFixed(2)}¤cy=${currency}`;
|
||||
|
||||
// Add sessionId
|
||||
const sessionId = getClientSessionId();
|
||||
const sessionParam = sessionId ? `&sessionId=${sessionId}` : "";
|
||||
|
||||
// Add state param with current UTM (base64 encoded JSON)
|
||||
const stateParam = getStateParamForRedirect();
|
||||
const stateStr = stateParam ? `&state=${stateParam}` : "";
|
||||
|
||||
// Add tracking cookies
|
||||
const trackingCookies = getTrackingCookiesForRedirect();
|
||||
const trackingStr = trackingCookies ? `&${trackingCookies}` : "";
|
||||
|
||||
const redirectUrl = `${paymentUrl}?${baseParams}${sessionParam}${stateStr}${trackingStr}`;
|
||||
return window.location.replace(redirectUrl);
|
||||
};
|
||||
|
||||
|
||||
@ -112,7 +112,7 @@ function trackFacebookPixelEvent(
|
||||
// Map EnteredEmail to Lead for Facebook
|
||||
const fbEvent = event === AnalyticsEvent.ENTERED_EMAIL ? AnalyticsEvent.LEAD : event;
|
||||
|
||||
window.fbq("track", fbEvent, options);
|
||||
window.fbq?.("track", fbEvent, options);
|
||||
console.log(`[FB] Event: ${fbEvent}`, options);
|
||||
}
|
||||
|
||||
|
||||
@ -17,3 +17,81 @@ export const parseQueryParams = () => {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// 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<string, string> => {
|
||||
if (typeof window === "undefined") return {};
|
||||
|
||||
const params = parseQueryParams();
|
||||
const utmParams: Record<string, string> = {};
|
||||
|
||||
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, string>): 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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user