@formo/analytics 1.11.8 → 1.11.9

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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/dist/223.index.umd.min.js +125 -0
  3. package/dist/223.index.umd.min.js.map +1 -0
  4. package/dist/cjs/src/FormoAnalytics.d.ts +27 -33
  5. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  6. package/dist/cjs/src/FormoAnalytics.js +162 -208
  7. package/dist/cjs/src/FormoAnalytics.js.map +1 -1
  8. package/dist/cjs/src/FormoAnalyticsProvider.d.ts +1 -1
  9. package/dist/cjs/src/FormoAnalyticsProvider.d.ts.map +1 -1
  10. package/dist/cjs/src/FormoAnalyticsProvider.js +2 -2
  11. package/dist/cjs/src/FormoAnalyticsProvider.js.map +1 -1
  12. package/dist/cjs/src/types/base.d.ts +2 -1
  13. package/dist/cjs/src/types/base.d.ts.map +1 -1
  14. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  15. package/dist/esm/src/FormoAnalytics.d.ts +27 -33
  16. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  17. package/dist/esm/src/FormoAnalytics.js +162 -208
  18. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  19. package/dist/esm/src/FormoAnalyticsProvider.d.ts +1 -1
  20. package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
  21. package/dist/esm/src/FormoAnalyticsProvider.js +2 -2
  22. package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
  23. package/dist/esm/src/types/base.d.ts +2 -1
  24. package/dist/esm/src/types/base.d.ts.map +1 -1
  25. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  26. package/dist/index.umd.min.js +1 -1
  27. package/dist/index.umd.min.js.map +1 -1
  28. package/package.json +2 -2
  29. package/src/FormoAnalytics.ts +172 -222
  30. package/src/FormoAnalyticsProvider.tsx +2 -4
  31. package/src/types/base.ts +2 -1
  32. package/dist/387.index.umd.min.js +0 -125
  33. package/dist/387.index.umd.min.js.map +0 -1
  34. package/dist/cjs/src/utils/index.d.ts +0 -2
  35. package/dist/cjs/src/utils/index.d.ts.map +0 -1
  36. package/dist/cjs/src/utils/index.js +0 -18
  37. package/dist/cjs/src/utils/index.js.map +0 -1
  38. package/dist/cjs/src/utils/isNotEmptyObject.d.ts +0 -2
  39. package/dist/cjs/src/utils/isNotEmptyObject.d.ts.map +0 -1
  40. package/dist/cjs/src/utils/isNotEmptyObject.js +0 -9
  41. package/dist/cjs/src/utils/isNotEmptyObject.js.map +0 -1
  42. package/dist/esm/src/utils/index.d.ts +0 -2
  43. package/dist/esm/src/utils/index.d.ts.map +0 -1
  44. package/dist/esm/src/utils/index.js +0 -2
  45. package/dist/esm/src/utils/index.js.map +0 -1
  46. package/dist/esm/src/utils/isNotEmptyObject.d.ts +0 -2
  47. package/dist/esm/src/utils/isNotEmptyObject.d.ts.map +0 -1
  48. package/dist/esm/src/utils/isNotEmptyObject.js +0 -6
  49. package/dist/esm/src/utils/isNotEmptyObject.js.map +0 -1
  50. package/src/utils/index.ts +0 -1
  51. package/src/utils/isNotEmptyObject.ts +0 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formo/analytics",
3
- "version": "1.11.8",
3
+ "version": "1.11.9",
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.6.3",
66
+ "typescript": "^5.7.2",
67
67
  "webpack": "^5.74.0",
68
68
  "webpack-cli": "^4.10.0"
69
69
  },
@@ -5,7 +5,6 @@ import {
5
5
  SESSION_STORAGE_ID_KEY,
6
6
  Event,
7
7
  } from './constants';
8
- import { isNotEmpty } from './utils';
9
8
  import { H } from 'highlight.run';
10
9
  import { ChainID, EIP1193Provider, Options } from './types';
11
10
 
@@ -13,12 +12,11 @@ interface IFormoAnalytics {
13
12
  /**
14
13
  * Initializes the FormoAnalytics instance with the provided API key and project ID.
15
14
  */
16
- init(apiKey: string, options: Options): Promise<FormoAnalytics>;
17
-
18
- /**
19
- * Identifies the user with the provided user data.
20
- */
21
- identify(userData: Record<string, any>): void;
15
+ init(
16
+ apiKey: string,
17
+ projectId: string,
18
+ options?: Options
19
+ ): Promise<FormoAnalytics>;
22
20
 
23
21
  /**
24
22
  * Tracks page visit events.
@@ -28,22 +26,22 @@ interface IFormoAnalytics {
28
26
  /**
29
27
  * Connects to a wallet with the specified chain ID and address.
30
28
  */
31
- connect(params: { account: string; chainId: ChainID }): Promise<void>;
29
+ connect(params: { chainId: ChainID; address: string }): Promise<void>;
32
30
 
33
31
  /**
34
32
  * Disconnects the current wallet and clears the session information.
35
33
  */
36
- disconnect(attributes?: { account?: string; chainId?: ChainID }): void;
34
+ disconnect(params?: { chainId?: ChainID; address?: string }): void;
37
35
 
38
36
  /**
39
- * Tracks a specific event with a name and associated data.
37
+ * Switches the blockchain chain context and optionally logs additional params.
40
38
  */
41
- track(eventName: string, eventData: Record<string, any>): void;
39
+ chain(params: { chainId: ChainID; address?: string }): void;
42
40
 
43
41
  /**
44
- * Switches the blockchain chain context and optionally logs additional attributes.
42
+ * Tracks a specific event with a name and associated data.
45
43
  */
46
- chain(attributes: { chainId: ChainID; account?: string }): void;
44
+ track(eventName: string, eventData: Record<string, any>): void;
47
45
  }
48
46
  interface Config {
49
47
  token: string;
@@ -61,17 +59,19 @@ export class FormoAnalytics implements IFormoAnalytics {
61
59
  private timezoneToCountry: Record<string, string> = COUNTRY_LIST;
62
60
 
63
61
  currentChainId?: string | null;
64
- currentConnectedAccount?: string;
62
+ currentConnectedAddress?: string;
65
63
 
66
64
  private constructor(
67
65
  public readonly apiKey: string,
66
+ public readonly projectId: string,
68
67
  public options: Options = {}
69
68
  ) {
70
69
  this.config = {
71
70
  token: this.apiKey,
72
71
  };
73
72
 
74
- const provider = window?.ethereum || window.web3?.currentProvider || options?.provider;
73
+ const provider =
74
+ window?.ethereum || window.web3?.currentProvider || options?.provider;
75
75
  if (provider) {
76
76
  this.trackProvider(provider);
77
77
  }
@@ -79,12 +79,13 @@ export class FormoAnalytics implements IFormoAnalytics {
79
79
 
80
80
  static async init(
81
81
  apiKey: string,
82
- options: Options
82
+ projectId: string,
83
+ options?: Options
83
84
  ): Promise<FormoAnalytics> {
84
85
  const config = {
85
86
  token: apiKey,
86
87
  };
87
- const instance = new FormoAnalytics(apiKey, options);
88
+ const instance = new FormoAnalytics(apiKey, projectId, options);
88
89
  instance.config = config;
89
90
 
90
91
  return instance;
@@ -94,10 +95,6 @@ export class FormoAnalytics implements IFormoAnalytics {
94
95
  return this._provider;
95
96
  }
96
97
 
97
- private identifyUser(userData: any) {
98
- this.trackEvent(Event.IDENTIFY, userData);
99
- }
100
-
101
98
  private getSessionId() {
102
99
  const existingSessionId = this.getCookieValue(this.sessionIdKey);
103
100
 
@@ -116,7 +113,9 @@ export class FormoAnalytics implements IFormoAnalytics {
116
113
  // Function to set the session cookie
117
114
  private setSessionCookie(): void {
118
115
  const sessionId = this.getSessionId();
119
- let cookieValue = `${this.sessionIdKey}=${sessionId}; Max-Age=1800; path=/; secure; domain=${this.getOrigin()}`;
116
+ let cookieValue = `${
117
+ this.sessionIdKey
118
+ }=${sessionId}; Max-Age=1800; path=/; secure; domain=${this.getOrigin()}`;
120
119
  document.cookie = cookieValue;
121
120
  }
122
121
 
@@ -147,19 +146,23 @@ export class FormoAnalytics implements IFormoAnalytics {
147
146
  address: address,
148
147
  session_id: this.getSessionId(),
149
148
  timestamp: new Date().toISOString(),
150
- action: action,
149
+ action,
151
150
  version: '1',
152
- payload: isNotEmpty(payload) ? this.maskSensitiveData(payload) : payload,
151
+ payload,
153
152
  };
154
153
 
155
154
  const sendRequest = async (): Promise<void> => {
156
155
  try {
157
- const response = await axios.post(EVENTS_API_URL, JSON.stringify(requestData), {
158
- headers: {
159
- 'Content-Type': 'application/json',
160
- Authorization: `Bearer ${this.apiKey}`
161
- },
162
- });
156
+ const response = await axios.post(
157
+ EVENTS_API_URL,
158
+ JSON.stringify(requestData),
159
+ {
160
+ headers: {
161
+ 'Content-Type': 'application/json',
162
+ Authorization: `Bearer ${this.apiKey}`,
163
+ },
164
+ }
165
+ );
163
166
 
164
167
  if (response.status >= 200 && response.status < 300) {
165
168
  console.log('Event sent successfully:', action);
@@ -192,72 +195,6 @@ export class FormoAnalytics implements IFormoAnalytics {
192
195
  await sendRequest();
193
196
  }
194
197
 
195
- // Function to mask sensitive data in the payload
196
- private maskSensitiveData(
197
- data: string | undefined | null
198
- ): Record<string, any> | null {
199
- // Check if data is null or undefined
200
- if (data === null || data === undefined) {
201
- console.warn('Data is null or undefined, returning null');
202
- return null;
203
- }
204
-
205
- // Check if data is a string; if so, parse it to an object
206
- if (typeof data === 'string') {
207
- let parsedData: Record<string, any>;
208
- try {
209
- parsedData = JSON.parse(data);
210
- } catch (error) {
211
- console.error('Failed to parse JSON:', error);
212
- return null; // Return null if parsing fails
213
- }
214
-
215
- const sensitiveFields = [
216
- 'username',
217
- 'user',
218
- 'user_id',
219
- 'password',
220
- 'email',
221
- 'phone',
222
- ];
223
-
224
- // Create a new object to store masked data
225
- const maskedData = { ...parsedData };
226
-
227
- // Mask sensitive fields
228
- sensitiveFields.forEach((field) => {
229
- if (field in maskedData) {
230
- maskedData[field] = '********'; // Replace value with masked string
231
- }
232
- });
233
-
234
- return maskedData; // Return the new object with masked fields
235
- } else if (typeof data === 'object') {
236
- // If data is already an object, handle masking directly
237
- const sensitiveFields = [
238
- 'username',
239
- 'user',
240
- 'user_id',
241
- 'password',
242
- 'email',
243
- 'phone',
244
- ];
245
-
246
- const maskedData = { ...(data as Record<string, any>) };
247
-
248
- // Mask sensitive fields
249
- sensitiveFields.forEach((field) => {
250
- if (field in maskedData) {
251
- maskedData[field] = '********'; // Replace value with masked string
252
- }
253
- });
254
-
255
- return maskedData; // Return the new object with masked fields
256
- }
257
-
258
- return data;
259
- }
260
-
261
198
  // Function to track page hits
262
199
  private trackPageHit() {
263
200
  if (window.__nightmare || window.navigator.webdriver || window.Cypress)
@@ -281,6 +218,7 @@ export class FormoAnalytics implements IFormoAnalytics {
281
218
  const params = new URLSearchParams(url.search);
282
219
  this.trackEvent(Event.PAGE, {
283
220
  'user-agent': window.navigator.userAgent,
221
+ address: this.currentConnectedAddress,
284
222
  locale: language,
285
223
  location: location,
286
224
  referrer: document.referrer,
@@ -296,11 +234,12 @@ export class FormoAnalytics implements IFormoAnalytics {
296
234
 
297
235
  private trackProvider(provider: EIP1193Provider) {
298
236
  if (provider === this._provider) {
237
+ console.log('Provider already tracked.');
299
238
  return;
300
239
  }
301
240
 
302
241
  this.currentChainId = undefined;
303
- this.currentConnectedAccount = undefined;
242
+ this.currentConnectedAddress = undefined;
304
243
 
305
244
  if (this._provider) {
306
245
  const eventNames = Object.keys(this._registeredProviderListeners);
@@ -313,13 +252,84 @@ export class FormoAnalytics implements IFormoAnalytics {
313
252
  }
314
253
  }
315
254
 
255
+ console.log('Tracking new provider:', provider);
316
256
  this._provider = provider;
317
257
 
318
258
  this.getCurrentWallet();
319
- this.registerAccountsChangedListener();
259
+ this.registerAddressChangedListener();
320
260
  this.registerChainChangedListener();
321
261
  }
322
262
 
263
+ private async getCurrentWallet() {
264
+ if (!this.provider) {
265
+ console.warn('FormoAnalytics::getCurrentWallet: the provider is not set');
266
+ return;
267
+ }
268
+
269
+ const sessionData = sessionStorage.getItem(this.walletAddressSessionKey);
270
+
271
+ if (!sessionData) {
272
+ console.warn(
273
+ 'Session data missing. Attempting to fetch address from provider.'
274
+ );
275
+ try {
276
+ const accounts = await this.provider.request<string[]>({
277
+ method: 'eth_accounts',
278
+ });
279
+ if (accounts && accounts.length > 0) {
280
+ const address = accounts[0];
281
+ this.storeWalletAddress(address);
282
+ return address;
283
+ }
284
+ } catch (err) {
285
+ console.error('Failed to fetch accounts from provider:', err);
286
+ }
287
+ return null;
288
+ }
289
+
290
+ const parsedData = JSON.parse(sessionData);
291
+ const sessionExpiry = 30 * 60 * 1000; // 30 minutes
292
+ const currentTime = Date.now();
293
+
294
+ if (currentTime - parsedData.timestamp > sessionExpiry) {
295
+ console.warn('Session expired. Ignoring wallet address.');
296
+ sessionStorage.removeItem(this.walletAddressSessionKey); // Clear expired session data
297
+ return '';
298
+ }
299
+
300
+ this.onAddressConnected(parsedData.address);
301
+ return parsedData.address || '';
302
+ }
303
+
304
+ private async getCurrentChainId(): Promise<string> {
305
+ if (!this.provider) {
306
+ console.error('FormoAnalytics::getCurrentChainId: provider not set');
307
+ }
308
+ const chainIdHex = await this.provider?.request<string>({
309
+ method: 'eth_chainId',
310
+ });
311
+ // Because we're connected, the chainId cannot be null
312
+ if (!chainIdHex) {
313
+ console.error(
314
+ `FormoAnalytics::getCurrentChainId: chainIdHex is: ${chainIdHex}`
315
+ );
316
+ }
317
+
318
+ return parseInt(chainIdHex as string, 16).toString();
319
+ }
320
+
321
+ private registerAddressChangedListener() {
322
+ const listener = (...args: unknown[]) =>
323
+ this.onAddressChanged(args[0] as string[]);
324
+
325
+ this._provider?.on('accountsChanged', listener);
326
+ this._registeredProviderListeners['accountsChanged'] = listener;
327
+
328
+ const onAddressDisconnected = this.onAddressDisconnected.bind(this);
329
+ this._provider?.on('disconnect', onAddressDisconnected);
330
+ this._registeredProviderListeners['disconnect'] = onAddressDisconnected;
331
+ }
332
+
323
333
  private registerChainChangedListener() {
324
334
  const listener = (...args: unknown[]) =>
325
335
  this.onChainChanged(args[0] as string);
@@ -327,25 +337,50 @@ export class FormoAnalytics implements IFormoAnalytics {
327
337
  this._registeredProviderListeners['chainChanged'] = listener;
328
338
  }
329
339
 
330
- private handleAccountDisconnected() {
331
- if (!this.currentConnectedAccount) {
340
+ private async onAddressChanged(addresses: string[]) {
341
+ if (addresses.length > 0) {
342
+ const newAccount = addresses[0];
343
+ if (newAccount !== this.currentConnectedAddress) {
344
+ this.onAddressConnected(newAccount);
345
+ }
346
+ } else {
347
+ this.onAddressDisconnected();
348
+ }
349
+ }
350
+
351
+ private async onAddressConnected(address: string) {
352
+ if (address === this.currentConnectedAddress) {
353
+ // We have already reported this address
332
354
  return;
355
+ } else {
356
+ this.currentConnectedAddress = address;
333
357
  }
334
358
 
335
- const disconnectAttributes = {
336
- address: this.currentConnectedAccount,
337
- chainId: this.currentChainId,
359
+ this.currentChainId = await this.getCurrentChainId();
360
+
361
+ this.connect({ chainId: this.currentChainId, address });
362
+ this.storeWalletAddress(address);
363
+ }
364
+
365
+ private onAddressDisconnected() {
366
+ if (!this.currentConnectedAddress) {
367
+ return;
368
+ }
369
+
370
+ const payload = {
371
+ chain_id: this.currentChainId,
372
+ address: this.currentConnectedAddress,
338
373
  };
339
374
  this.currentChainId = undefined;
340
- this.currentConnectedAccount = undefined;
375
+ this.currentConnectedAddress = undefined;
341
376
  this.clearWalletAddress();
342
377
 
343
- return this.trackEvent(Event.DISCONNECT, disconnectAttributes);
378
+ return this.trackEvent(Event.DISCONNECT, payload);
344
379
  }
345
380
 
346
381
  private async onChainChanged(chainIdHex: string) {
347
382
  this.currentChainId = parseInt(chainIdHex).toString();
348
- if (!this.currentConnectedAccount) {
383
+ if (!this.currentConnectedAddress) {
349
384
  if (!this.provider) {
350
385
  console.error(
351
386
  'error',
@@ -366,7 +401,7 @@ export class FormoAnalytics implements IFormoAnalytics {
366
401
  return;
367
402
  }
368
403
 
369
- this.currentConnectedAccount = res[0];
404
+ this.currentConnectedAddress = res[0];
370
405
  } catch (err) {
371
406
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
372
407
  if ((err as any).code !== 4001) {
@@ -383,88 +418,8 @@ export class FormoAnalytics implements IFormoAnalytics {
383
418
 
384
419
  return this.chain({
385
420
  chainId: this.currentChainId,
386
- account: this.currentConnectedAccount,
387
- });
388
- }
389
-
390
- private async onAccountsChanged(accounts: string[]) {
391
- if (accounts.length > 0) {
392
- const newAccount = accounts[0];
393
- if (newAccount !== this.currentConnectedAccount) {
394
- this.handleAccountConnected(newAccount);
395
- }
396
- } else {
397
- this.handleAccountDisconnected();
398
- }
399
- }
400
-
401
- private registerAccountsChangedListener() {
402
- const listener = (...args: unknown[]) =>
403
- this.onAccountsChanged(args[0] as string[]);
404
-
405
- this._provider?.on('accountsChanged', listener);
406
- this._registeredProviderListeners['accountsChanged'] = listener;
407
-
408
- const handleAccountDisconnected = this.handleAccountDisconnected.bind(this);
409
- this._provider?.on('disconnect', handleAccountDisconnected);
410
- this._registeredProviderListeners['disconnect'] = handleAccountDisconnected;
411
- }
412
-
413
- private async getCurrentChainId(): Promise<string> {
414
- if (!this.provider) {
415
- console.error('FormoAnalytics::getCurrentChainId: provider not set');
416
- }
417
-
418
- const chainIdHex = await this.provider?.request<string>({
419
- method: 'eth_chainId',
421
+ address: this.currentConnectedAddress,
420
422
  });
421
- // Because we're connected, the chainId cannot be null
422
- if (!chainIdHex) {
423
- console.error(
424
- `FormoAnalytics::getCurrentChainId: chainIdHex is: ${chainIdHex}`
425
- );
426
- }
427
-
428
- return parseInt(chainIdHex as string, 16).toString();
429
- }
430
-
431
- private async handleAccountConnected(account: string) {
432
- if (account === this.currentConnectedAccount) {
433
- // We have already reported this account
434
- return;
435
- } else {
436
- this.currentConnectedAccount = account;
437
- }
438
-
439
- this.currentChainId = await this.getCurrentChainId();
440
-
441
- this.connect({ account, chainId: this.currentChainId });
442
- this.storeWalletAddress(account);
443
- }
444
-
445
- private async getCurrentWallet() {
446
- if (!this.provider) {
447
- console.warn('FormoAnalytics::getCurrentWallet: the provider is not set');
448
- return;
449
- }
450
- const sessionData = sessionStorage.getItem(this.walletAddressSessionKey);
451
-
452
- if (!sessionData) {
453
- return null;
454
- }
455
-
456
- const parsedData = JSON.parse(sessionData);
457
- const sessionExpiry = 30 * 60 * 1000; // 30 minutes
458
- const currentTime = Date.now();
459
-
460
- if (currentTime - parsedData.timestamp > sessionExpiry) {
461
- console.warn('Session expired. Ignoring wallet address.');
462
- sessionStorage.removeItem(this.walletAddressSessionKey); // Clear expired session data
463
- return '';
464
- }
465
-
466
- this.handleAccountConnected(parsedData.address);
467
- return parsedData.address || '';
468
423
  }
469
424
 
470
425
  /**
@@ -482,7 +437,10 @@ export class FormoAnalytics implements IFormoAnalytics {
482
437
  timestamp: Date.now(),
483
438
  };
484
439
 
485
- sessionStorage.setItem(this.walletAddressSessionKey, JSON.stringify(sessionData));
440
+ sessionStorage.setItem(
441
+ this.walletAddressSessionKey,
442
+ JSON.stringify(sessionData)
443
+ );
486
444
  }
487
445
 
488
446
  /**
@@ -492,54 +450,55 @@ export class FormoAnalytics implements IFormoAnalytics {
492
450
  sessionStorage.removeItem(this.walletAddressSessionKey);
493
451
  }
494
452
 
495
- connect({ account, chainId }: { account: string; chainId: ChainID }) {
453
+ init(apiKey: string, projectId: string, options: Options): Promise<FormoAnalytics> {
454
+ const instance = new FormoAnalytics(apiKey, projectId, options);
455
+ return Promise.resolve(instance);
456
+ }
457
+
458
+ connect({ chainId, address }: { chainId: ChainID; address: string }) {
496
459
  if (!chainId) {
497
- throw new Error('FormoAnalytics::connect: chainId cannot be empty');
460
+ throw new Error('FormoAnalytics::connect: chain ID cannot be empty');
498
461
  }
499
- if (!account) {
500
- throw new Error('FormoAnalytics::connect: account cannot be empty');
462
+ if (!address) {
463
+ throw new Error('FormoAnalytics::connect: address cannot be empty');
501
464
  }
502
465
 
503
466
  this.currentChainId = chainId.toString();
504
- this.currentConnectedAccount = account;
467
+ this.currentConnectedAddress = address;
505
468
 
506
469
  return this.trackEvent(Event.CONNECT, {
507
- chainId,
508
- address: account,
470
+ chain_id: chainId,
471
+ address: address,
509
472
  });
510
473
  }
511
474
 
512
- disconnect(attributes?: { account?: string; chainId?: ChainID }) {
513
- const account = attributes?.account || this.currentConnectedAccount;
514
- if (!account) {
475
+ disconnect(params?: { chainId?: ChainID; address?: string }) {
476
+ const address = params?.address || this.currentConnectedAddress;
477
+ if (!address) {
515
478
  // We have most likely already reported this disconnection with the automatic
516
479
  // `disconnect` detection
517
480
  return;
518
481
  }
519
482
 
520
- const chainId = attributes?.chainId || this.currentChainId;
521
- const eventAttributes = {
522
- account,
523
- ...(chainId && { chainId }),
483
+ const payload = {
484
+ chain_id: params?.chainId || this.currentChainId,
485
+ address,
524
486
  };
525
-
526
487
  this.currentChainId = undefined;
527
- this.currentConnectedAccount = undefined;
488
+ this.currentConnectedAddress = undefined;
528
489
 
529
- return this.trackEvent(Event.DISCONNECT, eventAttributes);
490
+ return this.trackEvent(Event.DISCONNECT, payload);
530
491
  }
531
492
 
532
- chain({ chainId, account }: { chainId: ChainID; account?: string }) {
493
+ chain({ chainId, address }: { chainId: ChainID; address?: string }) {
533
494
  if (!chainId || Number(chainId) === 0) {
534
495
  throw new Error('FormoAnalytics::chain: chainId cannot be empty or 0');
535
496
  }
536
-
537
- if (!account && !this.currentConnectedAccount) {
497
+ if (!address && !this.currentConnectedAddress) {
538
498
  throw new Error(
539
- 'FormoAnalytics::chain: account was empty and no previous account has been recorded. You can either pass an account or call connect() first'
499
+ 'FormoAnalytics::chain: address was empty and no previous address has been recorded. You can either pass an address or call connect() first'
540
500
  );
541
501
  }
542
-
543
502
  if (isNaN(Number(chainId))) {
544
503
  throw new Error(
545
504
  'FormoAnalytics::chain: chainId must be a valid hex or decimal number'
@@ -549,20 +508,11 @@ export class FormoAnalytics implements IFormoAnalytics {
549
508
  this.currentChainId = chainId.toString();
550
509
 
551
510
  return this.trackEvent(Event.CHAIN_CHANGED, {
552
- chainId,
553
- account: account || this.currentConnectedAccount,
511
+ chain_id: chainId,
512
+ address: address || this.currentConnectedAddress,
554
513
  });
555
514
  }
556
515
 
557
- init(apiKey: string, options: Options): Promise<FormoAnalytics> {
558
- const instance = new FormoAnalytics(apiKey, options);
559
- return Promise.resolve(instance);
560
- }
561
-
562
- identify(userData: any) {
563
- this.identifyUser(userData);
564
- }
565
-
566
516
  page() {
567
517
  this.trackPageHit();
568
518
  }
@@ -19,6 +19,7 @@ export const FormoAnalyticsContext = createContext<FormoAnalytics | undefined>(
19
19
  export const FormoAnalyticsProvider = ({
20
20
  apiKey,
21
21
  options,
22
+ projectId,
22
23
  disabled,
23
24
  children,
24
25
  }: FormoAnalyticsProviderProps) => {
@@ -32,15 +33,12 @@ export const FormoAnalyticsProvider = ({
32
33
  console.error('FormoAnalyticsProvider: No API key provided');
33
34
  return;
34
35
  }
35
-
36
36
  if (disabled) {
37
37
  console.warn('FormoAnalytics is disabled');
38
38
  return;
39
39
  }
40
-
41
40
  if (initializedStartedRef.current) return;
42
41
  initializedStartedRef.current = true;
43
-
44
42
  // Initialize Highlight.run if project ID is available
45
43
  if (HIGHLIGHT_PROJECT_ID) {
46
44
  try {
@@ -64,7 +62,7 @@ export const FormoAnalyticsProvider = ({
64
62
 
65
63
  // Initialize FormoAnalytics
66
64
  try {
67
- const sdkInstance = await FormoAnalytics.init(apiKey, options);
65
+ const sdkInstance = await FormoAnalytics.init(apiKey, projectId, options);
68
66
  setSdk(sdkInstance);
69
67
  console.log('FormoAnalytics SDK initialized successfully');
70
68
  } catch (error) {
package/src/types/base.ts CHANGED
@@ -8,7 +8,8 @@ export interface Options {
8
8
 
9
9
  export interface FormoAnalyticsProviderProps {
10
10
  apiKey: string;
11
- options: Options;
11
+ projectId: string;
12
+ options?: Options;
12
13
  disabled?: boolean;
13
14
  children: React.ReactNode;
14
15
  }