@formo/analytics 1.12.0-alpha.2 → 1.12.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/.env.example +1 -0
- package/CONTRIBUTING.md +93 -0
- package/README.md +4 -163
- package/dist/cjs/src/FormoAnalytics.d.ts +45 -69
- package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalytics.js +378 -404
- package/dist/cjs/src/FormoAnalytics.js.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts +2 -2
- package/dist/cjs/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/cjs/src/FormoAnalyticsProvider.js +120 -29
- package/dist/cjs/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/cjs/src/constants/config.d.ts +2 -2
- package/dist/cjs/src/constants/config.d.ts.map +1 -1
- package/dist/cjs/src/constants/config.js +3 -3
- package/dist/cjs/src/constants/config.js.map +1 -1
- package/dist/cjs/src/constants/events.d.ts +3 -1
- package/dist/cjs/src/constants/events.d.ts.map +1 -1
- package/dist/cjs/src/constants/events.js +2 -0
- package/dist/cjs/src/constants/events.js.map +1 -1
- package/dist/cjs/src/types/base.d.ts +10 -2
- 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 +45 -69
- package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalytics.js +381 -407
- package/dist/esm/src/FormoAnalytics.js.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.d.ts +2 -2
- package/dist/esm/src/FormoAnalyticsProvider.d.ts.map +1 -1
- package/dist/esm/src/FormoAnalyticsProvider.js +120 -29
- package/dist/esm/src/FormoAnalyticsProvider.js.map +1 -1
- package/dist/esm/src/constants/config.d.ts +2 -2
- package/dist/esm/src/constants/config.d.ts.map +1 -1
- package/dist/esm/src/constants/config.js +2 -2
- package/dist/esm/src/constants/config.js.map +1 -1
- package/dist/esm/src/constants/events.d.ts +3 -1
- package/dist/esm/src/constants/events.d.ts.map +1 -1
- package/dist/esm/src/constants/events.js +2 -0
- package/dist/esm/src/constants/events.js.map +1 -1
- package/dist/esm/src/types/base.d.ts +10 -2
- 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 +293 -448
- package/src/FormoAnalyticsProvider.tsx +60 -30
- package/src/constants/config.ts +2 -2
- package/src/constants/events.ts +2 -0
- package/src/types/base.ts +16 -2
- package/dist/cjs/src/utils/index.d.ts +0 -2
- package/dist/cjs/src/utils/index.d.ts.map +0 -1
- package/dist/cjs/src/utils/index.js +0 -18
- package/dist/cjs/src/utils/index.js.map +0 -1
- package/dist/cjs/src/utils/isNotEmptyObject.d.ts +0 -2
- package/dist/cjs/src/utils/isNotEmptyObject.d.ts.map +0 -1
- package/dist/cjs/src/utils/isNotEmptyObject.js +0 -9
- package/dist/cjs/src/utils/isNotEmptyObject.js.map +0 -1
- package/dist/esm/src/utils/index.d.ts +0 -2
- package/dist/esm/src/utils/index.d.ts.map +0 -1
- package/dist/esm/src/utils/index.js +0 -2
- package/dist/esm/src/utils/index.js.map +0 -1
- package/dist/esm/src/utils/isNotEmptyObject.d.ts +0 -2
- package/dist/esm/src/utils/isNotEmptyObject.d.ts.map +0 -1
- package/dist/esm/src/utils/isNotEmptyObject.js +0 -6
- package/dist/esm/src/utils/isNotEmptyObject.js.map +0 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/isNotEmptyObject.ts +0 -5
|
@@ -45,258 +45,170 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
45
45
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
-
import axios from
|
|
49
|
-
import { COUNTRY_LIST,
|
|
50
|
-
import {
|
|
51
|
-
import { H } from 'highlight.run';
|
|
48
|
+
import axios from "axios";
|
|
49
|
+
import { COUNTRY_LIST, EVENTS_API_URL, Event, } from "./constants";
|
|
50
|
+
import { H } from "highlight.run";
|
|
52
51
|
var FormoAnalytics = /** @class */ (function () {
|
|
53
|
-
function FormoAnalytics(apiKey,
|
|
52
|
+
function FormoAnalytics(apiKey, options) {
|
|
53
|
+
if (options === void 0) { options = {}; }
|
|
54
54
|
var _a;
|
|
55
55
|
this.apiKey = apiKey;
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
this.sessionKey = 'walletAddress';
|
|
59
|
-
this.sessionIdKey = SESSION_STORAGE_ID_KEY;
|
|
60
|
-
this.timezoneToCountry = COUNTRY_LIST;
|
|
56
|
+
this.options = options;
|
|
57
|
+
this._providerListeners = {};
|
|
61
58
|
this.config = {
|
|
62
|
-
|
|
59
|
+
apiKey: apiKey,
|
|
63
60
|
};
|
|
64
|
-
var provider = (window === null || window === void 0 ? void 0 : window.ethereum) || ((_a = window.web3) === null || _a === void 0 ? void 0 : _a.currentProvider);
|
|
61
|
+
var provider = (window === null || window === void 0 ? void 0 : window.ethereum) || ((_a = window.web3) === null || _a === void 0 ? void 0 : _a.currentProvider) || (options === null || options === void 0 ? void 0 : options.provider);
|
|
65
62
|
if (provider) {
|
|
66
63
|
this.trackProvider(provider);
|
|
67
64
|
}
|
|
68
65
|
}
|
|
69
|
-
FormoAnalytics.init = function (apiKey,
|
|
66
|
+
FormoAnalytics.init = function (apiKey, options) {
|
|
70
67
|
return __awaiter(this, void 0, void 0, function () {
|
|
71
|
-
var config, instance;
|
|
72
68
|
return __generator(this, function (_a) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
instance = new FormoAnalytics(apiKey, projectId);
|
|
77
|
-
instance.config = config;
|
|
78
|
-
return [2 /*return*/, instance];
|
|
69
|
+
// May be needed for delayed loading
|
|
70
|
+
// https://github.com/segmentio/analytics-next/tree/master/packages/browser#lazy--delayed-loading
|
|
71
|
+
return [2 /*return*/, new FormoAnalytics(apiKey, options)];
|
|
79
72
|
});
|
|
80
73
|
});
|
|
81
74
|
};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Function to generate a new session ID
|
|
110
|
-
FormoAnalytics.prototype.generateSessionId = function () {
|
|
111
|
-
return crypto.randomUUID();
|
|
112
|
-
};
|
|
113
|
-
// Function to get a cookie value by name
|
|
114
|
-
FormoAnalytics.prototype.getCookieValue = function (name) {
|
|
115
|
-
var cookies = document.cookie.split(';').reduce(function (acc, cookie) {
|
|
116
|
-
var _a = cookie.split('='), key = _a[0], value = _a[1];
|
|
117
|
-
acc[key.trim()] = value;
|
|
118
|
-
return acc;
|
|
119
|
-
}, {});
|
|
120
|
-
return cookies[name];
|
|
75
|
+
/*
|
|
76
|
+
Public SDK functions
|
|
77
|
+
*/
|
|
78
|
+
FormoAnalytics.prototype.connect = function (_a) {
|
|
79
|
+
return __awaiter(this, arguments, void 0, function (_b) {
|
|
80
|
+
var chainId = _b.chainId, address = _b.address;
|
|
81
|
+
return __generator(this, function (_c) {
|
|
82
|
+
switch (_c.label) {
|
|
83
|
+
case 0:
|
|
84
|
+
if (!chainId) {
|
|
85
|
+
throw new Error("FormoAnalytics::connect: chain ID cannot be empty");
|
|
86
|
+
}
|
|
87
|
+
if (!address) {
|
|
88
|
+
throw new Error("FormoAnalytics::connect: address cannot be empty");
|
|
89
|
+
}
|
|
90
|
+
this.currentChainId = chainId;
|
|
91
|
+
this.currentConnectedAddress = address;
|
|
92
|
+
return [4 /*yield*/, this.trackEvent(Event.CONNECT, {
|
|
93
|
+
chain_id: chainId,
|
|
94
|
+
address: address,
|
|
95
|
+
})];
|
|
96
|
+
case 1:
|
|
97
|
+
_c.sent();
|
|
98
|
+
return [2 /*return*/];
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
121
102
|
};
|
|
122
|
-
|
|
123
|
-
FormoAnalytics.prototype.trackEvent = function (action, payload) {
|
|
103
|
+
FormoAnalytics.prototype.disconnect = function (params) {
|
|
124
104
|
return __awaiter(this, void 0, void 0, function () {
|
|
125
|
-
var
|
|
126
|
-
var _this = this;
|
|
105
|
+
var address, chainId;
|
|
127
106
|
return __generator(this, function (_a) {
|
|
128
107
|
switch (_a.label) {
|
|
129
108
|
case 0:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.
|
|
133
|
-
apiUrl = this.buildApiUrl();
|
|
134
|
-
return [4 /*yield*/, this.getCurrentWallet()];
|
|
109
|
+
address = (params === null || params === void 0 ? void 0 : params.address) || this.currentConnectedAddress;
|
|
110
|
+
chainId = (params === null || params === void 0 ? void 0 : params.chainId) || this.currentChainId;
|
|
111
|
+
return [4 /*yield*/, this.handleDisconnect(chainId, address)];
|
|
135
112
|
case 1:
|
|
136
|
-
address = _a.sent();
|
|
137
|
-
requestData = {
|
|
138
|
-
project_id: this.projectId,
|
|
139
|
-
address: address,
|
|
140
|
-
session_id: this.getSessionId(),
|
|
141
|
-
timestamp: new Date().toISOString(),
|
|
142
|
-
action: action,
|
|
143
|
-
version: '1',
|
|
144
|
-
payload: isNotEmpty(payload) ? this.maskSensitiveData(payload) : payload,
|
|
145
|
-
};
|
|
146
|
-
sendRequest = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
147
|
-
var response, error_1, retryDelay;
|
|
148
|
-
return __generator(this, function (_a) {
|
|
149
|
-
switch (_a.label) {
|
|
150
|
-
case 0:
|
|
151
|
-
_a.trys.push([0, 2, , 3]);
|
|
152
|
-
return [4 /*yield*/, axios.post(apiUrl, JSON.stringify(requestData), {
|
|
153
|
-
headers: {
|
|
154
|
-
'Content-Type': 'application/json',
|
|
155
|
-
},
|
|
156
|
-
})];
|
|
157
|
-
case 1:
|
|
158
|
-
response = _a.sent();
|
|
159
|
-
if (response.status >= 200 && response.status < 300) {
|
|
160
|
-
console.log('Event sent successfully:', action);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
throw new Error("Failed with status: ".concat(response.status));
|
|
164
|
-
}
|
|
165
|
-
return [3 /*break*/, 3];
|
|
166
|
-
case 2:
|
|
167
|
-
error_1 = _a.sent();
|
|
168
|
-
attempt++;
|
|
169
|
-
if (attempt <= maxRetries) {
|
|
170
|
-
retryDelay = Math.pow(2, attempt) * 1000;
|
|
171
|
-
console.error("Attempt ".concat(attempt, ": Retrying event \"").concat(action, "\" in ").concat(retryDelay / 1000, " seconds..."));
|
|
172
|
-
setTimeout(sendRequest, retryDelay);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
H.consumeError(error_1, "Request data: ".concat(JSON.stringify(requestData)));
|
|
176
|
-
console.error("Event \"".concat(action, "\" failed after ").concat(maxRetries, " attempts. Error: ").concat(error_1));
|
|
177
|
-
}
|
|
178
|
-
return [3 /*break*/, 3];
|
|
179
|
-
case 3: return [2 /*return*/];
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}); };
|
|
183
|
-
return [4 /*yield*/, sendRequest()];
|
|
184
|
-
case 2:
|
|
185
113
|
_a.sent();
|
|
186
114
|
return [2 /*return*/];
|
|
187
115
|
}
|
|
188
116
|
});
|
|
189
117
|
});
|
|
190
118
|
};
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
'phone',
|
|
215
|
-
];
|
|
216
|
-
// Create a new object to store masked data
|
|
217
|
-
var maskedData_1 = __assign({}, parsedData);
|
|
218
|
-
// Mask sensitive fields
|
|
219
|
-
sensitiveFields.forEach(function (field) {
|
|
220
|
-
if (field in maskedData_1) {
|
|
221
|
-
maskedData_1[field] = '********'; // Replace value with masked string
|
|
119
|
+
FormoAnalytics.prototype.chain = function (_a) {
|
|
120
|
+
return __awaiter(this, arguments, void 0, function (_b) {
|
|
121
|
+
var chainId = _b.chainId, address = _b.address;
|
|
122
|
+
return __generator(this, function (_c) {
|
|
123
|
+
switch (_c.label) {
|
|
124
|
+
case 0:
|
|
125
|
+
if (!chainId || Number(chainId) === 0) {
|
|
126
|
+
throw new Error("FormoAnalytics::chain: chainId cannot be empty or 0");
|
|
127
|
+
}
|
|
128
|
+
if (!address && !this.currentConnectedAddress) {
|
|
129
|
+
throw new Error("FormoAnalytics::chain: address was empty and no previous address has been recorded. You can either pass an address or call connect() first");
|
|
130
|
+
}
|
|
131
|
+
if (isNaN(Number(chainId))) {
|
|
132
|
+
throw new Error("FormoAnalytics::chain: chainId must be a valid decimal number");
|
|
133
|
+
}
|
|
134
|
+
this.currentChainId = chainId;
|
|
135
|
+
return [4 /*yield*/, this.trackEvent(Event.CHAIN_CHANGED, {
|
|
136
|
+
chain_id: chainId,
|
|
137
|
+
address: address || this.currentConnectedAddress,
|
|
138
|
+
})];
|
|
139
|
+
case 1:
|
|
140
|
+
_c.sent();
|
|
141
|
+
return [2 /*return*/];
|
|
222
142
|
}
|
|
223
143
|
});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
];
|
|
236
|
-
var maskedData_2 = __assign({}, data);
|
|
237
|
-
// Mask sensitive fields
|
|
238
|
-
sensitiveFields.forEach(function (field) {
|
|
239
|
-
if (field in maskedData_2) {
|
|
240
|
-
maskedData_2[field] = '********'; // Replace value with masked string
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
// TODO: allow custom url as input
|
|
147
|
+
FormoAnalytics.prototype.page = function () {
|
|
148
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
149
|
+
return __generator(this, function (_a) {
|
|
150
|
+
switch (_a.label) {
|
|
151
|
+
case 0: return [4 /*yield*/, this.trackPageHit()];
|
|
152
|
+
case 1:
|
|
153
|
+
_a.sent();
|
|
154
|
+
return [2 /*return*/];
|
|
241
155
|
}
|
|
242
156
|
});
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
return data;
|
|
157
|
+
});
|
|
246
158
|
};
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
location = this.timezoneToCountry[timezone];
|
|
257
|
-
language =
|
|
258
|
-
navigator.languages && navigator.languages.length
|
|
259
|
-
? navigator.languages[0]
|
|
260
|
-
: navigator.language || 'en';
|
|
261
|
-
}
|
|
262
|
-
catch (error) {
|
|
263
|
-
console.error('Error resolving timezone or language:', error);
|
|
264
|
-
}
|
|
265
|
-
setTimeout(function () {
|
|
266
|
-
var url = new URL(window.location.href);
|
|
267
|
-
var params = new URLSearchParams(url.search);
|
|
268
|
-
_this.trackEvent(Event.PAGE, {
|
|
269
|
-
'user-agent': window.navigator.userAgent,
|
|
270
|
-
locale: language,
|
|
271
|
-
location: location,
|
|
272
|
-
referrer: document.referrer,
|
|
273
|
-
pathname: window.location.pathname,
|
|
274
|
-
href: window.location.href,
|
|
275
|
-
utm_source: params.get('utm_source'),
|
|
276
|
-
utm_medium: params.get('utm_medium'),
|
|
277
|
-
utm_campaign: params.get('utm_campaign'),
|
|
278
|
-
ref: params.get('ref'),
|
|
159
|
+
FormoAnalytics.prototype.track = function (eventName, eventData) {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
161
|
+
return __generator(this, function (_a) {
|
|
162
|
+
switch (_a.label) {
|
|
163
|
+
case 0: return [4 /*yield*/, this.trackEvent(eventName, eventData)];
|
|
164
|
+
case 1:
|
|
165
|
+
_a.sent();
|
|
166
|
+
return [2 /*return*/];
|
|
167
|
+
}
|
|
279
168
|
});
|
|
280
|
-
}
|
|
169
|
+
});
|
|
281
170
|
};
|
|
171
|
+
/*
|
|
172
|
+
SDK tracking and event listener functions
|
|
173
|
+
*/
|
|
282
174
|
FormoAnalytics.prototype.trackProvider = function (provider) {
|
|
283
175
|
if (provider === this._provider) {
|
|
176
|
+
console.log("Provider already tracked.");
|
|
284
177
|
return;
|
|
285
178
|
}
|
|
286
179
|
this.currentChainId = undefined;
|
|
287
|
-
this.
|
|
180
|
+
this.currentConnectedAddress = undefined;
|
|
288
181
|
if (this._provider) {
|
|
289
|
-
var eventNames = Object.keys(this.
|
|
182
|
+
var eventNames = Object.keys(this._providerListeners);
|
|
290
183
|
for (var _i = 0, eventNames_1 = eventNames; _i < eventNames_1.length; _i++) {
|
|
291
184
|
var eventName = eventNames_1[_i];
|
|
292
|
-
this._provider.removeListener(eventName, this.
|
|
293
|
-
delete this.
|
|
185
|
+
this._provider.removeListener(eventName, this._providerListeners[eventName]);
|
|
186
|
+
delete this._providerListeners[eventName];
|
|
294
187
|
}
|
|
295
188
|
}
|
|
189
|
+
console.log("Tracking new provider:", provider);
|
|
296
190
|
this._provider = provider;
|
|
297
|
-
this.
|
|
298
|
-
this.
|
|
191
|
+
this.getAddress();
|
|
192
|
+
this.registerAddressChangedListener();
|
|
299
193
|
this.registerChainChangedListener();
|
|
194
|
+
// TODO: track signing and transactions
|
|
195
|
+
// https://linear.app/getformo/issue/P-607/sdk-support-signature-and-transaction-events
|
|
196
|
+
};
|
|
197
|
+
FormoAnalytics.prototype.registerAddressChangedListener = function () {
|
|
198
|
+
var _this = this;
|
|
199
|
+
var _a, _b;
|
|
200
|
+
var listener = function () {
|
|
201
|
+
var args = [];
|
|
202
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
203
|
+
args[_i] = arguments[_i];
|
|
204
|
+
}
|
|
205
|
+
return _this.onAddressChanged(args[0]);
|
|
206
|
+
};
|
|
207
|
+
(_a = this._provider) === null || _a === void 0 ? void 0 : _a.on("accountsChanged", listener);
|
|
208
|
+
this._providerListeners["accountsChanged"] = listener;
|
|
209
|
+
var onAddressDisconnected = this.onAddressDisconnected.bind(this);
|
|
210
|
+
(_b = this._provider) === null || _b === void 0 ? void 0 : _b.on("disconnect", onAddressDisconnected);
|
|
211
|
+
this._providerListeners["disconnect"] = onAddressDisconnected;
|
|
300
212
|
};
|
|
301
213
|
FormoAnalytics.prototype.registerChainChangedListener = function () {
|
|
302
214
|
var _this = this;
|
|
@@ -308,264 +220,326 @@ var FormoAnalytics = /** @class */ (function () {
|
|
|
308
220
|
}
|
|
309
221
|
return _this.onChainChanged(args[0]);
|
|
310
222
|
};
|
|
311
|
-
(_a = this.provider) === null || _a === void 0 ? void 0 : _a.on(
|
|
312
|
-
this.
|
|
223
|
+
(_a = this.provider) === null || _a === void 0 ? void 0 : _a.on("chainChanged", listener);
|
|
224
|
+
this._providerListeners["chainChanged"] = listener;
|
|
313
225
|
};
|
|
314
|
-
FormoAnalytics.prototype.
|
|
315
|
-
|
|
316
|
-
return
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
226
|
+
FormoAnalytics.prototype.onAddressChanged = function (addresses) {
|
|
227
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
228
|
+
return __generator(this, function (_a) {
|
|
229
|
+
if (addresses.length > 0) {
|
|
230
|
+
this.onAddressConnected(addresses[0]);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
this.onAddressDisconnected();
|
|
234
|
+
}
|
|
235
|
+
return [2 /*return*/];
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
FormoAnalytics.prototype.onAddressConnected = function (address) {
|
|
240
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
241
|
+
var _a;
|
|
242
|
+
return __generator(this, function (_b) {
|
|
243
|
+
switch (_b.label) {
|
|
244
|
+
case 0:
|
|
245
|
+
if (address === this.currentConnectedAddress) {
|
|
246
|
+
// We have already reported this address
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.currentConnectedAddress = address;
|
|
251
|
+
}
|
|
252
|
+
_a = this;
|
|
253
|
+
return [4 /*yield*/, this.getCurrentChainId()];
|
|
254
|
+
case 1:
|
|
255
|
+
_a.currentChainId = _b.sent();
|
|
256
|
+
this.connect({ chainId: this.currentChainId, address: address });
|
|
257
|
+
return [2 /*return*/];
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
FormoAnalytics.prototype.handleDisconnect = function (chainId, address) {
|
|
263
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
264
|
+
var payload;
|
|
265
|
+
return __generator(this, function (_a) {
|
|
266
|
+
switch (_a.label) {
|
|
267
|
+
case 0:
|
|
268
|
+
payload = {
|
|
269
|
+
chain_id: chainId || this.currentChainId,
|
|
270
|
+
address: address || this.currentConnectedAddress,
|
|
271
|
+
};
|
|
272
|
+
this.currentChainId = undefined;
|
|
273
|
+
this.currentConnectedAddress = undefined;
|
|
274
|
+
return [4 /*yield*/, this.trackEvent(Event.DISCONNECT, payload)];
|
|
275
|
+
case 1:
|
|
276
|
+
_a.sent();
|
|
277
|
+
return [2 /*return*/];
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
};
|
|
282
|
+
FormoAnalytics.prototype.onAddressDisconnected = function () {
|
|
283
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
284
|
+
return __generator(this, function (_a) {
|
|
285
|
+
switch (_a.label) {
|
|
286
|
+
case 0: return [4 /*yield*/, this.handleDisconnect(this.currentChainId, this.currentConnectedAddress)];
|
|
287
|
+
case 1:
|
|
288
|
+
_a.sent();
|
|
289
|
+
return [2 /*return*/];
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
326
293
|
};
|
|
327
294
|
FormoAnalytics.prototype.onChainChanged = function (chainIdHex) {
|
|
328
295
|
return __awaiter(this, void 0, void 0, function () {
|
|
329
|
-
var
|
|
296
|
+
var address;
|
|
330
297
|
return __generator(this, function (_a) {
|
|
331
298
|
switch (_a.label) {
|
|
332
299
|
case 0:
|
|
333
|
-
this.currentChainId = parseInt(chainIdHex)
|
|
334
|
-
if (!!this.
|
|
300
|
+
this.currentChainId = parseInt(chainIdHex);
|
|
301
|
+
if (!!this.currentConnectedAddress) return [3 /*break*/, 2];
|
|
335
302
|
if (!this.provider) {
|
|
336
|
-
console.
|
|
337
|
-
return [2 /*return
|
|
303
|
+
console.log("FormoAnalytics::onChainChanged: provider not found. CHAIN_CHANGED not reported");
|
|
304
|
+
return [2 /*return*/, Promise.resolve()];
|
|
338
305
|
}
|
|
339
|
-
|
|
306
|
+
return [4 /*yield*/, this.getAddress()];
|
|
340
307
|
case 1:
|
|
341
|
-
_a.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
308
|
+
address = _a.sent();
|
|
309
|
+
if (!address) {
|
|
310
|
+
console.log("FormoAnalytics::onChainChanged: Unable to fetch or store connected address");
|
|
311
|
+
return [2 /*return*/, Promise.resolve()];
|
|
312
|
+
}
|
|
313
|
+
this.currentConnectedAddress = address[0];
|
|
314
|
+
_a.label = 2;
|
|
345
315
|
case 2:
|
|
346
|
-
|
|
347
|
-
if (
|
|
348
|
-
|
|
349
|
-
|
|
316
|
+
// Proceed only if the address exists
|
|
317
|
+
if (this.currentConnectedAddress) {
|
|
318
|
+
return [2 /*return*/, this.chain({
|
|
319
|
+
chainId: this.currentChainId,
|
|
320
|
+
address: this.currentConnectedAddress,
|
|
321
|
+
})];
|
|
350
322
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
case 3:
|
|
354
|
-
err_1 = _a.sent();
|
|
355
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
356
|
-
if (err_1.code !== 4001) {
|
|
357
|
-
// 4001: The request is rejected by the user , see https://docs.metamask.io/wallet/reference/provider-api/#errors
|
|
358
|
-
console.error('error', "FormoAnalytics::onChainChanged: unable to get account. eth_accounts threw an error", err_1);
|
|
359
|
-
return [2 /*return*/];
|
|
323
|
+
else {
|
|
324
|
+
console.log("FormoAnalytics::onChainChanged: currentConnectedAddress is null despite fetch attempt");
|
|
360
325
|
}
|
|
361
|
-
return [
|
|
362
|
-
case 4: return [2 /*return*/, this.chain({
|
|
363
|
-
chainId: this.currentChainId,
|
|
364
|
-
account: this.currentConnectedAccount,
|
|
365
|
-
})];
|
|
326
|
+
return [2 /*return*/];
|
|
366
327
|
}
|
|
367
328
|
});
|
|
368
329
|
});
|
|
369
330
|
};
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
331
|
+
// TOFIX: support multiple page hit events
|
|
332
|
+
// TODO: Add event listener and support for SPA and hash-based navigation
|
|
333
|
+
// https://linear.app/getformo/issue/P-800/sdk-support-spa-and-hash-based-routing
|
|
334
|
+
FormoAnalytics.prototype.trackPageHit = function () {
|
|
335
|
+
var _this = this;
|
|
336
|
+
var pathname = window.location.pathname;
|
|
337
|
+
var href = window.location.href;
|
|
338
|
+
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
373
339
|
return __generator(this, function (_a) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
this.handleAccountDisconnected();
|
|
382
|
-
}
|
|
340
|
+
this.trackEvent(Event.PAGE, {
|
|
341
|
+
pathname: pathname,
|
|
342
|
+
href: href,
|
|
343
|
+
});
|
|
383
344
|
return [2 /*return*/];
|
|
384
345
|
});
|
|
385
|
-
});
|
|
386
|
-
};
|
|
387
|
-
FormoAnalytics.prototype.registerAccountsChangedListener = function () {
|
|
388
|
-
var _this = this;
|
|
389
|
-
var _a, _b;
|
|
390
|
-
var listener = function () {
|
|
391
|
-
var args = [];
|
|
392
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
393
|
-
args[_i] = arguments[_i];
|
|
394
|
-
}
|
|
395
|
-
return _this.onAccountsChanged(args[0]);
|
|
396
|
-
};
|
|
397
|
-
(_a = this._provider) === null || _a === void 0 ? void 0 : _a.on('accountsChanged', listener);
|
|
398
|
-
this._registeredProviderListeners['accountsChanged'] = listener;
|
|
399
|
-
var handleAccountDisconnected = this.handleAccountDisconnected.bind(this);
|
|
400
|
-
(_b = this._provider) === null || _b === void 0 ? void 0 : _b.on('disconnect', handleAccountDisconnected);
|
|
401
|
-
this._registeredProviderListeners['disconnect'] = handleAccountDisconnected;
|
|
346
|
+
}); }, 300);
|
|
402
347
|
};
|
|
403
|
-
|
|
348
|
+
// TODO: refactor this with event queue and flushing
|
|
349
|
+
// https://linear.app/getformo/issue/P-835/sdk-refactor-retries-with-event-queue-and-batching
|
|
350
|
+
FormoAnalytics.prototype.trackEvent = function (action, payload) {
|
|
404
351
|
return __awaiter(this, void 0, void 0, function () {
|
|
405
|
-
var
|
|
352
|
+
var address, requestData, response, error_1;
|
|
406
353
|
var _a;
|
|
407
354
|
return __generator(this, function (_b) {
|
|
408
355
|
switch (_b.label) {
|
|
356
|
+
case 0: return [4 /*yield*/, this.getAddress()];
|
|
357
|
+
case 1:
|
|
358
|
+
address = _b.sent();
|
|
359
|
+
_a = {
|
|
360
|
+
address: address,
|
|
361
|
+
timestamp: new Date().toISOString(),
|
|
362
|
+
action: action,
|
|
363
|
+
version: "1"
|
|
364
|
+
};
|
|
365
|
+
return [4 /*yield*/, this.buildEventPayload(payload)];
|
|
366
|
+
case 2:
|
|
367
|
+
requestData = (_a.payload = _b.sent(),
|
|
368
|
+
_a);
|
|
369
|
+
_b.label = 3;
|
|
370
|
+
case 3:
|
|
371
|
+
_b.trys.push([3, 5, , 6]);
|
|
372
|
+
return [4 /*yield*/, axios.post(EVENTS_API_URL, JSON.stringify(requestData), {
|
|
373
|
+
headers: {
|
|
374
|
+
"Content-Type": "application/json",
|
|
375
|
+
Authorization: "Bearer ".concat(this.config.apiKey),
|
|
376
|
+
},
|
|
377
|
+
})];
|
|
378
|
+
case 4:
|
|
379
|
+
response = _b.sent();
|
|
380
|
+
if (response.status >= 200 && response.status < 300) {
|
|
381
|
+
console.log("Event sent successfully:", action);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
throw new Error("Failed with status: ".concat(response.status));
|
|
385
|
+
}
|
|
386
|
+
return [3 /*break*/, 6];
|
|
387
|
+
case 5:
|
|
388
|
+
error_1 = _b.sent();
|
|
389
|
+
H.consumeError(error_1, "Request data: ".concat(JSON.stringify(requestData)));
|
|
390
|
+
console.error("Event \"".concat(action, "\" failed. Error: ").concat(error_1));
|
|
391
|
+
return [3 /*break*/, 6];
|
|
392
|
+
case 6: return [2 /*return*/];
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
Object.defineProperty(FormoAnalytics.prototype, "provider", {
|
|
398
|
+
/*
|
|
399
|
+
Utility functions
|
|
400
|
+
*/
|
|
401
|
+
get: function () {
|
|
402
|
+
return this._provider;
|
|
403
|
+
},
|
|
404
|
+
enumerable: false,
|
|
405
|
+
configurable: true
|
|
406
|
+
});
|
|
407
|
+
FormoAnalytics.prototype.getAddress = function () {
|
|
408
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
409
|
+
var accounts, address, err_1;
|
|
410
|
+
return __generator(this, function (_a) {
|
|
411
|
+
switch (_a.label) {
|
|
409
412
|
case 0:
|
|
410
413
|
if (!this.provider) {
|
|
411
|
-
console.
|
|
414
|
+
console.log("FormoAnalytics::getAddress: the provider is not set");
|
|
415
|
+
return [2 /*return*/, null];
|
|
412
416
|
}
|
|
413
|
-
|
|
414
|
-
method: 'eth_chainId',
|
|
415
|
-
}))];
|
|
417
|
+
_a.label = 1;
|
|
416
418
|
case 1:
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
_a.trys.push([1, 3, , 4]);
|
|
420
|
+
return [4 /*yield*/, this.getAccounts()];
|
|
421
|
+
case 2:
|
|
422
|
+
accounts = _a.sent();
|
|
423
|
+
if (accounts && accounts.length > 0) {
|
|
424
|
+
address = accounts[0];
|
|
425
|
+
// TODO: how to handle multiple addresses? Should we emit a connect event here? Since the user has not manually connected
|
|
426
|
+
// https://linear.app/getformo/issue/P-691/sdk-detect-multiple-wallets-using-eip6963
|
|
427
|
+
this.onAddressConnected(address);
|
|
428
|
+
return [2 /*return*/, address];
|
|
421
429
|
}
|
|
422
|
-
return [
|
|
430
|
+
return [3 /*break*/, 4];
|
|
431
|
+
case 3:
|
|
432
|
+
err_1 = _a.sent();
|
|
433
|
+
console.log("Failed to fetch accounts from provider:", err_1);
|
|
434
|
+
return [2 /*return*/, null];
|
|
435
|
+
case 4: return [2 /*return*/, null];
|
|
423
436
|
}
|
|
424
437
|
});
|
|
425
438
|
});
|
|
426
439
|
};
|
|
427
|
-
FormoAnalytics.prototype.
|
|
440
|
+
FormoAnalytics.prototype.getAccounts = function () {
|
|
428
441
|
return __awaiter(this, void 0, void 0, function () {
|
|
442
|
+
var res, err_2;
|
|
429
443
|
var _a;
|
|
430
444
|
return __generator(this, function (_b) {
|
|
431
445
|
switch (_b.label) {
|
|
432
446
|
case 0:
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
447
|
+
_b.trys.push([0, 2, , 3]);
|
|
448
|
+
return [4 /*yield*/, ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.request({
|
|
449
|
+
method: "eth_accounts",
|
|
450
|
+
}))];
|
|
451
|
+
case 1:
|
|
452
|
+
res = _b.sent();
|
|
453
|
+
if (!res || res.length === 0) {
|
|
454
|
+
console.log("FormoAnalytics::getAccounts: unable to get account. eth_accounts returned empty");
|
|
455
|
+
return [2 /*return*/, null];
|
|
436
456
|
}
|
|
437
|
-
|
|
438
|
-
|
|
457
|
+
return [2 /*return*/, res];
|
|
458
|
+
case 2:
|
|
459
|
+
err_2 = _b.sent();
|
|
460
|
+
if (err_2.code !== 4001) {
|
|
461
|
+
console.log("FormoAnalytics::getAccounts: eth_accounts threw an error", err_2);
|
|
439
462
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
case 1:
|
|
443
|
-
_a.currentChainId = _b.sent();
|
|
444
|
-
this.connect({ account: account, chainId: this.currentChainId });
|
|
445
|
-
this.storeWalletAddress(account);
|
|
446
|
-
return [2 /*return*/];
|
|
463
|
+
return [2 /*return*/, null];
|
|
464
|
+
case 3: return [2 /*return*/];
|
|
447
465
|
}
|
|
448
466
|
});
|
|
449
467
|
});
|
|
450
468
|
};
|
|
451
|
-
FormoAnalytics.prototype.
|
|
469
|
+
FormoAnalytics.prototype.getCurrentChainId = function () {
|
|
452
470
|
return __awaiter(this, void 0, void 0, function () {
|
|
453
|
-
var
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
471
|
+
var chainIdHex, err_3;
|
|
472
|
+
var _a;
|
|
473
|
+
return __generator(this, function (_b) {
|
|
474
|
+
switch (_b.label) {
|
|
475
|
+
case 0:
|
|
476
|
+
if (!this.provider) {
|
|
477
|
+
console.error("FormoAnalytics::getCurrentChainId: provider not set");
|
|
478
|
+
}
|
|
479
|
+
_b.label = 1;
|
|
480
|
+
case 1:
|
|
481
|
+
_b.trys.push([1, 3, , 4]);
|
|
482
|
+
return [4 /*yield*/, ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.request({
|
|
483
|
+
method: "eth_chainId",
|
|
484
|
+
}))];
|
|
485
|
+
case 2:
|
|
486
|
+
chainIdHex = _b.sent();
|
|
487
|
+
if (!chainIdHex) {
|
|
488
|
+
console.log("FormoAnalytics::fetchChainId: chain id not found");
|
|
489
|
+
return [2 /*return*/, 0];
|
|
490
|
+
}
|
|
491
|
+
return [2 /*return*/, parseInt(chainIdHex, 16)];
|
|
492
|
+
case 3:
|
|
493
|
+
err_3 = _b.sent();
|
|
494
|
+
console.log("FormoAnalytics::fetchChainId: eth_chainId threw an error", err_3);
|
|
495
|
+
return [2 /*return*/, 0];
|
|
496
|
+
case 4: return [2 /*return*/];
|
|
470
497
|
}
|
|
471
|
-
this.handleAccountConnected(parsedData.address);
|
|
472
|
-
return [2 /*return*/, parsedData.address || ''];
|
|
473
498
|
});
|
|
474
499
|
});
|
|
475
500
|
};
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
FormoAnalytics.prototype.storeWalletAddress = function (address) {
|
|
481
|
-
if (!address) {
|
|
482
|
-
console.error('No wallet address provided to store.');
|
|
483
|
-
return;
|
|
501
|
+
FormoAnalytics.prototype.getLocation = function () {
|
|
502
|
+
try {
|
|
503
|
+
var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
504
|
+
return COUNTRY_LIST[timezone];
|
|
484
505
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
};
|
|
489
|
-
sessionStorage.setItem(this.sessionKey, JSON.stringify(sessionData));
|
|
490
|
-
};
|
|
491
|
-
/**
|
|
492
|
-
* Clears the wallet address from session storage when disconnected.
|
|
493
|
-
*/
|
|
494
|
-
FormoAnalytics.prototype.clearWalletAddress = function () {
|
|
495
|
-
sessionStorage.removeItem(this.sessionKey);
|
|
496
|
-
};
|
|
497
|
-
// Function to build the API URL
|
|
498
|
-
FormoAnalytics.prototype.buildApiUrl = function () {
|
|
499
|
-
var _a = this.config, host = _a.host, proxy = _a.proxy, token = _a.token, _b = _a.dataSource, dataSource = _b === void 0 ? 'analytics_events' : _b;
|
|
500
|
-
if (token) {
|
|
501
|
-
if (proxy) {
|
|
502
|
-
return "".concat(proxy, "/api/tracking");
|
|
503
|
-
}
|
|
504
|
-
if (host) {
|
|
505
|
-
return "".concat(host.replace(/\/+$/, ''), "/v0/events?name=").concat(dataSource, "&token=").concat(token);
|
|
506
|
-
}
|
|
507
|
-
return "".concat(EVENTS_API, "?name=").concat(dataSource, "&token=").concat(token);
|
|
506
|
+
catch (error) {
|
|
507
|
+
console.error("Error resolving timezone:", error);
|
|
508
|
+
return undefined;
|
|
508
509
|
}
|
|
509
|
-
return 'Error: No token provided';
|
|
510
510
|
};
|
|
511
|
-
FormoAnalytics.prototype.
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
if (!account) {
|
|
517
|
-
throw new Error('FormoAnalytics::connect: account cannot be empty');
|
|
511
|
+
FormoAnalytics.prototype.getLanguage = function () {
|
|
512
|
+
try {
|
|
513
|
+
return ((navigator.languages && navigator.languages.length
|
|
514
|
+
? navigator.languages[0]
|
|
515
|
+
: navigator.language) || "en");
|
|
518
516
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
chainId: chainId,
|
|
523
|
-
address: account,
|
|
524
|
-
});
|
|
525
|
-
};
|
|
526
|
-
FormoAnalytics.prototype.disconnect = function (attributes) {
|
|
527
|
-
var account = (attributes === null || attributes === void 0 ? void 0 : attributes.account) || this.currentConnectedAccount;
|
|
528
|
-
if (!account) {
|
|
529
|
-
// We have most likely already reported this disconnection with the automatic
|
|
530
|
-
// `disconnect` detection
|
|
531
|
-
return;
|
|
517
|
+
catch (error) {
|
|
518
|
+
console.error("Error resolving language:", error);
|
|
519
|
+
return "en";
|
|
532
520
|
}
|
|
533
|
-
var chainId = (attributes === null || attributes === void 0 ? void 0 : attributes.chainId) || this.currentChainId;
|
|
534
|
-
var eventAttributes = __assign({ account: account }, (chainId && { chainId: chainId }));
|
|
535
|
-
this.currentChainId = undefined;
|
|
536
|
-
this.currentConnectedAccount = undefined;
|
|
537
|
-
return this.trackEvent(Event.DISCONNECT, eventAttributes);
|
|
538
521
|
};
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
522
|
+
// Adds browser properties to the user-supplied payload
|
|
523
|
+
FormoAnalytics.prototype.buildEventPayload = function () {
|
|
524
|
+
return __awaiter(this, arguments, void 0, function (eventSpecificPayload) {
|
|
525
|
+
var url, params, location, language, address;
|
|
526
|
+
if (eventSpecificPayload === void 0) { eventSpecificPayload = {}; }
|
|
527
|
+
return __generator(this, function (_a) {
|
|
528
|
+
switch (_a.label) {
|
|
529
|
+
case 0:
|
|
530
|
+
url = new URL(window.location.href);
|
|
531
|
+
params = new URLSearchParams(url.search);
|
|
532
|
+
location = this.getLocation();
|
|
533
|
+
language = this.getLanguage();
|
|
534
|
+
return [4 /*yield*/, this.getAddress()];
|
|
535
|
+
case 1:
|
|
536
|
+
address = _a.sent();
|
|
537
|
+
// common browser properties
|
|
538
|
+
return [2 /*return*/, __assign({ "user-agent": window.navigator.userAgent, address: address, locale: language, location: location, referrer: document.referrer, utm_source: params.get("utm_source"), utm_medium: params.get("utm_medium"), utm_campaign: params.get("utm_campaign"), ref: params.get("ref") }, eventSpecificPayload)];
|
|
539
|
+
}
|
|
540
|
+
});
|
|
554
541
|
});
|
|
555
542
|
};
|
|
556
|
-
FormoAnalytics.prototype.init = function (apiKey, projectId) {
|
|
557
|
-
var instance = new FormoAnalytics(apiKey, projectId);
|
|
558
|
-
return Promise.resolve(instance);
|
|
559
|
-
};
|
|
560
|
-
FormoAnalytics.prototype.identify = function (userData) {
|
|
561
|
-
this.identifyUser(userData);
|
|
562
|
-
};
|
|
563
|
-
FormoAnalytics.prototype.page = function () {
|
|
564
|
-
this.trackPageHit();
|
|
565
|
-
};
|
|
566
|
-
FormoAnalytics.prototype.track = function (eventName, eventData) {
|
|
567
|
-
this.trackEvent(eventName, eventData);
|
|
568
|
-
};
|
|
569
543
|
return FormoAnalytics;
|
|
570
544
|
}());
|
|
571
545
|
export { FormoAnalytics };
|