@phygitallabs/tapquest-core 6.7.9 → 6.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/data-tracking/GtagConsentSync.tsx +10 -2
- package/src/modules/data-tracking/hooks/index.ts +69 -67
- package/src/modules/data-tracking/index.ts +1 -1
- package/src/providers/ServicesProvider.tsx +131 -132
package/package.json
CHANGED
|
@@ -9,9 +9,12 @@ type GtagConsent = (
|
|
|
9
9
|
params: Record<string, string>
|
|
10
10
|
) => void;
|
|
11
11
|
|
|
12
|
+
/** Consent Mode v2: block analytics and ad tags until user accepts. */
|
|
12
13
|
const GTAG_CONSENT_DENIED = {
|
|
13
14
|
analytics_storage: "denied",
|
|
14
15
|
ad_storage: "denied",
|
|
16
|
+
ad_user_data: "denied",
|
|
17
|
+
ad_personalization: "denied",
|
|
15
18
|
} as const;
|
|
16
19
|
|
|
17
20
|
const GTAG_CONSENT_GRANTED_ANALYTICS = {
|
|
@@ -19,13 +22,18 @@ const GTAG_CONSENT_GRANTED_ANALYTICS = {
|
|
|
19
22
|
} as const;
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
|
-
* Sets gtag consent default to denied on mount and updates to granted
|
|
25
|
+
* Sets gtag/GTM consent default to denied on mount and updates to granted
|
|
23
26
|
* when user has accepted analytics (must be under PhygitalConsentProvider).
|
|
27
|
+
*
|
|
28
|
+
* When using GTM: add the script from getGtmConsentDefaultSnippet() in your
|
|
29
|
+
* HTML before the GTM container script (gtm.js) so consent is denied before
|
|
30
|
+
* any tags run. This component then pushes consent update when the user accepts.
|
|
24
31
|
* Renders nothing.
|
|
25
32
|
*/
|
|
26
33
|
export function GtagConsentSync() {
|
|
27
34
|
const consent = usePhygitalConsent();
|
|
28
|
-
const isAnalyticsAllowed =
|
|
35
|
+
const isAnalyticsAllowed =
|
|
36
|
+
(consent as { isAnalyticsAllowed?: boolean }).isAnalyticsAllowed ?? false;
|
|
29
37
|
|
|
30
38
|
useEffect(() => {
|
|
31
39
|
if (typeof window === "undefined") return;
|
|
@@ -3,93 +3,95 @@ import posthog from "posthog-js";
|
|
|
3
3
|
import { useSessionReplay } from "../../../modules/session-replay";
|
|
4
4
|
|
|
5
5
|
declare global {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
interface Window {
|
|
7
|
+
dataLayer: unknown[];
|
|
8
|
+
}
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
declare function gtag(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
command: "event",
|
|
13
|
+
eventName: string,
|
|
14
|
+
eventParameters: Record<string, any>
|
|
15
15
|
): void;
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
// GTM
|
|
19
18
|
const pushEventToDataLayer = (event: string, data: Record<string, any>) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
19
|
+
try {
|
|
20
|
+
window.dataLayer = window.dataLayer || [];
|
|
21
|
+
|
|
22
|
+
(window.dataLayer as Record<string, unknown>[]).push({
|
|
23
|
+
event,
|
|
24
|
+
...data,
|
|
25
|
+
});
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(error);
|
|
28
|
+
}
|
|
31
29
|
};
|
|
32
30
|
|
|
33
31
|
// GA
|
|
34
32
|
const pushEventToGA = (eventName: string, eventData: Record<string, any>) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
if (typeof gtag != "function") {
|
|
34
|
+
console.error("gtag is not a function");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
gtag("event", eventName, eventData);
|
|
40
38
|
};
|
|
41
39
|
|
|
42
40
|
// Posthog
|
|
43
41
|
const pushEventToPosthog = (eventName: string, eventData: Record<string, any>) => {
|
|
44
|
-
|
|
42
|
+
posthog.capture(eventName, eventData);
|
|
45
43
|
};
|
|
46
44
|
|
|
47
45
|
function useDataTracking() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const trackEvent = (eventName: string, eventData: Record<string, any>, useTools?: ("gtm" | "ga" | "posthog")[]) => {
|
|
53
|
-
console.log("trackEvent ", eventName, eventData);
|
|
54
|
-
|
|
55
|
-
useTools = useTools || ["gtm"];
|
|
56
|
-
|
|
57
|
-
if (useTools.includes("gtm") && typeof window !== "undefined") {
|
|
58
|
-
pushEventToDataLayer(eventName, eventData);
|
|
59
|
-
}
|
|
60
|
-
if (useTools.includes("ga") && isAnalyticsAllowed && typeof gtag == "function") {
|
|
61
|
-
pushEventToGA(eventName, eventData);
|
|
62
|
-
}
|
|
63
|
-
if (useTools.includes("posthog") && typeof posthog == "function") {
|
|
64
|
-
pushEventToPosthog(eventName, eventData);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const trackUserIdentify = (userInfo: Record<string, any>) => {
|
|
69
|
-
posthog.identify(userInfo.email, {
|
|
70
|
-
email: userInfo.email,
|
|
71
|
-
name: userInfo.name,
|
|
72
|
-
avatar: userInfo.avatar,
|
|
73
|
-
uid: userInfo.uid,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
setUserId(userInfo.id);
|
|
77
|
-
|
|
78
|
-
setMetadata({
|
|
79
|
-
user_email: userInfo.email
|
|
80
|
-
})
|
|
81
|
-
}
|
|
46
|
+
const { setUserId, setMetadata } = useSessionReplay();
|
|
47
|
+
const consent = usePhygitalConsent();
|
|
48
|
+
const isAnalyticsAllowed =
|
|
49
|
+
(consent as { isAnalyticsAllowed?: boolean }).isAnalyticsAllowed ?? false;
|
|
82
50
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
51
|
+
const trackEvent = (
|
|
52
|
+
eventName: string,
|
|
53
|
+
eventData: Record<string, any>,
|
|
54
|
+
useTools?: ("gtm" | "ga" | "posthog")[]
|
|
55
|
+
) => {
|
|
56
|
+
console.log("trackEvent ", eventName, eventData);
|
|
86
57
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
58
|
+
useTools = useTools || ["gtm"];
|
|
59
|
+
|
|
60
|
+
if (useTools.includes("gtm") && typeof window !== "undefined") {
|
|
61
|
+
pushEventToDataLayer(eventName, eventData);
|
|
62
|
+
}
|
|
63
|
+
if (useTools.includes("ga") && isAnalyticsAllowed && typeof gtag == "function") {
|
|
64
|
+
pushEventToGA(eventName, eventData);
|
|
65
|
+
}
|
|
66
|
+
if (useTools.includes("posthog") && typeof posthog == "function") {
|
|
67
|
+
pushEventToPosthog(eventName, eventData);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const trackUserIdentify = (userInfo: Record<string, any>) => {
|
|
72
|
+
posthog.identify(userInfo.email, {
|
|
73
|
+
email: userInfo.email,
|
|
74
|
+
name: userInfo.name,
|
|
75
|
+
avatar: userInfo.avatar,
|
|
76
|
+
uid: userInfo.uid,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
setUserId(userInfo.id);
|
|
80
|
+
|
|
81
|
+
setMetadata({
|
|
82
|
+
user_email: userInfo.email,
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const trackLogoutEvent = () => {
|
|
87
|
+
posthog.capture("user_signed_out");
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
trackEvent,
|
|
92
|
+
trackUserIdentify,
|
|
93
|
+
trackLogoutEvent,
|
|
94
|
+
};
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
export { useDataTracking };
|
|
95
|
-
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./GtagConsentSync";
|
|
2
|
-
export * from "./hooks";
|
|
2
|
+
export * from "./hooks";
|
|
@@ -21,143 +21,142 @@ import { tokenStorage } from "@phygitallabs/authentication";
|
|
|
21
21
|
import axios from "axios";
|
|
22
22
|
|
|
23
23
|
interface ServicesProviderProps {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
queryClient: QueryClient;
|
|
26
|
+
apiConfig: APIConfig;
|
|
27
|
+
firebaseConfig?: any;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const ServicesProvider: React.FC<ServicesProviderProps> = ({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
children,
|
|
32
|
+
queryClient,
|
|
33
|
+
apiConfig = {
|
|
34
|
+
environment: "dev",
|
|
35
|
+
version: "v1",
|
|
36
|
+
},
|
|
37
37
|
}) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
const requestInterceptors = ({
|
|
93
|
-
onFulfilled: (config: any) => config,
|
|
94
|
-
onRejected: (error: any) => Promise.reject(error),
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
const axiosConfig = {
|
|
98
|
-
headers: {
|
|
99
|
-
"Content-Type": "application/json",
|
|
100
|
-
"Device-UID": deviceUid,
|
|
101
|
-
}
|
|
38
|
+
const { signOut, refreshToken } = useAuth();
|
|
39
|
+
const { environment, version } = apiConfig;
|
|
40
|
+
const [commonServiceConfig, setCommonServiceConfig] = useState<ServiceConfig | null>(null);
|
|
41
|
+
|
|
42
|
+
const [deviceUid, setDeviceUid] = useState<string>("");
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const initDeviceUid = async () => {
|
|
46
|
+
const deviceUid = await checkDeviceUid();
|
|
47
|
+
setDeviceUid(deviceUid);
|
|
48
|
+
};
|
|
49
|
+
initDeviceUid();
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
// Init client
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const initClient = async () => {
|
|
55
|
+
try {
|
|
56
|
+
const deviceUid = await checkDeviceUid();
|
|
57
|
+
|
|
58
|
+
const responseInterceptors = {
|
|
59
|
+
onFulfilled: (response: any) => response,
|
|
60
|
+
onRejected: async (error: any) => {
|
|
61
|
+
const originalRequest = error.config;
|
|
62
|
+
const token = tokenStorage.getAuthToken();
|
|
63
|
+
|
|
64
|
+
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
65
|
+
const retryAttempts = parseInt(getFromLS(retryAttemptsRefreshToken) || "0", 10);
|
|
66
|
+
if (retryAttempts >= httpMaxRetries) {
|
|
67
|
+
await signOut();
|
|
68
|
+
setToLS(retryAttemptsRefreshToken, 0);
|
|
69
|
+
return Promise.reject(error);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setToLS(retryAttemptsRefreshToken, `${retryAttempts + 1}`);
|
|
73
|
+
originalRequest._retry = true;
|
|
74
|
+
|
|
75
|
+
if (token) {
|
|
76
|
+
try {
|
|
77
|
+
const result = await refreshToken();
|
|
78
|
+
if (result?.data?.idToken) {
|
|
79
|
+
originalRequest.headers.Authorization = `Bearer ${result?.data?.idToken}`;
|
|
80
|
+
return axios(originalRequest);
|
|
81
|
+
}
|
|
82
|
+
} catch (refreshError) {
|
|
83
|
+
console.error("Failed to refresh token:", refreshError);
|
|
84
|
+
await signOut();
|
|
85
|
+
return Promise.reject(refreshError);
|
|
102
86
|
}
|
|
103
|
-
|
|
104
|
-
const config: ServiceConfig = {
|
|
105
|
-
queryClient,
|
|
106
|
-
axiosConfig,
|
|
107
|
-
responseInterceptors,
|
|
108
|
-
requestInterceptors,
|
|
109
|
-
useDevTool: true,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
setCommonServiceConfig(config);
|
|
113
|
-
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error(error);
|
|
87
|
+
}
|
|
116
88
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const requestInterceptors = {
|
|
93
|
+
onFulfilled: (config: any) => config,
|
|
94
|
+
onRejected: (error: any) => Promise.reject(error),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const axiosConfig = {
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"Device-UID": deviceUid,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const config: ServiceConfig = {
|
|
105
|
+
queryClient,
|
|
106
|
+
axiosConfig,
|
|
107
|
+
responseInterceptors,
|
|
108
|
+
requestInterceptors,
|
|
109
|
+
useDevTool: true,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
setCommonServiceConfig(config);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(error);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
initClient();
|
|
119
|
+
}, [queryClient]);
|
|
120
|
+
|
|
121
|
+
if (!commonServiceConfig) {
|
|
122
|
+
return <></>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<PGLCoreServiceProvider
|
|
127
|
+
{...commonServiceConfig}
|
|
128
|
+
baseURL={`${serviceApiUrl[environment].API_BASE_URL}/${version}`}
|
|
129
|
+
baseCoreURL={`${serviceApiUrl[environment].API_BASE_CORE_URL}/${version}`}
|
|
130
|
+
>
|
|
131
|
+
<RewardServiceProvider
|
|
132
|
+
{...commonServiceConfig}
|
|
133
|
+
// baseURL={`${serviceApiUrl[environment].API_REWARD_URL}/${version}`}
|
|
134
|
+
baseURL={`${serviceApiUrl[environment].API_REWARD_URL}/v1`} // todo: using v1 until backend fully migrate
|
|
135
|
+
>
|
|
136
|
+
<AchievementServiceProvider
|
|
137
|
+
{...commonServiceConfig}
|
|
138
|
+
baseURL={`${serviceApiUrl[environment].API_ACHIEVEMENT_URL}/${version}`}
|
|
131
139
|
>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
<GenerateCertificateServiceProvider
|
|
141
|
+
{...commonServiceConfig}
|
|
142
|
+
baseURL={`${serviceApiUrl[environment].API_GENERATE_CERTIFICATE_URL}/v1`}
|
|
143
|
+
>
|
|
144
|
+
<PhygitalConsentProvider
|
|
145
|
+
{...commonServiceConfig}
|
|
146
|
+
deviceId={deviceUid}
|
|
147
|
+
baseURL={`${serviceApiUrl[environment].API_CONSENT_URL}/v1`}
|
|
148
|
+
axiosConfig={{
|
|
149
|
+
headers: {
|
|
150
|
+
"Content-Type": "application/json",
|
|
151
|
+
},
|
|
152
|
+
}}
|
|
136
153
|
>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
{...commonServiceConfig}
|
|
147
|
-
deviceId={deviceUid}
|
|
148
|
-
baseURL={`${serviceApiUrl[environment].API_CONSENT_URL}/v1`}
|
|
149
|
-
axiosConfig={{
|
|
150
|
-
headers: {
|
|
151
|
-
"Content-Type": "application/json",
|
|
152
|
-
}
|
|
153
|
-
}}
|
|
154
|
-
>
|
|
155
|
-
<GtagConsentSync />
|
|
156
|
-
{children}
|
|
157
|
-
</PhygitalConsentProvider>
|
|
158
|
-
</GenerateCertificateServiceProvider>
|
|
159
|
-
</AchievementServiceProvider>
|
|
160
|
-
</RewardServiceProvider>
|
|
161
|
-
</PGLCoreServiceProvider>
|
|
162
|
-
);
|
|
163
|
-
};
|
|
154
|
+
<GtagConsentSync />
|
|
155
|
+
{children}
|
|
156
|
+
</PhygitalConsentProvider>
|
|
157
|
+
</GenerateCertificateServiceProvider>
|
|
158
|
+
</AchievementServiceProvider>
|
|
159
|
+
</RewardServiceProvider>
|
|
160
|
+
</PGLCoreServiceProvider>
|
|
161
|
+
);
|
|
162
|
+
};
|