@formo/analytics 1.15.2 → 1.16.1
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/cjs/src/FormoAnalytics.d.ts +10 -4
- package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalytics.js +106 -113
- package/dist/cjs/src/FormoAnalytics.js.map +1 -1
- package/dist/cjs/src/constants/base.d.ts +1 -1
- package/dist/cjs/src/constants/base.d.ts.map +1 -1
- package/dist/cjs/src/constants/base.js +2 -2
- package/dist/cjs/src/constants/base.js.map +1 -1
- package/dist/cjs/src/constants/events.d.ts +1 -0
- package/dist/cjs/src/constants/events.d.ts.map +1 -1
- package/dist/cjs/src/constants/events.js +1 -0
- package/dist/cjs/src/constants/events.js.map +1 -1
- package/dist/cjs/src/lib/queue.d.ts.map +1 -1
- package/dist/cjs/src/lib/queue.js +3 -2
- package/dist/cjs/src/lib/queue.js.map +1 -1
- package/dist/cjs/src/types/events.d.ts +1 -1
- package/dist/cjs/src/types/events.d.ts.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/src/FormoAnalytics.d.ts +10 -4
- package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalytics.js +109 -116
- package/dist/esm/src/FormoAnalytics.js.map +1 -1
- package/dist/esm/src/constants/base.d.ts +1 -1
- package/dist/esm/src/constants/base.d.ts.map +1 -1
- package/dist/esm/src/constants/base.js +1 -1
- package/dist/esm/src/constants/base.js.map +1 -1
- package/dist/esm/src/constants/events.d.ts +1 -0
- package/dist/esm/src/constants/events.d.ts.map +1 -1
- package/dist/esm/src/constants/events.js +1 -0
- package/dist/esm/src/constants/events.js.map +1 -1
- package/dist/esm/src/lib/queue.d.ts.map +1 -1
- package/dist/esm/src/lib/queue.js +3 -2
- package/dist/esm/src/lib/queue.js.map +1 -1
- package/dist/esm/src/types/events.d.ts +1 -1
- package/dist/esm/src/types/events.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 +1 -1
- package/src/FormoAnalytics.ts +89 -75
- package/src/constants/base.ts +3 -2
- package/src/constants/events.ts +8 -7
- package/src/lib/queue.ts +2 -1
- package/src/types/events.ts +1 -1
package/package.json
CHANGED
package/src/FormoAnalytics.ts
CHANGED
|
@@ -6,8 +6,6 @@ import {
|
|
|
6
6
|
EVENTS_API_URL,
|
|
7
7
|
Event,
|
|
8
8
|
SESSION_USER_ID_KEY,
|
|
9
|
-
EVENTS_API_REQUEST_HEADER,
|
|
10
|
-
USER_API_URL,
|
|
11
9
|
} from "./constants";
|
|
12
10
|
import {
|
|
13
11
|
ChainID,
|
|
@@ -21,14 +19,14 @@ import {
|
|
|
21
19
|
TransactionStatus,
|
|
22
20
|
RequestEvent,
|
|
23
21
|
} from "./types";
|
|
24
|
-
import { session, local, logger, EventQueue,
|
|
22
|
+
import { session, local, logger, EventQueue, Logger } from "./lib";
|
|
25
23
|
import {
|
|
26
24
|
isLocalhost,
|
|
27
25
|
isAddress,
|
|
28
26
|
toSnakeCase,
|
|
29
27
|
generateNativeUUID,
|
|
30
28
|
} from "./utils";
|
|
31
|
-
import {
|
|
29
|
+
import { SESSION_WALLET_DETECTED_KEY } from "./constants";
|
|
32
30
|
import { UUID } from "crypto";
|
|
33
31
|
|
|
34
32
|
interface IFormoAnalytics {
|
|
@@ -77,7 +75,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
77
75
|
private session: FormoAnalyticsSession;
|
|
78
76
|
private eventQueue: EventQueue;
|
|
79
77
|
private anonymousId: UUID | null = null;
|
|
80
|
-
private userId:
|
|
78
|
+
private userId: string | null = null;
|
|
81
79
|
|
|
82
80
|
config: Config;
|
|
83
81
|
currentChainId?: ChainID;
|
|
@@ -109,7 +107,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
109
107
|
});
|
|
110
108
|
|
|
111
109
|
this.anonymousId = this.getAnonymousId();
|
|
112
|
-
this.
|
|
110
|
+
this.userId = session.get(SESSION_USER_ID_KEY) as string | null;
|
|
113
111
|
|
|
114
112
|
// TODO: replace with eip6963
|
|
115
113
|
const provider = options.provider || window?.ethereum;
|
|
@@ -127,9 +125,9 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
127
125
|
): Promise<FormoAnalytics> {
|
|
128
126
|
const analytics = new FormoAnalytics(writeKey, options);
|
|
129
127
|
|
|
130
|
-
//
|
|
128
|
+
// Detect
|
|
131
129
|
const providers = await analytics.getProviders();
|
|
132
|
-
await analytics.
|
|
130
|
+
await analytics.detects(providers);
|
|
133
131
|
|
|
134
132
|
return analytics;
|
|
135
133
|
}
|
|
@@ -311,23 +309,22 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
311
309
|
}
|
|
312
310
|
|
|
313
311
|
/**
|
|
314
|
-
* Emits an
|
|
312
|
+
* Emits an detect event with current wallet provider info.
|
|
315
313
|
* @param {Address} params.address
|
|
316
314
|
* @returns {Promise<void>}
|
|
317
315
|
*/
|
|
318
316
|
public async identify({
|
|
319
317
|
address,
|
|
320
318
|
providerName,
|
|
319
|
+
userId,
|
|
321
320
|
rdns,
|
|
322
321
|
}: {
|
|
323
322
|
address: Address | null;
|
|
324
323
|
providerName?: string;
|
|
324
|
+
userId?: string;
|
|
325
325
|
rdns?: string;
|
|
326
326
|
}): Promise<void> {
|
|
327
|
-
if (this.
|
|
328
|
-
return logger.warn("Identify: Wallet already identified in this session");
|
|
329
|
-
|
|
330
|
-
this.session.identify();
|
|
327
|
+
if (userId) this.userId = userId || null;
|
|
331
328
|
await this.trackEvent(Event.IDENTIFY, {
|
|
332
329
|
address,
|
|
333
330
|
providerName,
|
|
@@ -335,6 +332,30 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
335
332
|
});
|
|
336
333
|
}
|
|
337
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Emits an identify event with current wallet address.
|
|
337
|
+
* @param {Address} params.address
|
|
338
|
+
* @returns {Promise<void>}
|
|
339
|
+
*/
|
|
340
|
+
private async detect({
|
|
341
|
+
providerName,
|
|
342
|
+
rdns,
|
|
343
|
+
}: {
|
|
344
|
+
providerName: string;
|
|
345
|
+
rdns: string;
|
|
346
|
+
}): Promise<void> {
|
|
347
|
+
if (this.session.isWalletDetected(rdns))
|
|
348
|
+
return logger.warn(
|
|
349
|
+
`detect: Wallet ${providerName} already detected in this session`
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
this.session.markWalletdetected(rdns);
|
|
353
|
+
await this.trackEvent(Event.DETECT_WALLET, {
|
|
354
|
+
providerName,
|
|
355
|
+
rdns,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
338
359
|
/**
|
|
339
360
|
* Emits a custom event with custom data.
|
|
340
361
|
* @param {string} action
|
|
@@ -573,7 +594,6 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
573
594
|
return Promise.resolve();
|
|
574
595
|
}
|
|
575
596
|
this.currentConnectedAddress = address;
|
|
576
|
-
this.userId = await this.getUserId(address);
|
|
577
597
|
}
|
|
578
598
|
|
|
579
599
|
// Proceed only if the address exists
|
|
@@ -646,7 +666,7 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
646
666
|
private async trackEvent(action: string, payload: any): Promise<void> {
|
|
647
667
|
try {
|
|
648
668
|
const address = await this.getAddress();
|
|
649
|
-
const user_id =
|
|
669
|
+
const user_id = this.userId;
|
|
650
670
|
|
|
651
671
|
const requestData: RequestEvent = {
|
|
652
672
|
anonymous_id: this.anonymousId as UUID,
|
|
@@ -685,38 +705,54 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
685
705
|
return providers;
|
|
686
706
|
}
|
|
687
707
|
|
|
688
|
-
private async
|
|
708
|
+
private async detects(
|
|
689
709
|
providers: readonly EIP6963ProviderDetail[]
|
|
690
710
|
): Promise<void> {
|
|
691
711
|
try {
|
|
692
712
|
for (const eip6963ProviderDetail of providers) {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
eip6963ProviderDetail?.
|
|
696
|
-
);
|
|
697
|
-
// Identify with accounts
|
|
698
|
-
if (accounts && accounts.length > 0) {
|
|
699
|
-
for (const address of accounts) {
|
|
700
|
-
await this.identify({
|
|
701
|
-
address,
|
|
702
|
-
providerName: eip6963ProviderDetail?.info.name,
|
|
703
|
-
rdns: eip6963ProviderDetail?.info.rdns,
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
} else {
|
|
707
|
-
// Identify without accounts
|
|
708
|
-
await this.identify({
|
|
709
|
-
address: null,
|
|
710
|
-
providerName: eip6963ProviderDetail?.info.name,
|
|
711
|
-
rdns: eip6963ProviderDetail?.info.rdns,
|
|
712
|
-
});
|
|
713
|
-
}
|
|
713
|
+
await this.detect({
|
|
714
|
+
providerName: eip6963ProviderDetail?.info.name,
|
|
715
|
+
rdns: eip6963ProviderDetail?.info.rdns,
|
|
716
|
+
});
|
|
714
717
|
}
|
|
715
718
|
} catch (err) {
|
|
716
|
-
logger.error("Error
|
|
719
|
+
logger.error("Error detect all wallets:", err);
|
|
717
720
|
}
|
|
718
721
|
}
|
|
719
722
|
|
|
723
|
+
// TODO: Refactoring => public this function as API
|
|
724
|
+
// private async identifyAll(
|
|
725
|
+
// providers: readonly EIP6963ProviderDetail[]
|
|
726
|
+
// ): Promise<void> {
|
|
727
|
+
// try {
|
|
728
|
+
// for (const eip6963ProviderDetail of providers) {
|
|
729
|
+
// if (!eip6963ProviderDetail) continue;
|
|
730
|
+
// const accounts = await this.getAccounts(
|
|
731
|
+
// eip6963ProviderDetail?.provider
|
|
732
|
+
// );
|
|
733
|
+
// // Identify with accounts
|
|
734
|
+
// if (accounts && accounts.length > 0) {
|
|
735
|
+
// for (const address of accounts) {
|
|
736
|
+
// await this.identify({
|
|
737
|
+
// address,
|
|
738
|
+
// providerName: eip6963ProviderDetail?.info.name,
|
|
739
|
+
// rdns: eip6963ProviderDetail?.info.rdns,
|
|
740
|
+
// });
|
|
741
|
+
// }
|
|
742
|
+
// } else {
|
|
743
|
+
// // Identify without accounts
|
|
744
|
+
// await this.identify({
|
|
745
|
+
// address: null,
|
|
746
|
+
// providerName: eip6963ProviderDetail?.info.name,
|
|
747
|
+
// rdns: eip6963ProviderDetail?.info.rdns,
|
|
748
|
+
// });
|
|
749
|
+
// }
|
|
750
|
+
// }
|
|
751
|
+
// } catch (err) {
|
|
752
|
+
// logger.error("Error identifying all:", err);
|
|
753
|
+
// }
|
|
754
|
+
// }
|
|
755
|
+
|
|
720
756
|
get provider(): EIP1193Provider | undefined {
|
|
721
757
|
return this._provider;
|
|
722
758
|
}
|
|
@@ -730,31 +766,6 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
730
766
|
return newAnonymousId;
|
|
731
767
|
}
|
|
732
768
|
|
|
733
|
-
private async getUserId(address: string | null): Promise<UUID | null> {
|
|
734
|
-
const storedUserId = session.get(SESSION_USER_ID_KEY);
|
|
735
|
-
if (storedUserId && typeof storedUserId === "string")
|
|
736
|
-
return storedUserId as UUID;
|
|
737
|
-
|
|
738
|
-
if (address) {
|
|
739
|
-
const res = await fetch(`${USER_API_URL}?address=${address}`, {
|
|
740
|
-
headers: EVENTS_API_REQUEST_HEADER(this.writeKey),
|
|
741
|
-
method: "GET",
|
|
742
|
-
});
|
|
743
|
-
const data = await res.json();
|
|
744
|
-
const userId = data?.data?.[0]?.user_id;
|
|
745
|
-
if (userId) {
|
|
746
|
-
session.set(SESSION_USER_ID_KEY, userId);
|
|
747
|
-
return userId;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
const newUserId = generateNativeUUID();
|
|
751
|
-
session.set(SESSION_USER_ID_KEY, newUserId);
|
|
752
|
-
return newUserId;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
return null;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
769
|
private async getAddress(): Promise<Address | null> {
|
|
759
770
|
if (this.currentConnectedAddress) return this.currentConnectedAddress;
|
|
760
771
|
if (!this?.provider) {
|
|
@@ -860,12 +871,12 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
860
871
|
locale: language,
|
|
861
872
|
location,
|
|
862
873
|
referrer: document.referrer,
|
|
863
|
-
utm_source: params.get("utm_source"),
|
|
864
|
-
utm_medium: params.get("utm_medium"),
|
|
865
|
-
utm_campaign: params.get("utm_campaign"),
|
|
866
|
-
utm_content: params.get("utm_content"),
|
|
867
|
-
utm_term: params.get("utm_term"),
|
|
868
|
-
ref: params.get("ref"),
|
|
874
|
+
utm_source: params.get("utm_source")?.trim() || "",
|
|
875
|
+
utm_medium: params.get("utm_medium")?.trim() || "",
|
|
876
|
+
utm_campaign: params.get("utm_campaign")?.trim() || "",
|
|
877
|
+
utm_content: params.get("utm_content")?.trim() || "",
|
|
878
|
+
utm_term: params.get("utm_term")?.trim() || "",
|
|
879
|
+
ref: params.get("ref")?.trim() || "",
|
|
869
880
|
...eventSpecificPayload,
|
|
870
881
|
};
|
|
871
882
|
}
|
|
@@ -920,18 +931,21 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
920
931
|
}
|
|
921
932
|
|
|
922
933
|
interface IFormoAnalyticsSession {
|
|
923
|
-
|
|
924
|
-
|
|
934
|
+
isWalletDetected(rdns: string): boolean;
|
|
935
|
+
markWalletdetected(rdns: string): void;
|
|
925
936
|
}
|
|
926
937
|
|
|
927
938
|
class FormoAnalyticsSession implements IFormoAnalyticsSession {
|
|
928
939
|
constructor() {}
|
|
929
940
|
|
|
930
|
-
public
|
|
931
|
-
|
|
941
|
+
public isWalletDetected(rdns: string): boolean {
|
|
942
|
+
const rdnses = (session.get(SESSION_WALLET_DETECTED_KEY) as string[]) || [];
|
|
943
|
+
return rdnses.includes(rdns);
|
|
932
944
|
}
|
|
933
945
|
|
|
934
|
-
public
|
|
935
|
-
session.
|
|
946
|
+
public markWalletdetected(rdns: string): void {
|
|
947
|
+
const rdnses = (session.get(SESSION_WALLET_DETECTED_KEY) as string[]) || [];
|
|
948
|
+
rdnses.push(rdns);
|
|
949
|
+
session.set(SESSION_WALLET_DETECTED_KEY, rdnses);
|
|
936
950
|
}
|
|
937
951
|
}
|
package/src/constants/base.ts
CHANGED
|
@@ -2,8 +2,9 @@ const STORAGE_PREFIX = "formo-";
|
|
|
2
2
|
|
|
3
3
|
const generateStoragePrefix = (prefix: string) => `${STORAGE_PREFIX}${prefix}`;
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
5
|
+
export const SESSION_WALLET_DETECTED_KEY = generateStoragePrefix(
|
|
6
|
+
"session-wallet-detected"
|
|
7
|
+
);
|
|
7
8
|
export const SESSION_CURRENT_URL_KEY = generateStoragePrefix(
|
|
8
9
|
"analytics-current-url"
|
|
9
10
|
);
|
package/src/constants/events.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export enum Event {
|
|
2
|
-
PAGE =
|
|
3
|
-
IDENTIFY =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
PAGE = "page_hit",
|
|
3
|
+
IDENTIFY = "identify",
|
|
4
|
+
DETECT_WALLET = "detect_wallet",
|
|
5
|
+
CONNECT = "connect",
|
|
6
|
+
DISCONNECT = "disconnect",
|
|
7
|
+
CHAIN_CHANGED = "chain_changed",
|
|
8
|
+
SIGNATURE = "signature",
|
|
9
|
+
TRANSACTION = "transaction",
|
|
9
10
|
}
|
package/src/lib/queue.ts
CHANGED
|
@@ -100,6 +100,7 @@ export class EventQueue {
|
|
|
100
100
|
callback = callback || noop;
|
|
101
101
|
|
|
102
102
|
const formattedTimestamp = toDateHourMinute(new Date(event.timestamp));
|
|
103
|
+
const originTimestamp = event.timestamp;
|
|
103
104
|
event.timestamp = formattedTimestamp;
|
|
104
105
|
|
|
105
106
|
const eventString = JSON.stringify(event);
|
|
@@ -114,7 +115,7 @@ export class EventQueue {
|
|
|
114
115
|
return;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
this.queue.push({ message: { ...event, id: eventId }, callback });
|
|
118
|
+
this.queue.push({ message: { ...event, timestamp: originTimestamp, id: eventId }, callback });
|
|
118
119
|
|
|
119
120
|
logger.log(
|
|
120
121
|
`Event enqueued: ${getActionDescriptor(event.action, event.payload)}`
|