@formo/analytics 1.15.2 → 1.16.0
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 +9 -3
- package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalytics.js +109 -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 +9 -3
- package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalytics.js +112 -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 +93 -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.detectWallets(providers);
|
|
133
131
|
|
|
134
132
|
return analytics;
|
|
135
133
|
}
|
|
@@ -318,16 +316,15 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
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 detectWallet({
|
|
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
|
+
`detectWallet: 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,12 +666,16 @@ 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;
|
|
670
|
+
|
|
671
|
+
if (payload?.userId) {
|
|
672
|
+
delete payload.userId;
|
|
673
|
+
}
|
|
650
674
|
|
|
651
675
|
const requestData: RequestEvent = {
|
|
652
676
|
anonymous_id: this.anonymousId as UUID,
|
|
653
677
|
user_id,
|
|
654
|
-
address,
|
|
678
|
+
address: address?.toLowerCase() || null,
|
|
655
679
|
timestamp: new Date().toISOString(),
|
|
656
680
|
action,
|
|
657
681
|
version: "1",
|
|
@@ -685,38 +709,54 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
685
709
|
return providers;
|
|
686
710
|
}
|
|
687
711
|
|
|
688
|
-
private async
|
|
712
|
+
private async detectWallets(
|
|
689
713
|
providers: readonly EIP6963ProviderDetail[]
|
|
690
714
|
): Promise<void> {
|
|
691
715
|
try {
|
|
692
716
|
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
|
-
}
|
|
717
|
+
await this.detectWallet({
|
|
718
|
+
providerName: eip6963ProviderDetail?.info.name,
|
|
719
|
+
rdns: eip6963ProviderDetail?.info.rdns,
|
|
720
|
+
});
|
|
714
721
|
}
|
|
715
722
|
} catch (err) {
|
|
716
|
-
logger.error("Error
|
|
723
|
+
logger.error("Error detect all wallets:", err);
|
|
717
724
|
}
|
|
718
725
|
}
|
|
719
726
|
|
|
727
|
+
// TODO: Refactoring => public this function as API
|
|
728
|
+
// private async identifyAll(
|
|
729
|
+
// providers: readonly EIP6963ProviderDetail[]
|
|
730
|
+
// ): Promise<void> {
|
|
731
|
+
// try {
|
|
732
|
+
// for (const eip6963ProviderDetail of providers) {
|
|
733
|
+
// if (!eip6963ProviderDetail) continue;
|
|
734
|
+
// const accounts = await this.getAccounts(
|
|
735
|
+
// eip6963ProviderDetail?.provider
|
|
736
|
+
// );
|
|
737
|
+
// // Identify with accounts
|
|
738
|
+
// if (accounts && accounts.length > 0) {
|
|
739
|
+
// for (const address of accounts) {
|
|
740
|
+
// await this.identify({
|
|
741
|
+
// address,
|
|
742
|
+
// providerName: eip6963ProviderDetail?.info.name,
|
|
743
|
+
// rdns: eip6963ProviderDetail?.info.rdns,
|
|
744
|
+
// });
|
|
745
|
+
// }
|
|
746
|
+
// } else {
|
|
747
|
+
// // Identify without accounts
|
|
748
|
+
// await this.identify({
|
|
749
|
+
// address: null,
|
|
750
|
+
// providerName: eip6963ProviderDetail?.info.name,
|
|
751
|
+
// rdns: eip6963ProviderDetail?.info.rdns,
|
|
752
|
+
// });
|
|
753
|
+
// }
|
|
754
|
+
// }
|
|
755
|
+
// } catch (err) {
|
|
756
|
+
// logger.error("Error identifying all:", err);
|
|
757
|
+
// }
|
|
758
|
+
// }
|
|
759
|
+
|
|
720
760
|
get provider(): EIP1193Provider | undefined {
|
|
721
761
|
return this._provider;
|
|
722
762
|
}
|
|
@@ -730,31 +770,6 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
730
770
|
return newAnonymousId;
|
|
731
771
|
}
|
|
732
772
|
|
|
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
773
|
private async getAddress(): Promise<Address | null> {
|
|
759
774
|
if (this.currentConnectedAddress) return this.currentConnectedAddress;
|
|
760
775
|
if (!this?.provider) {
|
|
@@ -860,12 +875,12 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
860
875
|
locale: language,
|
|
861
876
|
location,
|
|
862
877
|
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"),
|
|
878
|
+
utm_source: params.get("utm_source")?.trim() || "",
|
|
879
|
+
utm_medium: params.get("utm_medium")?.trim() || "",
|
|
880
|
+
utm_campaign: params.get("utm_campaign")?.trim() || "",
|
|
881
|
+
utm_content: params.get("utm_content")?.trim() || "",
|
|
882
|
+
utm_term: params.get("utm_term")?.trim() || "",
|
|
883
|
+
ref: params.get("ref")?.trim() || "",
|
|
869
884
|
...eventSpecificPayload,
|
|
870
885
|
};
|
|
871
886
|
}
|
|
@@ -920,18 +935,21 @@ export class FormoAnalytics implements IFormoAnalytics {
|
|
|
920
935
|
}
|
|
921
936
|
|
|
922
937
|
interface IFormoAnalyticsSession {
|
|
923
|
-
|
|
924
|
-
|
|
938
|
+
isWalletDetected(rdns: string): boolean;
|
|
939
|
+
markWalletdetected(rdns: string): void;
|
|
925
940
|
}
|
|
926
941
|
|
|
927
942
|
class FormoAnalyticsSession implements IFormoAnalyticsSession {
|
|
928
943
|
constructor() {}
|
|
929
944
|
|
|
930
|
-
public
|
|
931
|
-
|
|
945
|
+
public isWalletDetected(rdns: string): boolean {
|
|
946
|
+
const rdnses = (session.get(SESSION_WALLET_DETECTED_KEY) as string[]) || [];
|
|
947
|
+
return rdnses.includes(rdns);
|
|
932
948
|
}
|
|
933
949
|
|
|
934
|
-
public
|
|
935
|
-
session.
|
|
950
|
+
public markWalletdetected(rdns: string): void {
|
|
951
|
+
const rdnses = (session.get(SESSION_WALLET_DETECTED_KEY) as string[]) || [];
|
|
952
|
+
rdnses.push(rdns);
|
|
953
|
+
session.set(SESSION_WALLET_DETECTED_KEY, rdnses);
|
|
936
954
|
}
|
|
937
955
|
}
|
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)}`
|