@dashgram/javascript 1.0.0 → 1.0.2
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/README.md +117 -174
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +5 -4
- package/dist/core/context.d.ts +4 -8
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +6 -17
- package/dist/core/event-queue.d.ts +4 -4
- package/dist/core/event-queue.d.ts.map +1 -1
- package/dist/dashgram.min.js +2 -0
- package/dist/dashgram.min.js.map +1 -0
- package/dist/errors.d.ts +0 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +0 -10
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -32
- package/dist/trackers/base-tracker.d.ts +3 -3
- package/dist/trackers/base-tracker.d.ts.map +1 -1
- package/dist/trackers/base-tracker.js +1 -4
- package/dist/trackers/core-tracker.d.ts +3 -3
- package/dist/trackers/core-tracker.d.ts.map +1 -1
- package/dist/trackers/core-tracker.js +19 -21
- package/dist/trackers/deep-tracker.d.ts +6 -0
- package/dist/trackers/deep-tracker.d.ts.map +1 -1
- package/dist/trackers/deep-tracker.js +562 -12
- package/dist/trackers/interaction-tracker.d.ts +7 -3
- package/dist/trackers/interaction-tracker.d.ts.map +1 -1
- package/dist/trackers/interaction-tracker.js +142 -37
- package/dist/transport/batch-processor.d.ts +4 -4
- package/dist/transport/batch-processor.d.ts.map +1 -1
- package/dist/transport/batch-processor.js +8 -8
- package/dist/transport/transport.d.ts +4 -3
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/transport/transport.js +17 -24
- package/dist/types/index.d.ts +100 -25
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/device.d.ts +3 -7
- package/dist/utils/device.d.ts.map +1 -1
- package/dist/utils/device.js +19 -53
- package/dist/utils/telegram.d.ts +4 -6
- package/dist/utils/telegram.d.ts.map +1 -1
- package/dist/utils/telegram.js +45 -29
- package/package.json +9 -3
- package/dist/core/session.d.ts +0 -13
- package/dist/core/session.d.ts.map +0 -1
- package/dist/core/session.js +0 -63
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { BaseTracker } from
|
|
2
|
-
import { throttle } from
|
|
3
|
-
import { getElementSelector, getElementText } from
|
|
4
|
-
import { getCurrentPath, getPageTitle, getCurrentUrl } from
|
|
1
|
+
import { BaseTracker } from "./base-tracker";
|
|
2
|
+
import { throttle } from "../utils/helpers";
|
|
3
|
+
import { getElementSelector, getElementText } from "../utils/helpers";
|
|
4
|
+
import { getCurrentPath, getPageTitle, getCurrentUrl } from "../utils/device";
|
|
5
5
|
export class InteractionTracker extends BaseTracker {
|
|
6
6
|
constructor(config, trackCallback) {
|
|
7
7
|
super(config, trackCallback, 2);
|
|
8
8
|
this.unsubscribers = [];
|
|
9
|
-
this.lastPath =
|
|
9
|
+
this.lastPath = "";
|
|
10
|
+
this.inputValues = new Map();
|
|
10
11
|
}
|
|
11
12
|
setup() {
|
|
12
|
-
if (typeof window ===
|
|
13
|
+
if (typeof window === "undefined") {
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
16
|
this.trackScreenView();
|
|
@@ -17,10 +18,12 @@ export class InteractionTracker extends BaseTracker {
|
|
|
17
18
|
this.setupClickTracking();
|
|
18
19
|
this.setupFormTracking();
|
|
19
20
|
this.setupInputTracking();
|
|
21
|
+
this.setupClipboardTracking();
|
|
22
|
+
this.setupSelectionTracking();
|
|
20
23
|
this.setupErrorTracking();
|
|
21
24
|
}
|
|
22
25
|
teardown() {
|
|
23
|
-
this.unsubscribers.forEach(
|
|
26
|
+
this.unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
24
27
|
this.unsubscribers = [];
|
|
25
28
|
}
|
|
26
29
|
trackScreenView() {
|
|
@@ -29,11 +32,11 @@ export class InteractionTracker extends BaseTracker {
|
|
|
29
32
|
return;
|
|
30
33
|
}
|
|
31
34
|
this.lastPath = path;
|
|
32
|
-
this.track(
|
|
35
|
+
this.track("screen_view", {
|
|
33
36
|
path,
|
|
34
37
|
url: getCurrentUrl(),
|
|
35
38
|
title: getPageTitle(),
|
|
36
|
-
referrer: document.referrer ||
|
|
39
|
+
referrer: document.referrer || "direct"
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
setupHistoryTracking() {
|
|
@@ -50,11 +53,11 @@ export class InteractionTracker extends BaseTracker {
|
|
|
50
53
|
originalReplaceState.apply(history, args);
|
|
51
54
|
trackOnHistoryChange();
|
|
52
55
|
};
|
|
53
|
-
window.addEventListener(
|
|
56
|
+
window.addEventListener("popstate", trackOnHistoryChange);
|
|
54
57
|
this.unsubscribers.push(() => {
|
|
55
58
|
history.pushState = originalPushState;
|
|
56
59
|
history.replaceState = originalReplaceState;
|
|
57
|
-
window.removeEventListener(
|
|
60
|
+
window.removeEventListener("popstate", trackOnHistoryChange);
|
|
58
61
|
});
|
|
59
62
|
}
|
|
60
63
|
setupClickTracking() {
|
|
@@ -65,35 +68,57 @@ export class InteractionTracker extends BaseTracker {
|
|
|
65
68
|
const button = target.closest('button, [role="button"], a');
|
|
66
69
|
if (button) {
|
|
67
70
|
const tagName = button.tagName.toLowerCase();
|
|
68
|
-
const isLink = tagName ===
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
href
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const isLink = tagName === "a";
|
|
72
|
+
if (isLink) {
|
|
73
|
+
const anchor = button;
|
|
74
|
+
const href = anchor.href;
|
|
75
|
+
const isExternal = href ? this.isExternalLink(href) : false;
|
|
76
|
+
this.track("link_click", {
|
|
77
|
+
element: getElementSelector(button),
|
|
78
|
+
text: getElementText(button),
|
|
79
|
+
href: href || undefined,
|
|
80
|
+
target: anchor.target || undefined,
|
|
81
|
+
is_external: isExternal,
|
|
82
|
+
is_download: anchor.hasAttribute("download")
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.track("button_click", {
|
|
87
|
+
element: getElementSelector(button),
|
|
88
|
+
text: getElementText(button)
|
|
89
|
+
});
|
|
90
|
+
}
|
|
75
91
|
}
|
|
76
92
|
};
|
|
77
|
-
document.addEventListener(
|
|
93
|
+
document.addEventListener("click", handleClick, { capture: true });
|
|
78
94
|
this.unsubscribers.push(() => {
|
|
79
|
-
document.removeEventListener(
|
|
95
|
+
document.removeEventListener("click", handleClick, { capture: true });
|
|
80
96
|
});
|
|
81
97
|
}
|
|
98
|
+
isExternalLink(url) {
|
|
99
|
+
try {
|
|
100
|
+
const linkUrl = new URL(url, window.location.href);
|
|
101
|
+
return linkUrl.origin !== window.location.origin;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
82
107
|
setupFormTracking() {
|
|
83
108
|
const handleSubmit = (event) => {
|
|
84
109
|
const form = event.target;
|
|
85
110
|
if (!form)
|
|
86
111
|
return;
|
|
87
|
-
this.track(
|
|
112
|
+
this.track("form_submit", {
|
|
88
113
|
form_id: form.id || undefined,
|
|
89
114
|
form_name: form.name || undefined,
|
|
90
115
|
form_action: form.action || undefined,
|
|
91
|
-
form_method: form.method || undefined
|
|
116
|
+
form_method: form.method || undefined
|
|
92
117
|
});
|
|
93
118
|
};
|
|
94
|
-
document.addEventListener(
|
|
119
|
+
document.addEventListener("submit", handleSubmit, { capture: true });
|
|
95
120
|
this.unsubscribers.push(() => {
|
|
96
|
-
document.removeEventListener(
|
|
121
|
+
document.removeEventListener("submit", handleSubmit, { capture: true });
|
|
97
122
|
});
|
|
98
123
|
}
|
|
99
124
|
setupInputTracking() {
|
|
@@ -102,44 +127,124 @@ export class InteractionTracker extends BaseTracker {
|
|
|
102
127
|
if (!target)
|
|
103
128
|
return;
|
|
104
129
|
const tagName = target.tagName.toLowerCase();
|
|
105
|
-
if ([
|
|
130
|
+
if (["input", "textarea", "select"].includes(tagName)) {
|
|
106
131
|
const input = target;
|
|
107
|
-
this.
|
|
132
|
+
this.inputValues.set(target, input.value || "");
|
|
133
|
+
this.track("input_focus", {
|
|
108
134
|
element: getElementSelector(input),
|
|
109
135
|
input_type: input.type || tagName,
|
|
110
136
|
input_name: input.name || undefined,
|
|
111
|
-
input_id: input.id || undefined
|
|
137
|
+
input_id: input.id || undefined
|
|
112
138
|
});
|
|
113
139
|
}
|
|
114
140
|
}, 1000);
|
|
115
|
-
|
|
141
|
+
const handleBlur = (event) => {
|
|
142
|
+
const target = event.target;
|
|
143
|
+
if (!target)
|
|
144
|
+
return;
|
|
145
|
+
const tagName = target.tagName.toLowerCase();
|
|
146
|
+
if (["input", "textarea", "select"].includes(tagName)) {
|
|
147
|
+
const input = target;
|
|
148
|
+
const previousValue = this.inputValues.get(target);
|
|
149
|
+
const currentValue = input.value || "";
|
|
150
|
+
if (previousValue !== undefined && previousValue !== currentValue) {
|
|
151
|
+
this.track("input_change", {
|
|
152
|
+
element: getElementSelector(input),
|
|
153
|
+
input_type: input.type || tagName,
|
|
154
|
+
input_name: input.name || undefined,
|
|
155
|
+
input_id: input.id || undefined,
|
|
156
|
+
had_value: previousValue.length > 0,
|
|
157
|
+
has_value: currentValue.length > 0
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
this.inputValues.delete(target);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
document.addEventListener("focus", handleFocus, { capture: true });
|
|
164
|
+
document.addEventListener("blur", handleBlur, { capture: true });
|
|
165
|
+
this.unsubscribers.push(() => {
|
|
166
|
+
document.removeEventListener("focus", handleFocus, { capture: true });
|
|
167
|
+
document.removeEventListener("blur", handleBlur, { capture: true });
|
|
168
|
+
this.inputValues.clear();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
setupClipboardTracking() {
|
|
172
|
+
const handleCopy = (_event) => {
|
|
173
|
+
const selection = window.getSelection();
|
|
174
|
+
const selectedText = selection?.toString() || "";
|
|
175
|
+
this.track("copy", {
|
|
176
|
+
text_length: selectedText.length,
|
|
177
|
+
has_selection: selectedText.length > 0
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
const handleCut = (_event) => {
|
|
181
|
+
const selection = window.getSelection();
|
|
182
|
+
const selectedText = selection?.toString() || "";
|
|
183
|
+
this.track("cut", {
|
|
184
|
+
text_length: selectedText.length,
|
|
185
|
+
has_selection: selectedText.length > 0
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
const handlePaste = (event) => {
|
|
189
|
+
const pastedText = event.clipboardData?.getData("text") || "";
|
|
190
|
+
const target = event.target;
|
|
191
|
+
this.track("paste", {
|
|
192
|
+
text_length: pastedText.length,
|
|
193
|
+
target_element: target ? getElementSelector(target) : undefined
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
document.addEventListener("copy", handleCopy);
|
|
197
|
+
document.addEventListener("cut", handleCut);
|
|
198
|
+
document.addEventListener("paste", handlePaste);
|
|
199
|
+
this.unsubscribers.push(() => {
|
|
200
|
+
document.removeEventListener("copy", handleCopy);
|
|
201
|
+
document.removeEventListener("cut", handleCut);
|
|
202
|
+
document.removeEventListener("paste", handlePaste);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
setupSelectionTracking() {
|
|
206
|
+
let selectionTimeout;
|
|
207
|
+
const handleSelectionChange = () => {
|
|
208
|
+
clearTimeout(selectionTimeout);
|
|
209
|
+
selectionTimeout = setTimeout(() => {
|
|
210
|
+
const selection = window.getSelection();
|
|
211
|
+
const selectedText = selection?.toString() || "";
|
|
212
|
+
if (selectedText.length > 0) {
|
|
213
|
+
this.track("text_select", {
|
|
214
|
+
text_length: selectedText.length
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}, 500);
|
|
218
|
+
};
|
|
219
|
+
document.addEventListener("selectionchange", handleSelectionChange);
|
|
116
220
|
this.unsubscribers.push(() => {
|
|
117
|
-
document.removeEventListener(
|
|
221
|
+
document.removeEventListener("selectionchange", handleSelectionChange);
|
|
222
|
+
clearTimeout(selectionTimeout);
|
|
118
223
|
});
|
|
119
224
|
}
|
|
120
225
|
setupErrorTracking() {
|
|
121
226
|
const handleError = (event) => {
|
|
122
|
-
this.track(
|
|
227
|
+
this.track("js_error", {
|
|
123
228
|
message: event.message,
|
|
124
229
|
filename: event.filename,
|
|
125
230
|
lineno: event.lineno,
|
|
126
231
|
colno: event.colno,
|
|
127
|
-
stack: event.error?.stack
|
|
232
|
+
stack: event.error?.stack
|
|
128
233
|
});
|
|
129
234
|
};
|
|
130
|
-
window.addEventListener(
|
|
235
|
+
window.addEventListener("error", handleError);
|
|
131
236
|
this.unsubscribers.push(() => {
|
|
132
|
-
window.removeEventListener(
|
|
237
|
+
window.removeEventListener("error", handleError);
|
|
133
238
|
});
|
|
134
239
|
const handleRejection = (event) => {
|
|
135
|
-
this.track(
|
|
240
|
+
this.track("unhandled_rejection", {
|
|
136
241
|
reason: String(event.reason),
|
|
137
|
-
promise: String(event.promise)
|
|
242
|
+
promise: String(event.promise)
|
|
138
243
|
});
|
|
139
244
|
};
|
|
140
|
-
window.addEventListener(
|
|
245
|
+
window.addEventListener("unhandledrejection", handleRejection);
|
|
141
246
|
this.unsubscribers.push(() => {
|
|
142
|
-
window.removeEventListener(
|
|
247
|
+
window.removeEventListener("unhandledrejection", handleRejection);
|
|
143
248
|
});
|
|
144
249
|
}
|
|
145
250
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Config } from
|
|
3
|
-
import { Transport } from
|
|
1
|
+
import type { WebAppEvent } from "../types";
|
|
2
|
+
import type { Config } from "../core/config";
|
|
3
|
+
import { Transport } from "./transport";
|
|
4
4
|
export declare class BatchProcessor {
|
|
5
5
|
private config;
|
|
6
6
|
private queue;
|
|
@@ -10,7 +10,7 @@ export declare class BatchProcessor {
|
|
|
10
10
|
constructor(config: Config, transport: Transport);
|
|
11
11
|
start(): void;
|
|
12
12
|
stop(): void;
|
|
13
|
-
addEvent(event:
|
|
13
|
+
addEvent(event: WebAppEvent): void;
|
|
14
14
|
private scheduleFlush;
|
|
15
15
|
flush(): void;
|
|
16
16
|
flushAsync(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-processor.d.ts","sourceRoot":"","sources":["../../src/transport/batch-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"batch-processor.d.ts","sourceRoot":"","sources":["../../src/transport/batch-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAKvC,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,SAAS,CAAiB;gBAEtB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS;IAShD,KAAK,IAAI,IAAI;IAab,IAAI,IAAI,IAAI;IAYZ,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAalC,OAAO,CAAC,aAAa;IAkBrB,KAAK,IAAI,IAAI;IAWP,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC,OAAO,CAAC,sBAAsB;CAqB/B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventQueue } from
|
|
1
|
+
import { EventQueue } from "../core/event-queue";
|
|
2
2
|
export class BatchProcessor {
|
|
3
3
|
constructor(config, transport) {
|
|
4
4
|
this.flushTimer = null;
|
|
@@ -24,7 +24,7 @@ export class BatchProcessor {
|
|
|
24
24
|
}
|
|
25
25
|
addEvent(event) {
|
|
26
26
|
this.queue.enqueue(event);
|
|
27
|
-
const batchSize = this.config.get(
|
|
27
|
+
const batchSize = this.config.get("batchSize");
|
|
28
28
|
if (this.queue.size() >= batchSize) {
|
|
29
29
|
this.flush();
|
|
30
30
|
}
|
|
@@ -33,7 +33,7 @@ export class BatchProcessor {
|
|
|
33
33
|
if (this.flushTimer) {
|
|
34
34
|
clearTimeout(this.flushTimer);
|
|
35
35
|
}
|
|
36
|
-
const interval = this.config.get(
|
|
36
|
+
const interval = this.config.get("flushInterval");
|
|
37
37
|
this.flushTimer = setTimeout(() => {
|
|
38
38
|
this.flush();
|
|
39
39
|
if (this.isStarted) {
|
|
@@ -55,7 +55,7 @@ export class BatchProcessor {
|
|
|
55
55
|
await this.transport.flush();
|
|
56
56
|
}
|
|
57
57
|
setupPageUnloadHandler() {
|
|
58
|
-
if (typeof window ===
|
|
58
|
+
if (typeof window === "undefined") {
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
const handleUnload = () => {
|
|
@@ -64,12 +64,12 @@ export class BatchProcessor {
|
|
|
64
64
|
this.transport.sendBeacon(events);
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
-
window.addEventListener(
|
|
68
|
-
if (document.visibilityState ===
|
|
67
|
+
window.addEventListener("visibilitychange", () => {
|
|
68
|
+
if (document.visibilityState === "hidden") {
|
|
69
69
|
handleUnload();
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
|
-
window.addEventListener(
|
|
73
|
-
window.addEventListener(
|
|
72
|
+
window.addEventListener("pagehide", handleUnload);
|
|
73
|
+
window.addEventListener("beforeunload", handleUnload);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { WebAppEvent } from "../types";
|
|
2
2
|
import type { Config } from "../core/config";
|
|
3
3
|
export declare class Transport {
|
|
4
4
|
private config;
|
|
@@ -6,9 +6,10 @@ export declare class Transport {
|
|
|
6
6
|
private pendingRequests;
|
|
7
7
|
constructor(config: Config);
|
|
8
8
|
private setupOnlineListener;
|
|
9
|
-
|
|
9
|
+
private buildPayload;
|
|
10
|
+
send(events: WebAppEvent[]): Promise<void>;
|
|
10
11
|
private sendRequest;
|
|
11
|
-
sendBeacon(events:
|
|
12
|
+
sendBeacon(events: WebAppEvent[]): boolean;
|
|
12
13
|
flush(): Promise<void>;
|
|
13
14
|
private log;
|
|
14
15
|
private logError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAA;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAQ5C,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,eAAe,CAAgC;gBAE3C,MAAM,EAAE,MAAM;IAQ1B,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,YAAY;IAUd,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA2ClC,WAAW;IA2CzB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO;IA2BpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,OAAO,CAAC,GAAG;IASX,OAAO,CAAC,QAAQ;CAKjB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { safeStringify } from "../utils/helpers";
|
|
2
|
-
import {
|
|
2
|
+
import { DashgramAPIError, NetworkError } from "../errors";
|
|
3
|
+
import { getCurrentOrigin } from "../utils/device";
|
|
3
4
|
export class Transport {
|
|
4
5
|
constructor(config) {
|
|
5
6
|
this.isOnline = true;
|
|
@@ -21,6 +22,12 @@ export class Transport {
|
|
|
21
22
|
});
|
|
22
23
|
this.isOnline = navigator.onLine;
|
|
23
24
|
}
|
|
25
|
+
buildPayload(events) {
|
|
26
|
+
return {
|
|
27
|
+
origin: getCurrentOrigin() || undefined,
|
|
28
|
+
updates: events
|
|
29
|
+
};
|
|
30
|
+
}
|
|
24
31
|
async send(events) {
|
|
25
32
|
if (events.length === 0) {
|
|
26
33
|
return;
|
|
@@ -43,9 +50,7 @@ export class Transport {
|
|
|
43
50
|
const onError = this.config.getOnError();
|
|
44
51
|
if (onError) {
|
|
45
52
|
try {
|
|
46
|
-
if (error instanceof
|
|
47
|
-
error instanceof DashgramAPIError ||
|
|
48
|
-
error instanceof NetworkError) {
|
|
53
|
+
if (error instanceof DashgramAPIError || error instanceof NetworkError) {
|
|
49
54
|
onError(error);
|
|
50
55
|
}
|
|
51
56
|
else if (error instanceof Error) {
|
|
@@ -62,23 +67,17 @@ export class Transport {
|
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
async sendRequest(events) {
|
|
65
|
-
const url = this.config.
|
|
66
|
-
const
|
|
67
|
-
const projectId = this.config.get("projectId");
|
|
70
|
+
const url = this.config.getTrackUrl();
|
|
71
|
+
const payload = this.buildPayload(events);
|
|
68
72
|
try {
|
|
69
73
|
const response = await fetch(url, {
|
|
70
74
|
method: "POST",
|
|
71
75
|
headers: {
|
|
72
|
-
"Content-Type": "application/json"
|
|
73
|
-
"X-API-Key": apiKey,
|
|
74
|
-
"X-Project-ID": projectId
|
|
76
|
+
"Content-Type": "application/json"
|
|
75
77
|
},
|
|
76
|
-
body: safeStringify(
|
|
78
|
+
body: safeStringify(payload),
|
|
77
79
|
keepalive: true
|
|
78
80
|
});
|
|
79
|
-
if (response.status === 403) {
|
|
80
|
-
throw new InvalidCredentialsError();
|
|
81
|
-
}
|
|
82
81
|
if (!response.ok) {
|
|
83
82
|
let details = response.statusText;
|
|
84
83
|
try {
|
|
@@ -92,7 +91,7 @@ export class Transport {
|
|
|
92
91
|
this.log(`Sent ${events.length} events successfully`);
|
|
93
92
|
}
|
|
94
93
|
catch (error) {
|
|
95
|
-
if (error instanceof
|
|
94
|
+
if (error instanceof DashgramAPIError) {
|
|
96
95
|
throw error;
|
|
97
96
|
}
|
|
98
97
|
if (error instanceof Error) {
|
|
@@ -111,15 +110,9 @@ export class Transport {
|
|
|
111
110
|
if (typeof navigator === "undefined" || !navigator.sendBeacon) {
|
|
112
111
|
return false;
|
|
113
112
|
}
|
|
114
|
-
const url = this.config.
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
const payload = safeStringify({
|
|
118
|
-
events,
|
|
119
|
-
apiKey,
|
|
120
|
-
projectId
|
|
121
|
-
});
|
|
122
|
-
const blob = new Blob([payload], { type: "application/json" });
|
|
113
|
+
const url = this.config.getTrackUrl();
|
|
114
|
+
const payload = this.buildPayload(events);
|
|
115
|
+
const blob = new Blob([safeStringify(payload)], { type: "application/json" });
|
|
123
116
|
const sent = navigator.sendBeacon(url, blob);
|
|
124
117
|
this.log(`sendBeacon ${sent ? "succeeded" : "failed"} for ${events.length} events`);
|
|
125
118
|
return sent;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export type TrackLevel = 1 | 2 | 3;
|
|
|
3
3
|
export type EventSource = "auto" | "manual";
|
|
4
4
|
export interface DashgramConfig {
|
|
5
5
|
projectId: string;
|
|
6
|
-
apiKey: string;
|
|
7
6
|
trackLevel?: TrackLevel;
|
|
8
7
|
apiUrl?: string;
|
|
9
8
|
batchSize?: number;
|
|
@@ -12,32 +11,30 @@ export interface DashgramConfig {
|
|
|
12
11
|
disabled?: boolean;
|
|
13
12
|
onError?: (error: DashgramError) => void;
|
|
14
13
|
}
|
|
15
|
-
export interface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
screen_height: number;
|
|
21
|
-
viewport_width: number;
|
|
22
|
-
viewport_height: number;
|
|
23
|
-
user_agent: string;
|
|
24
|
-
timezone: string;
|
|
25
|
-
telegram_version?: string;
|
|
14
|
+
export interface Telemetry {
|
|
15
|
+
ip?: string;
|
|
16
|
+
platform?: string;
|
|
17
|
+
user_agent?: string;
|
|
18
|
+
timezone?: string;
|
|
26
19
|
theme?: string;
|
|
27
20
|
}
|
|
28
|
-
export type EventProperties = Record<string,
|
|
29
|
-
export interface
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
export type EventProperties = Record<string, unknown>;
|
|
22
|
+
export interface WebAppEvent {
|
|
23
|
+
eventId: string;
|
|
24
|
+
type: string;
|
|
25
|
+
initData: string;
|
|
26
|
+
properties?: unknown;
|
|
27
|
+
telemetry?: Telemetry;
|
|
28
|
+
source?: string;
|
|
29
|
+
level?: number;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
}
|
|
32
|
+
export interface WebAppTrackRequest {
|
|
33
|
+
origin?: string;
|
|
34
|
+
updates: WebAppEvent[];
|
|
38
35
|
}
|
|
39
|
-
export type UserTraits = Record<string, any>;
|
|
40
36
|
export interface TelegramWebApp {
|
|
37
|
+
initData?: string;
|
|
41
38
|
initDataUnsafe?: {
|
|
42
39
|
user?: {
|
|
43
40
|
id: number;
|
|
@@ -50,8 +47,86 @@ export interface TelegramWebApp {
|
|
|
50
47
|
platform?: string;
|
|
51
48
|
version?: string;
|
|
52
49
|
themeParams?: Record<string, string>;
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
colorScheme?: "light" | "dark";
|
|
51
|
+
isExpanded?: boolean;
|
|
52
|
+
viewportHeight?: number;
|
|
53
|
+
viewportStableHeight?: number;
|
|
54
|
+
safeAreaInset?: {
|
|
55
|
+
top: number;
|
|
56
|
+
bottom: number;
|
|
57
|
+
left: number;
|
|
58
|
+
right: number;
|
|
59
|
+
};
|
|
60
|
+
contentSafeAreaInset?: {
|
|
61
|
+
top: number;
|
|
62
|
+
bottom: number;
|
|
63
|
+
left: number;
|
|
64
|
+
right: number;
|
|
65
|
+
};
|
|
66
|
+
MainButton?: {
|
|
67
|
+
text?: string;
|
|
68
|
+
isVisible?: boolean;
|
|
69
|
+
isActive?: boolean;
|
|
70
|
+
isProgressVisible?: boolean;
|
|
71
|
+
};
|
|
72
|
+
SecondaryButton?: {
|
|
73
|
+
text?: string;
|
|
74
|
+
isVisible?: boolean;
|
|
75
|
+
isActive?: boolean;
|
|
76
|
+
isProgressVisible?: boolean;
|
|
77
|
+
};
|
|
78
|
+
BiometricManager?: {
|
|
79
|
+
isInited?: boolean;
|
|
80
|
+
isBiometricAvailable?: boolean;
|
|
81
|
+
biometricType?: "finger" | "face" | "unknown";
|
|
82
|
+
isAccessRequested?: boolean;
|
|
83
|
+
isAccessGranted?: boolean;
|
|
84
|
+
isBiometricTokenSaved?: boolean;
|
|
85
|
+
deviceId?: string;
|
|
86
|
+
};
|
|
87
|
+
LocationManager?: {
|
|
88
|
+
isInited?: boolean;
|
|
89
|
+
isLocationAvailable?: boolean;
|
|
90
|
+
isAccessRequested?: boolean;
|
|
91
|
+
isAccessGranted?: boolean;
|
|
92
|
+
};
|
|
93
|
+
Accelerometer?: {
|
|
94
|
+
isStarted?: boolean;
|
|
95
|
+
x?: number;
|
|
96
|
+
y?: number;
|
|
97
|
+
z?: number;
|
|
98
|
+
};
|
|
99
|
+
Gyroscope?: {
|
|
100
|
+
isStarted?: boolean;
|
|
101
|
+
x?: number;
|
|
102
|
+
y?: number;
|
|
103
|
+
z?: number;
|
|
104
|
+
};
|
|
105
|
+
DeviceOrientation?: {
|
|
106
|
+
isStarted?: boolean;
|
|
107
|
+
absolute?: boolean;
|
|
108
|
+
alpha?: number;
|
|
109
|
+
beta?: number;
|
|
110
|
+
gamma?: number;
|
|
111
|
+
};
|
|
112
|
+
onEvent?: (event: string, callback: (eventType: string, eventData?: unknown) => void) => void;
|
|
113
|
+
offEvent?: (event: string, callback: (eventType: string, eventData?: unknown) => void) => void;
|
|
114
|
+
openLink?: (url: string, options?: {
|
|
115
|
+
try_instant_view?: boolean;
|
|
116
|
+
}) => void;
|
|
117
|
+
openTelegramLink?: (url: string) => void;
|
|
118
|
+
switchInlineQuery?: (query: string, chooseChatTypes?: string[]) => void;
|
|
119
|
+
shareToStory?: (mediaUrl: string, params?: unknown) => void;
|
|
120
|
+
close?: (options?: {
|
|
121
|
+
return_back?: boolean;
|
|
122
|
+
}) => void;
|
|
123
|
+
exitFullscreen?: () => void;
|
|
124
|
+
openInvoice?: (slug: string, callback?: (status: string) => void) => void;
|
|
125
|
+
requestAccess?: (accessType: string, callback?: (status: string) => void) => void;
|
|
126
|
+
requestContact?: (callback?: (status: string) => void) => void;
|
|
127
|
+
requestPhone?: (callback?: (status: string) => void) => void;
|
|
128
|
+
requestLocation?: (callback?: (status: string, location?: unknown) => void) => void;
|
|
129
|
+
checkLocation?: (callback?: (isAvailable: boolean, location?: unknown) => void) => void;
|
|
55
130
|
}
|
|
56
131
|
export interface TelegramWindow extends Window {
|
|
57
132
|
Telegram?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAK9C,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAKlC,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAA;AAK3C,MAAM,WAAW,cAAc;IAE7B,SAAS,EAAE,MAAM,CAAA;IAGjB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/device.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function getViewportSize(): {
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
};
|
|
7
|
-
export declare function getScrollDepth(): number;
|
|
1
|
+
import type { Telemetry } from "../types";
|
|
2
|
+
export declare function getTelemetry(): Telemetry;
|
|
8
3
|
export declare function getCurrentUrl(): string;
|
|
9
4
|
export declare function getCurrentPath(): string;
|
|
10
5
|
export declare function getPageTitle(): string;
|
|
6
|
+
export declare function getCurrentOrigin(): string;
|
|
11
7
|
//# sourceMappingURL=device.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/utils/device.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAMzC,wBAAgB,YAAY,IAAI,SAAS,CAaxC;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAKD,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAKD,wBAAgB,YAAY,IAAI,MAAM,CAMrC;AAKD,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC"}
|