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