@formo/analytics 1.11.13 → 1.11.14-alpha.2
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/CONTRIBUTING.md +43 -0
- package/README.md +4 -251
- package/dist/cjs/src/FormoAnalytics.d.ts +10 -9
- package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalytics.js +215 -132
- package/dist/cjs/src/FormoAnalytics.js.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.js +53 -37
- package/dist/cjs/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/cjs/src/constants/config.d.ts +0 -1
- package/dist/cjs/src/constants/config.d.ts.map +1 -1
- package/dist/cjs/src/constants/config.js +1 -2
- package/dist/cjs/src/constants/config.js.map +1 -1
- package/dist/cjs/src/types/base.d.ts +1 -1
- package/dist/cjs/src/types/base.d.ts.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/src/FormoAnalytics.d.ts +10 -9
- package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalytics.js +216 -133
- package/dist/esm/src/FormoAnalytics.js.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.js +53 -37
- package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/esm/src/constants/config.d.ts +0 -1
- package/dist/esm/src/constants/config.d.ts.map +1 -1
- package/dist/esm/src/constants/config.js +0 -1
- package/dist/esm/src/constants/config.js.map +1 -1
- package/dist/esm/src/types/base.d.ts +1 -1
- package/dist/esm/src/types/base.d.ts.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/package.json +2 -2
- package/src/FormoAnalytics.ts +169 -123
- package/src/FormoAnalyticsProvider.tsx +36 -30
- package/src/constants/config.ts +0 -1
- package/src/types/base.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formo/analytics",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.14-alpha.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/getformo/sdk.git"
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"sinon-chai": "^3.7.0",
|
|
64
64
|
"ts-loader": "^9.3.1",
|
|
65
65
|
"ts-node": "^10.8.2",
|
|
66
|
-
"typescript": "^5.
|
|
66
|
+
"typescript": "^5.7.2",
|
|
67
67
|
"webpack": "^5.74.0",
|
|
68
68
|
"webpack-cli": "^4.10.0"
|
|
69
69
|
},
|
package/src/FormoAnalytics.ts
CHANGED
|
@@ -2,7 +2,6 @@ import axios from "axios";
|
|
|
2
2
|
import {
|
|
3
3
|
COUNTRY_LIST,
|
|
4
4
|
EVENTS_API_URL,
|
|
5
|
-
SESSION_STORAGE_ID_KEY,
|
|
6
5
|
Event,
|
|
7
6
|
} from "./constants";
|
|
8
7
|
import { H } from "highlight.run";
|
|
@@ -12,7 +11,7 @@ interface IFormoAnalytics {
|
|
|
12
11
|
/**
|
|
13
12
|
* Initializes the FormoAnalytics instance with the provided API key and project ID.
|
|
14
13
|
*/
|
|
15
|
-
init(apiKey: string, options
|
|
14
|
+
init(apiKey: string, options?: Options): Promise<FormoAnalytics>;
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Tracks page visit events.
|
|
@@ -51,7 +50,6 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
51
50
|
|
|
52
51
|
private walletAddressSessionKey = "walletAddress";
|
|
53
52
|
private config: Config;
|
|
54
|
-
private sessionIdKey: string = SESSION_STORAGE_ID_KEY;
|
|
55
53
|
private timezoneToCountry: Record<string, string> = COUNTRY_LIST;
|
|
56
54
|
|
|
57
55
|
currentChainId?: string | null;
|
|
@@ -72,7 +70,10 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
72
70
|
}
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
static async init(
|
|
73
|
+
static async init(
|
|
74
|
+
apiKey: string,
|
|
75
|
+
options?: Options
|
|
76
|
+
): Promise<FormoAnalytics> {
|
|
76
77
|
const config = {
|
|
77
78
|
token: apiKey,
|
|
78
79
|
};
|
|
@@ -86,64 +87,20 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
86
87
|
return this._provider;
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
private getSessionId() {
|
|
90
|
-
const existingSessionId = this.getCookieValue(this.sessionIdKey);
|
|
91
|
-
|
|
92
|
-
if (existingSessionId) {
|
|
93
|
-
return existingSessionId;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const newSessionId = this.generateSessionId();
|
|
97
|
-
return newSessionId;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private getOrigin(): string {
|
|
101
|
-
return window.location.origin || "ORIGIN_NOT_FOUND";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Function to set the session cookie
|
|
105
|
-
private setSessionCookie(): void {
|
|
106
|
-
const sessionId = this.getSessionId();
|
|
107
|
-
let cookieValue = `${
|
|
108
|
-
this.sessionIdKey
|
|
109
|
-
}=${sessionId}; Max-Age=1800; path=/; secure; domain=${this.getOrigin()}`;
|
|
110
|
-
document.cookie = cookieValue;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Function to generate a new session ID
|
|
114
|
-
private generateSessionId(): string {
|
|
115
|
-
return crypto.randomUUID();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Function to get a cookie value by name
|
|
119
|
-
private getCookieValue(name: string): string | undefined {
|
|
120
|
-
const cookies = document.cookie.split(";").reduce((acc, cookie) => {
|
|
121
|
-
const [key, value] = cookie.split("=");
|
|
122
|
-
acc[key.trim()] = value;
|
|
123
|
-
return acc;
|
|
124
|
-
}, {} as Record<string, string>);
|
|
125
|
-
return cookies[name];
|
|
126
|
-
}
|
|
127
90
|
|
|
128
91
|
// Function to send tracking data
|
|
129
92
|
private async trackEvent(action: string, payload: any) {
|
|
130
93
|
const maxRetries = 3;
|
|
131
94
|
let attempt = 0;
|
|
132
95
|
|
|
133
|
-
this.setSessionCookie();
|
|
134
96
|
const address = await this.getCurrentWallet();
|
|
135
97
|
|
|
136
98
|
const requestData = {
|
|
137
99
|
address: address,
|
|
138
|
-
session_id: this.getSessionId(),
|
|
139
100
|
timestamp: new Date().toISOString(),
|
|
140
101
|
action,
|
|
141
102
|
version: "1",
|
|
142
|
-
payload:
|
|
143
|
-
// common fields
|
|
144
|
-
...this.getCommonTrackingFields(),
|
|
145
|
-
...payload,
|
|
146
|
-
},
|
|
103
|
+
payload: await this.buildEventPayload(payload),
|
|
147
104
|
};
|
|
148
105
|
|
|
149
106
|
const sendRequest = async (): Promise<void> => {
|
|
@@ -190,24 +147,71 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
190
147
|
await sendRequest();
|
|
191
148
|
}
|
|
192
149
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
150
|
+
// Function to track page hits
|
|
151
|
+
private trackPageHit() {
|
|
152
|
+
if (this.isAutomationEnvironment()) return;
|
|
153
|
+
|
|
154
|
+
const pathname = window.location.pathname;
|
|
155
|
+
const href = window.location.href;
|
|
156
|
+
|
|
157
|
+
setTimeout(async () => {
|
|
158
|
+
this.trackEvent(Event.PAGE, {
|
|
159
|
+
pathname,
|
|
160
|
+
href,
|
|
161
|
+
});
|
|
162
|
+
}, 300);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private isAutomationEnvironment(): boolean {
|
|
166
|
+
return (
|
|
167
|
+
window.__nightmare ||
|
|
168
|
+
window.navigator.webdriver ||
|
|
169
|
+
window.Cypress ||
|
|
170
|
+
false
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private getUserLocation(): string | undefined {
|
|
196
175
|
try {
|
|
197
176
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
177
|
+
return this.timezoneToCountry[timezone];
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error("Error resolving timezone:", error);
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private getUserLanguage(): string {
|
|
185
|
+
try {
|
|
186
|
+
return (
|
|
187
|
+
(navigator.languages && navigator.languages.length
|
|
201
188
|
? navigator.languages[0]
|
|
202
|
-
: navigator.language || "en"
|
|
189
|
+
: navigator.language) || "en"
|
|
190
|
+
);
|
|
203
191
|
} catch (error) {
|
|
204
|
-
console.error("Error resolving
|
|
192
|
+
console.error("Error resolving language:", error);
|
|
193
|
+
return "en";
|
|
205
194
|
}
|
|
195
|
+
}
|
|
206
196
|
|
|
197
|
+
async buildEventPayload(
|
|
198
|
+
eventSpecificPayload: Record<string, unknown> = {}
|
|
199
|
+
): Promise<Record<string, unknown>> {
|
|
207
200
|
const url = new URL(window.location.href);
|
|
208
201
|
const params = new URLSearchParams(url.search);
|
|
202
|
+
|
|
203
|
+
const location = this.getUserLocation();
|
|
204
|
+
const language = this.getUserLanguage();
|
|
205
|
+
|
|
206
|
+
const address = await this.getAndStoreConnectedAddress();
|
|
207
|
+
if (address === null) {
|
|
208
|
+
console.warn("Wallet address could not be retrieved.");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// common fields
|
|
209
212
|
return {
|
|
210
213
|
"user-agent": window.navigator.userAgent,
|
|
214
|
+
address,
|
|
211
215
|
locale: language,
|
|
212
216
|
location,
|
|
213
217
|
referrer: document.referrer,
|
|
@@ -215,24 +219,13 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
215
219
|
utm_medium: params.get("utm_medium"),
|
|
216
220
|
utm_campaign: params.get("utm_campaign"),
|
|
217
221
|
ref: params.get("ref"),
|
|
222
|
+
...eventSpecificPayload,
|
|
218
223
|
};
|
|
219
224
|
}
|
|
220
225
|
|
|
221
|
-
// Function to track page hits
|
|
222
|
-
private trackPageHit() {
|
|
223
|
-
if (window.__nightmare || window.navigator.webdriver || window.Cypress)
|
|
224
|
-
return;
|
|
225
|
-
|
|
226
|
-
setTimeout(() => {
|
|
227
|
-
this.trackEvent(Event.PAGE, {
|
|
228
|
-
pathname: window.location.pathname,
|
|
229
|
-
href: window.location.href,
|
|
230
|
-
});
|
|
231
|
-
}, 300);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
226
|
private trackProvider(provider: EIP1193Provider) {
|
|
235
227
|
if (provider === this._provider) {
|
|
228
|
+
console.log("Provider already tracked.");
|
|
236
229
|
return;
|
|
237
230
|
}
|
|
238
231
|
|
|
@@ -250,6 +243,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
250
243
|
}
|
|
251
244
|
}
|
|
252
245
|
|
|
246
|
+
console.log("Tracking new provider:", provider);
|
|
253
247
|
this._provider = provider;
|
|
254
248
|
|
|
255
249
|
this.getCurrentWallet();
|
|
@@ -257,14 +251,33 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
257
251
|
this.registerChainChangedListener();
|
|
258
252
|
}
|
|
259
253
|
|
|
254
|
+
private async getAndStoreConnectedAddress(): Promise<string | null> {
|
|
255
|
+
console.log(
|
|
256
|
+
"Session data missing. Attempting to fetch address from provider."
|
|
257
|
+
);
|
|
258
|
+
try {
|
|
259
|
+
const accounts = await this.fetchAccounts();
|
|
260
|
+
if (accounts && accounts.length > 0) {
|
|
261
|
+
const address = accounts[0];
|
|
262
|
+
this.storeWalletAddress(address);
|
|
263
|
+
return address;
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.log("Failed to fetch accounts from provider:", err);
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
|
|
260
271
|
private async getCurrentWallet() {
|
|
261
272
|
if (!this.provider) {
|
|
262
273
|
console.warn("FormoAnalytics::getCurrentWallet: the provider is not set");
|
|
263
274
|
return;
|
|
264
275
|
}
|
|
276
|
+
|
|
265
277
|
const sessionData = sessionStorage.getItem(this.walletAddressSessionKey);
|
|
278
|
+
|
|
266
279
|
if (!sessionData) {
|
|
267
|
-
return
|
|
280
|
+
return await this.getAndStoreConnectedAddress();
|
|
268
281
|
}
|
|
269
282
|
|
|
270
283
|
const parsedData = JSON.parse(sessionData);
|
|
@@ -272,7 +285,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
272
285
|
const currentTime = Date.now();
|
|
273
286
|
|
|
274
287
|
if (currentTime - parsedData.timestamp > sessionExpiry) {
|
|
275
|
-
console.
|
|
288
|
+
console.log("Session expired. Ignoring wallet address.");
|
|
276
289
|
sessionStorage.removeItem(this.walletAddressSessionKey); // Clear expired session data
|
|
277
290
|
return "";
|
|
278
291
|
}
|
|
@@ -281,16 +294,61 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
281
294
|
return parsedData.address || "";
|
|
282
295
|
}
|
|
283
296
|
|
|
297
|
+
// Utility to fetch accounts
|
|
298
|
+
private async fetchAccounts(): Promise<string[] | null> {
|
|
299
|
+
try {
|
|
300
|
+
const res: string[] | null | undefined = await this.provider?.request({
|
|
301
|
+
method: "eth_accounts",
|
|
302
|
+
});
|
|
303
|
+
if (!res || res.length === 0) {
|
|
304
|
+
console.log(
|
|
305
|
+
"FormoAnalytics::fetchAccounts: unable to get account. eth_accounts returned empty"
|
|
306
|
+
);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
return res;
|
|
310
|
+
} catch (err) {
|
|
311
|
+
if ((err as any).code !== 4001) {
|
|
312
|
+
console.log(
|
|
313
|
+
"FormoAnalytics::fetchAccounts: eth_accounts threw an error",
|
|
314
|
+
err
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Utility to fetch chain ID
|
|
322
|
+
private async fetchChainId(): Promise<string | null> {
|
|
323
|
+
try {
|
|
324
|
+
const chainIdHex = await this.provider?.request<string>({
|
|
325
|
+
method: "eth_chainId",
|
|
326
|
+
});
|
|
327
|
+
if (!chainIdHex) {
|
|
328
|
+
console.log(
|
|
329
|
+
"FormoAnalytics::fetchChainId: chainIdHex is null or undefined"
|
|
330
|
+
);
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
return chainIdHex;
|
|
334
|
+
} catch (err) {
|
|
335
|
+
console.log(
|
|
336
|
+
"FormoAnalytics::fetchChainId: eth_chainId threw an error",
|
|
337
|
+
err
|
|
338
|
+
);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
284
343
|
private async getCurrentChainId(): Promise<string> {
|
|
285
344
|
if (!this.provider) {
|
|
286
|
-
console.
|
|
345
|
+
console.log("FormoAnalytics::getCurrentChainId: provider not set");
|
|
287
346
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
});
|
|
347
|
+
|
|
348
|
+
const chainIdHex = await this.fetchChainId();
|
|
291
349
|
// Because we're connected, the chainId cannot be null
|
|
292
350
|
if (!chainIdHex) {
|
|
293
|
-
console.
|
|
351
|
+
console.log(
|
|
294
352
|
`FormoAnalytics::getCurrentChainId: chainIdHex is: ${chainIdHex}`
|
|
295
353
|
);
|
|
296
354
|
}
|
|
@@ -342,64 +400,60 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
342
400
|
this.storeWalletAddress(address);
|
|
343
401
|
}
|
|
344
402
|
|
|
345
|
-
private
|
|
346
|
-
if (!
|
|
403
|
+
private handleDisconnection(chainId?: string, address?: string) {
|
|
404
|
+
if (!address) {
|
|
347
405
|
return;
|
|
348
406
|
}
|
|
349
|
-
|
|
350
407
|
const payload = {
|
|
351
|
-
chain_id: this.currentChainId,
|
|
352
|
-
address
|
|
408
|
+
chain_id: chainId || this.currentChainId,
|
|
409
|
+
address,
|
|
353
410
|
};
|
|
354
411
|
this.currentChainId = undefined;
|
|
355
412
|
this.currentConnectedAddress = undefined;
|
|
356
413
|
this.clearWalletAddress();
|
|
357
|
-
|
|
358
414
|
return this.trackEvent(Event.DISCONNECT, payload);
|
|
359
415
|
}
|
|
360
416
|
|
|
417
|
+
private onAddressDisconnected() {
|
|
418
|
+
if (!this.currentConnectedAddress) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.handleDisconnection(this.currentChainId || undefined, this.currentConnectedAddress);
|
|
422
|
+
}
|
|
423
|
+
|
|
361
424
|
private async onChainChanged(chainIdHex: string) {
|
|
362
425
|
this.currentChainId = parseInt(chainIdHex).toString();
|
|
363
426
|
if (!this.currentConnectedAddress) {
|
|
364
427
|
if (!this.provider) {
|
|
365
|
-
console.
|
|
366
|
-
"error",
|
|
428
|
+
console.log(
|
|
367
429
|
"FormoAnalytics::onChainChanged: provider not found. CHAIN_CHANGED not reported"
|
|
368
430
|
);
|
|
369
431
|
return;
|
|
370
432
|
}
|
|
371
433
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
"FormoAnalytics::onChainChanged: unable to get account. eth_accounts returned empty"
|
|
380
|
-
);
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
this.currentConnectedAddress = res[0];
|
|
385
|
-
} catch (err) {
|
|
386
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
387
|
-
if ((err as any).code !== 4001) {
|
|
388
|
-
// 4001: The request is rejected by the user , see https://docs.metamask.io/wallet/reference/provider-api/#errors
|
|
389
|
-
console.error(
|
|
390
|
-
"error",
|
|
391
|
-
`FormoAnalytics::onChainChanged: unable to get account. eth_accounts threw an error`,
|
|
392
|
-
err
|
|
393
|
-
);
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
434
|
+
// Attempt to fetch and store the connected address
|
|
435
|
+
const address = await this.getAndStoreConnectedAddress();
|
|
436
|
+
if (!address) {
|
|
437
|
+
console.log(
|
|
438
|
+
"FormoAnalytics::onChainChanged: Unable to fetch or store connected address"
|
|
439
|
+
);
|
|
440
|
+
return;
|
|
396
441
|
}
|
|
442
|
+
|
|
443
|
+
this.currentConnectedAddress = address[0];
|
|
397
444
|
}
|
|
398
445
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
446
|
+
// Proceed only if the address exists
|
|
447
|
+
if (this.currentConnectedAddress) {
|
|
448
|
+
return this.chain({
|
|
449
|
+
chainId: this.currentChainId,
|
|
450
|
+
address: this.currentConnectedAddress,
|
|
451
|
+
});
|
|
452
|
+
} else {
|
|
453
|
+
console.log(
|
|
454
|
+
"FormoAnalytics::onChainChanged: currentConnectedAddress is null despite fetch attempt"
|
|
455
|
+
);
|
|
456
|
+
}
|
|
403
457
|
}
|
|
404
458
|
|
|
405
459
|
/**
|
|
@@ -408,7 +462,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
408
462
|
*/
|
|
409
463
|
private storeWalletAddress(address: string): void {
|
|
410
464
|
if (!address) {
|
|
411
|
-
console.
|
|
465
|
+
console.log("No wallet address provided to store.");
|
|
412
466
|
return;
|
|
413
467
|
}
|
|
414
468
|
|
|
@@ -459,15 +513,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
459
513
|
// `disconnect` detection
|
|
460
514
|
return;
|
|
461
515
|
}
|
|
462
|
-
|
|
463
|
-
const payload = {
|
|
464
|
-
chain_id: params?.chainId || this.currentChainId,
|
|
465
|
-
address,
|
|
466
|
-
};
|
|
467
|
-
this.currentChainId = undefined;
|
|
468
|
-
this.currentConnectedAddress = undefined;
|
|
469
|
-
|
|
470
|
-
return this.trackEvent(Event.DISCONNECT, payload);
|
|
516
|
+
return this.handleDisconnection((params?.chainId?.toString() || this.currentChainId) as string, address);
|
|
471
517
|
}
|
|
472
518
|
|
|
473
519
|
chain({ chainId, address }: { chainId: ChainID; address?: string }) {
|
|
@@ -26,6 +26,40 @@ export const FormoAnalyticsProvider = ({
|
|
|
26
26
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
27
27
|
const initializedStartedRef = useRef(false);
|
|
28
28
|
|
|
29
|
+
const initializeHighlight = async () => {
|
|
30
|
+
if (HIGHLIGHT_PROJECT_ID) {
|
|
31
|
+
try {
|
|
32
|
+
H.init(HIGHLIGHT_PROJECT_ID, {
|
|
33
|
+
serviceName: 'formo-analytics-sdk',
|
|
34
|
+
tracingOrigins: true,
|
|
35
|
+
networkRecording: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
recordHeadersAndBody: true,
|
|
38
|
+
urlBlocklist: [
|
|
39
|
+
'https://www.googleapis.com/identitytoolkit',
|
|
40
|
+
'https://securetoken.googleapis.com',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
console.log('Highlight.run initialized successfully');
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Failed to initialize Highlight.run', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const initializeFormoAnalytics = async (apiKey: string, options: any) => {
|
|
52
|
+
try {
|
|
53
|
+
const sdkInstance = await FormoAnalytics.init(apiKey, options);
|
|
54
|
+
setSdk(sdkInstance);
|
|
55
|
+
console.log('FormoAnalytics SDK initialized successfully');
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Failed to initialize FormoAnalytics SDK', error);
|
|
58
|
+
} finally {
|
|
59
|
+
setIsInitialized(true); // Ensure UI renders even after failure
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
29
63
|
useEffect(() => {
|
|
30
64
|
const initialize = async () => {
|
|
31
65
|
if (!apiKey) {
|
|
@@ -38,37 +72,9 @@ export const FormoAnalyticsProvider = ({
|
|
|
38
72
|
}
|
|
39
73
|
if (initializedStartedRef.current) return;
|
|
40
74
|
initializedStartedRef.current = true;
|
|
41
|
-
// Initialize Highlight.run if project ID is available
|
|
42
|
-
if (HIGHLIGHT_PROJECT_ID) {
|
|
43
|
-
try {
|
|
44
|
-
H.init(HIGHLIGHT_PROJECT_ID, {
|
|
45
|
-
serviceName: 'formo-analytics-sdk',
|
|
46
|
-
tracingOrigins: true,
|
|
47
|
-
networkRecording: {
|
|
48
|
-
enabled: true,
|
|
49
|
-
recordHeadersAndBody: true,
|
|
50
|
-
urlBlocklist: [
|
|
51
|
-
'https://www.googleapis.com/identitytoolkit',
|
|
52
|
-
'https://securetoken.googleapis.com',
|
|
53
|
-
],
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
console.log('Highlight.run initialized successfully');
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('Failed to initialize Highlight.run', error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const sdkInstance = await FormoAnalytics.init(apiKey, options);
|
|
65
|
-
setSdk(sdkInstance);
|
|
66
|
-
console.log('FormoAnalytics SDK initialized successfully');
|
|
67
|
-
} catch (error) {
|
|
68
|
-
console.error('Failed to initialize FormoAnalytics SDK', error);
|
|
69
|
-
} finally {
|
|
70
|
-
setIsInitialized(true); // Ensure UI renders even after failure
|
|
71
|
-
}
|
|
76
|
+
await initializeHighlight();
|
|
77
|
+
await initializeFormoAnalytics(apiKey, options);
|
|
72
78
|
};
|
|
73
79
|
|
|
74
80
|
initialize();
|
package/src/constants/config.ts
CHANGED