Skip to content

Commit efbde4f

Browse files
committed
Fix UTM & network in redux
1 parent c6b4c99 commit efbde4f

4 files changed

Lines changed: 42 additions & 7 deletions

File tree

api/app/routes/users/auth.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
The authorization method of the user object of the API
33
"""
44

5+
import time
6+
57
import jwt
68
from fastapi import APIRouter, Body, Request
79
from fastapi.responses import JSONResponse
@@ -54,6 +56,7 @@ def get_user(global_user, **kwargs):
5456
async def update_utm(user, global_user, utm):
5557
if not utm:
5658
return user, None, None
59+
log.info(f"UTM #{utm} for {user.id}")
5760

5861
try:
5962
referrer_id = decrypt(utm)
@@ -91,7 +94,11 @@ async def update_utm(user, global_user, utm):
9194
if referrer.id == user.id:
9295
return user, None, None
9396

94-
if user.referrer is None:
97+
if (
98+
user.referrer is None
99+
and not user.frens # friend link
100+
and time.time() - user.created > 3600 # old user – no referrer
101+
):
95102
user.referrer = referrer.id
96103

97104
if referrer.id not in user.frens:

web/src/features/auth/components/VkAuthInitializer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useToastActions } from '@/shared/hooks/useToast';
66
import { useApiErrorMessage } from '@/shared/hooks/useApiErrorMessage';
77
import { useAppDispatch, useAppSelector } from '@/shared/stores/store';
88
import { isVkMiniApp } from '@/shared/lib/vk';
9+
import { getUtmFromSearchParams } from '@/shared/lib/utm';
910
import { loginWithVkApp, selectAuthUser } from '../stores/authSlice';
1011

1112
type VkUserInfo = {
@@ -19,7 +20,7 @@ type VkUserInfo = {
1920
const getVkUtm = () => {
2021
if (typeof window === 'undefined') return null;
2122
const params = new URLSearchParams(window.location.search);
22-
return params.get('utm') || params.get('vk_ref') || null;
23+
return getUtmFromSearchParams(params);
2324
};
2425

2526
const getVkEmail = () => {
@@ -81,6 +82,8 @@ export default function VkAuthInitializer() {
8182
const image = userInfo?.photo_200_orig || userInfo?.photo_200 || userInfo?.photo_100 || null;
8283
const mail = getVkEmail();
8384

85+
console.log(`VK UTM #${resolvedUtm}`, userInfo);
86+
8487
return dispatch(
8588
loginWithVkApp({
8689
url,

web/src/features/session/components/SessionInitializer.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,32 @@ import { useToastActions } from '@/shared/hooks/useToast';
77
import { useAppDispatch, useAppSelector } from '@/shared/stores/store';
88
import { STORAGE_KEYS } from '@/shared/constants';
99
import { syncAuthCookie } from '@/shared/lib/auth';
10-
import { initializeSession, setUtm } from '../stores/sessionSlice';
10+
import { getClientNetwork } from '@/shared/lib/app';
11+
import { getUtmFromSearchParams } from '@/shared/lib/utm';
12+
import { initializeSession, setNetwork, setUtm } from '../stores/sessionSlice';
1113

1214
export default function SessionInitializer() {
1315
const dispatch = useAppDispatch();
1416
const searchParams = useSearchParams();
1517
const t = useTranslations('session');
16-
const { status } = useAppSelector((state) => state.session);
18+
const { status, network: storedNetwork, utm: storedUtm } = useAppSelector((state) => state.session);
1719
const authToken = useAppSelector((state) => state.session.authToken);
1820
const { error: showError } = useToastActions();
1921

20-
const utmParam = useMemo(() => searchParams?.get('utm') || searchParams?.get('vk_ref') || null, [searchParams]);
22+
const utmParam = useMemo(() => getUtmFromSearchParams(searchParams), [searchParams]);
2123

2224
useEffect(() => {
23-
if (utmParam) {
25+
if (storedUtm !== utmParam) {
2426
dispatch(setUtm(utmParam));
2527
}
26-
}, [dispatch, utmParam]);
28+
}, [dispatch, storedUtm, utmParam]);
29+
30+
useEffect(() => {
31+
const resolvedNetwork = getClientNetwork();
32+
if (storedNetwork !== resolvedNetwork) {
33+
dispatch(setNetwork(resolvedNetwork));
34+
}
35+
}, [dispatch, storedNetwork]);
2736

2837
useEffect(() => {
2938
if (status === 'loading') {

web/src/shared/lib/utm.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
type SearchParamsLike = {
2+
get: (key: string) => string | null;
3+
};
4+
5+
export const normalizeUtm = (value?: string | null): string | null => {
6+
if (!value) return null;
7+
const trimmed = value.trim();
8+
if (!trimmed) return null;
9+
if (trimmed.toLowerCase() === 'other') return null;
10+
return trimmed;
11+
};
12+
13+
export const getUtmFromSearchParams = (params?: SearchParamsLike | null): string | null => {
14+
if (!params) return null;
15+
return normalizeUtm(params.get('utm') || params.get('vk_ref'));
16+
};

0 commit comments

Comments
 (0)