@dashgram/javascript 1.0.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.
Files changed (51) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +257 -0
  3. package/dist/core/config.d.ts +13 -0
  4. package/dist/core/config.d.ts.map +1 -0
  5. package/dist/core/config.js +50 -0
  6. package/dist/core/context.d.ts +12 -0
  7. package/dist/core/context.d.ts.map +1 -0
  8. package/dist/core/context.js +23 -0
  9. package/dist/core/event-queue.d.ts +13 -0
  10. package/dist/core/event-queue.d.ts.map +1 -0
  11. package/dist/core/event-queue.js +29 -0
  12. package/dist/core/session.d.ts +13 -0
  13. package/dist/core/session.d.ts.map +1 -0
  14. package/dist/core/session.js +63 -0
  15. package/dist/errors.d.ts +19 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +53 -0
  18. package/dist/index.d.ts +28 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +148 -0
  21. package/dist/trackers/base-tracker.d.ts +17 -0
  22. package/dist/trackers/base-tracker.d.ts.map +1 -0
  23. package/dist/trackers/base-tracker.js +41 -0
  24. package/dist/trackers/core-tracker.d.ts +14 -0
  25. package/dist/trackers/core-tracker.d.ts.map +1 -0
  26. package/dist/trackers/core-tracker.js +64 -0
  27. package/dist/trackers/deep-tracker.d.ts +19 -0
  28. package/dist/trackers/deep-tracker.d.ts.map +1 -0
  29. package/dist/trackers/deep-tracker.js +241 -0
  30. package/dist/trackers/interaction-tracker.d.ts +17 -0
  31. package/dist/trackers/interaction-tracker.d.ts.map +1 -0
  32. package/dist/trackers/interaction-tracker.js +145 -0
  33. package/dist/transport/batch-processor.d.ts +19 -0
  34. package/dist/transport/batch-processor.d.ts.map +1 -0
  35. package/dist/transport/batch-processor.js +75 -0
  36. package/dist/transport/transport.d.ts +16 -0
  37. package/dist/transport/transport.d.ts.map +1 -0
  38. package/dist/transport/transport.js +140 -0
  39. package/dist/types/index.d.ts +61 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/index.js +1 -0
  42. package/dist/utils/device.d.ts +11 -0
  43. package/dist/utils/device.d.ts.map +1 -0
  44. package/dist/utils/device.js +72 -0
  45. package/dist/utils/helpers.d.ts +9 -0
  46. package/dist/utils/helpers.d.ts.map +1 -0
  47. package/dist/utils/helpers.js +74 -0
  48. package/dist/utils/telegram.d.ts +10 -0
  49. package/dist/utils/telegram.d.ts.map +1 -0
  50. package/dist/utils/telegram.js +55 -0
  51. package/package.json +50 -0
package/dist/index.js ADDED
@@ -0,0 +1,148 @@
1
+ import { Config } from "./core/config";
2
+ import { Context } from "./core/context";
3
+ import { Session } from "./core/session";
4
+ import { Transport } from "./transport/transport";
5
+ import { BatchProcessor } from "./transport/batch-processor";
6
+ import { CoreTracker } from "./trackers/core-tracker";
7
+ import { InteractionTracker } from "./trackers/interaction-tracker";
8
+ import { DeepTracker } from "./trackers/deep-tracker";
9
+ import { getTimestamp, isBrowser } from "./utils/helpers";
10
+ import { getTelegramUserId } from "./utils/telegram";
11
+ class DashgramSDK {
12
+ constructor() {
13
+ this.config = null;
14
+ this.context = null;
15
+ this.session = null;
16
+ this.transport = null;
17
+ this.batchProcessor = null;
18
+ this.trackers = [];
19
+ this.isInitialized = false;
20
+ }
21
+ init(userConfig) {
22
+ if (this.isInitialized) {
23
+ console.warn("Dashgram: Already initialized");
24
+ return;
25
+ }
26
+ if (!isBrowser()) {
27
+ console.warn("Dashgram: Not running in browser environment");
28
+ return;
29
+ }
30
+ try {
31
+ this.config = new Config(userConfig);
32
+ this.context = new Context();
33
+ this.session = new Session();
34
+ this.transport = new Transport(this.config);
35
+ this.batchProcessor = new BatchProcessor(this.config, this.transport);
36
+ this.setupTrackers();
37
+ this.batchProcessor.start();
38
+ this.isInitialized = true;
39
+ this.log("Initialized successfully", {
40
+ projectId: this.config.get("projectId"),
41
+ trackLevel: this.config.getTrackLevel()
42
+ });
43
+ }
44
+ catch (error) {
45
+ console.error("Dashgram: Initialization failed", error);
46
+ throw error;
47
+ }
48
+ }
49
+ setupTrackers() {
50
+ if (!this.config)
51
+ return;
52
+ const trackCallback = (event, properties) => {
53
+ this.trackAuto(event, properties);
54
+ };
55
+ const coreTracker = new CoreTracker(this.config, trackCallback);
56
+ this.trackers.push(coreTracker);
57
+ coreTracker.start();
58
+ const interactionTracker = new InteractionTracker(this.config, trackCallback);
59
+ this.trackers.push(interactionTracker);
60
+ interactionTracker.start();
61
+ const deepTracker = new DeepTracker(this.config, trackCallback);
62
+ this.trackers.push(deepTracker);
63
+ deepTracker.start();
64
+ }
65
+ track(event, properties = {}) {
66
+ this.ensureInitialized();
67
+ const fullEvent = this.buildEvent(event, properties, "manual");
68
+ this.batchProcessor.addEvent(fullEvent);
69
+ this.log("Tracked event", { event, properties });
70
+ }
71
+ trackAuto(event, properties = {}) {
72
+ if (!this.isInitialized)
73
+ return;
74
+ const fullEvent = this.buildEvent(event, properties, "auto");
75
+ this.batchProcessor.addEvent(fullEvent);
76
+ this.log("Auto-tracked event", { event, properties });
77
+ }
78
+ buildEvent(event, properties, source) {
79
+ this.ensureInitialized();
80
+ this.session.renewIfExpired();
81
+ this.session.updateLastActivity();
82
+ return {
83
+ event,
84
+ properties,
85
+ timestamp: getTimestamp(),
86
+ source,
87
+ level: this.config.getTrackLevel(),
88
+ session_id: this.session.getSessionId(),
89
+ user_id: this.context.getUserId() || getTelegramUserId(),
90
+ context: this.context.getContext()
91
+ };
92
+ }
93
+ identify(userId, traits = {}) {
94
+ this.ensureInitialized();
95
+ this.context.setUserId(userId);
96
+ this.track("identify", {
97
+ user_id: userId,
98
+ ...traits
99
+ });
100
+ this.log("Identified user", { userId, traits });
101
+ }
102
+ setTrackLevel(level) {
103
+ this.ensureInitialized();
104
+ const oldLevel = this.config.getTrackLevel();
105
+ this.config.setTrackLevel(level);
106
+ this.trackers.forEach(tracker => {
107
+ tracker.stop();
108
+ tracker.start();
109
+ });
110
+ this.log("Track level changed", { from: oldLevel, to: level });
111
+ }
112
+ async flush() {
113
+ this.ensureInitialized();
114
+ await this.batchProcessor.flushAsync();
115
+ this.log("Flushed all events");
116
+ }
117
+ reset() {
118
+ this.ensureInitialized();
119
+ this.session.reset();
120
+ this.context.clearUserId();
121
+ this.log("Reset session and user");
122
+ }
123
+ shutdown() {
124
+ if (!this.isInitialized) {
125
+ return;
126
+ }
127
+ this.trackers.forEach(tracker => tracker.stop());
128
+ this.trackers = [];
129
+ this.batchProcessor.flush();
130
+ this.batchProcessor.stop();
131
+ this.isInitialized = false;
132
+ this.log("Shutdown complete");
133
+ }
134
+ ensureInitialized() {
135
+ if (!this.isInitialized) {
136
+ throw new Error("Dashgram: SDK not initialized. Call init() first.");
137
+ }
138
+ }
139
+ log(...args) {
140
+ if (this.config?.isDebug()) {
141
+ console.log("[Dashgram SDK]", ...args);
142
+ }
143
+ }
144
+ }
145
+ const DashgramMini = new DashgramSDK();
146
+ export { DashgramError, InvalidCredentialsError, DashgramAPIError, NetworkError, DashgramConfigurationError } from "./errors";
147
+ export { DashgramMini };
148
+ export default DashgramMini;
@@ -0,0 +1,17 @@
1
+ import type { TrackLevel, EventProperties } from '../types';
2
+ import type { Config } from '../core/config';
3
+ export type TrackCallback = (event: string, properties: EventProperties) => void;
4
+ export declare abstract class BaseTracker {
5
+ protected config: Config;
6
+ protected trackCallback: TrackCallback;
7
+ protected isActive: boolean;
8
+ protected level: TrackLevel;
9
+ constructor(config: Config, trackCallback: TrackCallback, level: TrackLevel);
10
+ start(): void;
11
+ stop(): void;
12
+ protected track(event: string, properties?: EventProperties): void;
13
+ protected abstract setup(): void;
14
+ protected abstract teardown(): void;
15
+ protected log(...args: any[]): void;
16
+ }
17
+ //# sourceMappingURL=base-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-tracker.d.ts","sourceRoot":"","sources":["../../src/trackers/base-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK7C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,KAAK,IAAI,CAAC;AAKjF,8BAAsB,WAAW;IAC/B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAS;IACpC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC;gBAEhB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU;IAS3E,KAAK,IAAI,IAAI;IAkBb,IAAI,IAAI,IAAI;IAaZ,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,eAAoB,GAAG,IAAI;IActE,SAAS,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;IAKhC,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI;IAKnC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;CAKpC"}
@@ -0,0 +1,41 @@
1
+ export class BaseTracker {
2
+ constructor(config, trackCallback, level) {
3
+ this.isActive = false;
4
+ this.config = config;
5
+ this.trackCallback = trackCallback;
6
+ this.level = level;
7
+ }
8
+ start() {
9
+ if (this.isActive) {
10
+ return;
11
+ }
12
+ const currentLevel = this.config.getTrackLevel();
13
+ if (currentLevel >= this.level) {
14
+ this.isActive = true;
15
+ this.setup();
16
+ this.log(`Started (level ${this.level})`);
17
+ }
18
+ }
19
+ stop() {
20
+ if (!this.isActive) {
21
+ return;
22
+ }
23
+ this.isActive = false;
24
+ this.teardown();
25
+ this.log(`Stopped`);
26
+ }
27
+ track(event, properties = {}) {
28
+ if (!this.isActive) {
29
+ return;
30
+ }
31
+ this.trackCallback(event, {
32
+ ...properties,
33
+ _tracker: this.constructor.name,
34
+ });
35
+ }
36
+ log(...args) {
37
+ if (this.config.isDebug()) {
38
+ console.log(`[Dashgram ${this.constructor.name}]`, ...args);
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseTracker } from './base-tracker';
2
+ import type { Config } from '../core/config';
3
+ import type { TrackCallback } from './base-tracker';
4
+ export declare class CoreTracker extends BaseTracker {
5
+ private unsubscribers;
6
+ private hasTrackedAppOpen;
7
+ constructor(config: Config, trackCallback: TrackCallback);
8
+ protected setup(): void;
9
+ protected teardown(): void;
10
+ private trackAppOpen;
11
+ private setupVisibilityTracking;
12
+ private setupUnloadTracking;
13
+ }
14
+ //# sourceMappingURL=core-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-tracker.d.ts","sourceRoot":"","sources":["../../src/trackers/core-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMpD,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;IAIxD,SAAS,CAAC,KAAK,IAAI,IAAI;IAgBvB,SAAS,CAAC,QAAQ,IAAI,IAAI;IAS1B,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,uBAAuB;IAuB/B,OAAO,CAAC,mBAAmB;CAuB5B"}
@@ -0,0 +1,64 @@
1
+ import { BaseTracker } from './base-tracker';
2
+ export class CoreTracker extends BaseTracker {
3
+ constructor(config, trackCallback) {
4
+ super(config, trackCallback, 1);
5
+ this.unsubscribers = [];
6
+ this.hasTrackedAppOpen = false;
7
+ }
8
+ setup() {
9
+ if (typeof window === 'undefined') {
10
+ return;
11
+ }
12
+ this.trackAppOpen();
13
+ this.track('session_start', {});
14
+ this.setupVisibilityTracking();
15
+ this.setupUnloadTracking();
16
+ }
17
+ teardown() {
18
+ this.unsubscribers.forEach((unsubscribe) => unsubscribe());
19
+ this.unsubscribers = [];
20
+ }
21
+ trackAppOpen() {
22
+ if (this.hasTrackedAppOpen) {
23
+ return;
24
+ }
25
+ this.track('app_open', {
26
+ referrer: document.referrer || 'direct',
27
+ });
28
+ this.hasTrackedAppOpen = true;
29
+ }
30
+ setupVisibilityTracking() {
31
+ const handleVisibilityChange = () => {
32
+ if (document.visibilityState === 'hidden') {
33
+ this.track('app_close', {
34
+ visibility_state: 'hidden',
35
+ });
36
+ }
37
+ else if (document.visibilityState === 'visible') {
38
+ this.track('app_open', {
39
+ visibility_state: 'visible',
40
+ });
41
+ }
42
+ };
43
+ document.addEventListener('visibilitychange', handleVisibilityChange);
44
+ this.unsubscribers.push(() => {
45
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
46
+ });
47
+ }
48
+ setupUnloadTracking() {
49
+ const handleUnload = () => {
50
+ this.track('app_close', {
51
+ reason: 'unload',
52
+ });
53
+ this.track('session_end', {});
54
+ };
55
+ window.addEventListener('pagehide', handleUnload);
56
+ this.unsubscribers.push(() => {
57
+ window.removeEventListener('pagehide', handleUnload);
58
+ });
59
+ window.addEventListener('beforeunload', handleUnload);
60
+ this.unsubscribers.push(() => {
61
+ window.removeEventListener('beforeunload', handleUnload);
62
+ });
63
+ }
64
+ }
@@ -0,0 +1,19 @@
1
+ import { BaseTracker } from "./base-tracker";
2
+ import type { Config } from "../core/config";
3
+ import type { TrackCallback } from "./base-tracker";
4
+ export declare class DeepTracker extends BaseTracker {
5
+ private unsubscribers;
6
+ private observers;
7
+ private clickTracker;
8
+ private maxScrollDepth;
9
+ constructor(config: Config, trackCallback: TrackCallback);
10
+ protected setup(): void;
11
+ protected teardown(): void;
12
+ private setupScrollTracking;
13
+ private setupVisibilityTracking;
14
+ private setupRageClickTracking;
15
+ private setupLongTaskTracking;
16
+ private setupWebVitals;
17
+ private setupTelegramTracking;
18
+ }
19
+ //# sourceMappingURL=deep-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-tracker.d.ts","sourceRoot":"","sources":["../../src/trackers/deep-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AASnD,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAwD;IACzE,OAAO,CAAC,YAAY,CAAoD;IACxE,OAAO,CAAC,cAAc,CAAI;gBAEd,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;IAIxD,SAAS,CAAC,KAAK,IAAI,IAAI;IAavB,SAAS,CAAC,QAAQ,IAAI,IAAI;IAa1B,OAAO,CAAC,mBAAmB;IA8B3B,OAAO,CAAC,uBAAuB;IA+D/B,OAAO,CAAC,sBAAsB;IA6C9B,OAAO,CAAC,qBAAqB;IA6B7B,OAAO,CAAC,cAAc;IAmFtB,OAAO,CAAC,qBAAqB;CA+B9B"}
@@ -0,0 +1,241 @@
1
+ import { BaseTracker } from "./base-tracker";
2
+ import { throttle } from "../utils/helpers";
3
+ import { getScrollDepth } from "../utils/device";
4
+ import { subscribeToTelegramEvent } from "../utils/telegram";
5
+ export class DeepTracker extends BaseTracker {
6
+ constructor(config, trackCallback) {
7
+ super(config, trackCallback, 3);
8
+ this.unsubscribers = [];
9
+ this.observers = [];
10
+ this.clickTracker = new Map();
11
+ this.maxScrollDepth = 0;
12
+ }
13
+ setup() {
14
+ if (typeof window === "undefined") {
15
+ return;
16
+ }
17
+ this.setupScrollTracking();
18
+ this.setupVisibilityTracking();
19
+ this.setupRageClickTracking();
20
+ this.setupLongTaskTracking();
21
+ this.setupWebVitals();
22
+ this.setupTelegramTracking();
23
+ }
24
+ teardown() {
25
+ this.unsubscribers.forEach(unsubscribe => unsubscribe());
26
+ this.unsubscribers = [];
27
+ this.observers.forEach(observer => observer.disconnect());
28
+ this.observers = [];
29
+ this.clickTracker.clear();
30
+ }
31
+ setupScrollTracking() {
32
+ const handleScroll = throttle(() => {
33
+ const depth = getScrollDepth();
34
+ if (depth > this.maxScrollDepth) {
35
+ this.maxScrollDepth = depth;
36
+ const milestones = [25, 50, 75, 100];
37
+ const milestone = milestones.find(m => depth >= m && this.maxScrollDepth - depth < m);
38
+ if (milestone) {
39
+ this.track("scroll_depth", {
40
+ depth: milestone,
41
+ max_depth: this.maxScrollDepth
42
+ });
43
+ }
44
+ }
45
+ }, 500);
46
+ window.addEventListener("scroll", handleScroll, { passive: true });
47
+ this.unsubscribers.push(() => {
48
+ window.removeEventListener("scroll", handleScroll);
49
+ });
50
+ }
51
+ setupVisibilityTracking() {
52
+ if (!("IntersectionObserver" in window)) {
53
+ return;
54
+ }
55
+ const observer = new IntersectionObserver(entries => {
56
+ entries.forEach(entry => {
57
+ if (entry.isIntersecting) {
58
+ const element = entry.target;
59
+ const selector = element.getAttribute("data-track-visible");
60
+ if (selector) {
61
+ this.track("element_visible", {
62
+ element: selector,
63
+ intersection_ratio: entry.intersectionRatio
64
+ });
65
+ observer.unobserve(element);
66
+ }
67
+ }
68
+ });
69
+ }, { threshold: 0.5 });
70
+ document.querySelectorAll("[data-track-visible]").forEach(element => {
71
+ observer.observe(element);
72
+ });
73
+ this.observers.push(observer);
74
+ const mutationObserver = new MutationObserver(mutations => {
75
+ mutations.forEach(mutation => {
76
+ mutation.addedNodes.forEach(node => {
77
+ if (node instanceof Element) {
78
+ if (node.hasAttribute("data-track-visible")) {
79
+ observer.observe(node);
80
+ }
81
+ node.querySelectorAll("[data-track-visible]").forEach(el => {
82
+ observer.observe(el);
83
+ });
84
+ }
85
+ });
86
+ });
87
+ });
88
+ mutationObserver.observe(document.body, {
89
+ childList: true,
90
+ subtree: true
91
+ });
92
+ this.unsubscribers.push(() => {
93
+ mutationObserver.disconnect();
94
+ });
95
+ }
96
+ setupRageClickTracking() {
97
+ const RAGE_THRESHOLD = 5;
98
+ const RAGE_TIMEOUT = 2000;
99
+ const handleClick = (event) => {
100
+ const target = event.target;
101
+ if (!target)
102
+ return;
103
+ const tracker = this.clickTracker.get(target);
104
+ if (tracker) {
105
+ tracker.count++;
106
+ clearTimeout(tracker.timer);
107
+ if (tracker.count >= RAGE_THRESHOLD) {
108
+ this.track("rage_click", {
109
+ element: target.tagName.toLowerCase(),
110
+ click_count: tracker.count
111
+ });
112
+ this.clickTracker.delete(target);
113
+ }
114
+ else {
115
+ tracker.timer = setTimeout(() => {
116
+ this.clickTracker.delete(target);
117
+ }, RAGE_TIMEOUT);
118
+ }
119
+ }
120
+ else {
121
+ const timer = setTimeout(() => {
122
+ this.clickTracker.delete(target);
123
+ }, RAGE_TIMEOUT);
124
+ this.clickTracker.set(target, { count: 1, timer });
125
+ }
126
+ };
127
+ document.addEventListener("click", handleClick);
128
+ this.unsubscribers.push(() => {
129
+ document.removeEventListener("click", handleClick);
130
+ });
131
+ }
132
+ setupLongTaskTracking() {
133
+ if (!("PerformanceObserver" in window)) {
134
+ return;
135
+ }
136
+ try {
137
+ const observer = new PerformanceObserver(list => {
138
+ for (const entry of list.getEntries()) {
139
+ if (entry.duration > 50) {
140
+ this.track("long_task", {
141
+ duration: Math.round(entry.duration),
142
+ start_time: Math.round(entry.startTime)
143
+ });
144
+ }
145
+ }
146
+ });
147
+ observer.observe({ entryTypes: ["longtask"] });
148
+ this.observers.push(observer);
149
+ }
150
+ catch (error) {
151
+ this.log("Long task tracking not supported");
152
+ }
153
+ }
154
+ setupWebVitals() {
155
+ if (!("PerformanceObserver" in window)) {
156
+ return;
157
+ }
158
+ try {
159
+ const lcpObserver = new PerformanceObserver(list => {
160
+ const entries = list.getEntries();
161
+ const lastEntry = entries[entries.length - 1];
162
+ this.track("web_vital_lcp", {
163
+ value: Math.round(lastEntry.renderTime || lastEntry.loadTime),
164
+ element: lastEntry.element?.tagName.toLowerCase()
165
+ });
166
+ });
167
+ lcpObserver.observe({ entryTypes: ["largest-contentful-paint"] });
168
+ this.observers.push(lcpObserver);
169
+ }
170
+ catch (error) {
171
+ this.log("LCP tracking not supported");
172
+ }
173
+ try {
174
+ const fidObserver = new PerformanceObserver(list => {
175
+ const entries = list.getEntries();
176
+ entries.forEach((entry) => {
177
+ this.track("web_vital_fid", {
178
+ value: Math.round(entry.processingStart - entry.startTime),
179
+ event_type: entry.name
180
+ });
181
+ });
182
+ });
183
+ fidObserver.observe({ entryTypes: ["first-input"] });
184
+ this.observers.push(fidObserver);
185
+ }
186
+ catch (error) {
187
+ this.log("FID tracking not supported");
188
+ }
189
+ let clsValue = 0;
190
+ try {
191
+ const clsObserver = new PerformanceObserver(list => {
192
+ const entries = list.getEntries();
193
+ entries.forEach((entry) => {
194
+ if (!entry.hadRecentInput) {
195
+ clsValue += entry.value;
196
+ }
197
+ });
198
+ });
199
+ clsObserver.observe({ entryTypes: ["layout-shift"] });
200
+ this.observers.push(clsObserver);
201
+ const reportCLS = () => {
202
+ if (clsValue > 0) {
203
+ this.track("web_vital_cls", {
204
+ value: Math.round(clsValue * 1000) / 1000
205
+ });
206
+ }
207
+ };
208
+ window.addEventListener("visibilitychange", () => {
209
+ if (document.visibilityState === "hidden") {
210
+ reportCLS();
211
+ }
212
+ });
213
+ this.unsubscribers.push(() => {
214
+ reportCLS();
215
+ });
216
+ }
217
+ catch (error) {
218
+ this.log("CLS tracking not supported");
219
+ }
220
+ }
221
+ setupTelegramTracking() {
222
+ const unsubTheme = subscribeToTelegramEvent("themeChanged", () => {
223
+ this.track("telegram_theme_changed", {});
224
+ });
225
+ this.unsubscribers.push(unsubTheme);
226
+ const unsubViewport = subscribeToTelegramEvent("viewportChanged", () => {
227
+ this.track("telegram_viewport_changed", {
228
+ is_expanded: window.Telegram?.WebApp?.isExpanded
229
+ });
230
+ });
231
+ this.unsubscribers.push(unsubViewport);
232
+ const unsubBack = subscribeToTelegramEvent("backButtonClicked", () => {
233
+ this.track("telegram_back_button_clicked", {});
234
+ });
235
+ this.unsubscribers.push(unsubBack);
236
+ const unsubMain = subscribeToTelegramEvent("mainButtonClicked", () => {
237
+ this.track("telegram_main_button_clicked", {});
238
+ });
239
+ this.unsubscribers.push(unsubMain);
240
+ }
241
+ }
@@ -0,0 +1,17 @@
1
+ import { BaseTracker } from './base-tracker';
2
+ import type { Config } from '../core/config';
3
+ import type { TrackCallback } from './base-tracker';
4
+ export declare class InteractionTracker extends BaseTracker {
5
+ private unsubscribers;
6
+ private lastPath;
7
+ constructor(config: Config, trackCallback: TrackCallback);
8
+ protected setup(): void;
9
+ protected teardown(): void;
10
+ private trackScreenView;
11
+ private setupHistoryTracking;
12
+ private setupClickTracking;
13
+ private setupFormTracking;
14
+ private setupInputTracking;
15
+ private setupErrorTracking;
16
+ }
17
+ //# sourceMappingURL=interaction-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interaction-tracker.d.ts","sourceRoot":"","sources":["../../src/trackers/interaction-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AASpD,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAc;gBAElB,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa;IAIxD,SAAS,CAAC,KAAK,IAAI,IAAI;IAgBvB,SAAS,CAAC,QAAQ,IAAI,IAAI;IAQ1B,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,iBAAiB;IAuBzB,OAAO,CAAC,kBAAkB;IA4B1B,OAAO,CAAC,kBAAkB;CAgC3B"}