swetrix 1.3.1 → 2.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.
@@ -0,0 +1 @@
1
+ ko_fi: andriir
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  <img src="https://swetrix.com/assets/logo_blue.svg" alt="" height="100" />
2
2
 
3
+ [![JSDelivr hits](https://data.jsdelivr.com/v1/package/gh/Swetrix/swetrix-js/badge?style=rounded)](https://data.jsdelivr.com/v1/package/gh/Swetrix/swetrix-js/stats)
4
+ [![Package size](https://img.shields.io/bundlephobia/minzip/swetrix)](https://bundlephobia.com/api/size?package=swetrix)
5
+ [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/swetrix/swetrix-js/issues)
6
+
3
7
  # Swetrix Tracking Script
4
8
 
5
9
  This repository contains the analytics script which is used at https://swetrix.com \
@@ -8,5 +12,11 @@ You can find the detailed documentation and use cases at our [docs page](https:/
8
12
  Feel free to contribute to the source code by opening a pull requests. \
9
13
  For any questions, you can open an issue ticket, refer to our [FAQs](https://swetrix.com/#faq) page or reach us at contact@swetrix.com
10
14
 
15
+ The latest live versions of the script are located at [jsDelivr](https://swetrix.org/swetrix.js) and [NPM](https://www.npmjs.com/package/swetrix).
16
+
11
17
  # Selfhosted API
12
18
  If you are selfhosting the [Swetrix-API](https://github.com/Swetrix/swetrix-api), be sure to point the `apiUrl` parameter to: `https://yourapiinstance.com/log`
19
+
20
+ # Donate
21
+ You can support the project by donating us at https://ko-fi.com/andriir \
22
+ We can only run our services by once again asking for your financial support!
@@ -1,31 +1,65 @@
1
1
  export interface LibOptions {
2
+ /**
3
+ * When set to `true`, all tracking logs will be printed to console and localhost events will be sent to server.
4
+ */
2
5
  debug?: boolean;
6
+ /**
7
+ * When set to `true`, the tracking library won't send any data to server.
8
+ * Useful for development purposes when this value is set based on `.env` var.
9
+ */
3
10
  disabled?: boolean;
11
+ /**
12
+ * By setting this flag to `true`, we will not collect ANY kind of data about the user with the DNT setting.
13
+ */
4
14
  respectDNT?: boolean;
15
+ /** Set a custom URL of the API server (for selfhosted variants of Swetrix). */
5
16
  apiURL?: string;
6
17
  }
7
18
  export interface TrackEventOptions {
19
+ /** The custom event name. */
8
20
  ev: string;
21
+ /** If set to `true`, only 1 event with the same ID will be saved per user session. */
9
22
  unique?: boolean;
10
23
  }
24
+ /**
25
+ * The object returned by `trackPageViews()`, used to stop tracking pages.
26
+ */
27
+ export interface PageActions {
28
+ /** Stops the tracking of pages. */
29
+ stop: () => void;
30
+ }
11
31
  export interface PageData {
32
+ /** Current URL path. */
12
33
  path: string;
13
- actions: object;
34
+ /** The object returned by `trackPageViews()`, used to stop tracking pages. */
35
+ actions: PageActions;
14
36
  }
15
37
  export interface PageViewsOptions {
38
+ /**
39
+ * If set to `true`, only unique events will be saved.
40
+ * This param is useful when tracking single-page landing websites.
41
+ */
16
42
  unique?: boolean;
17
- ignore?: Array<any>;
43
+ /** A list of Regular Expressions or string pathes to ignore. */
44
+ ignore?: Array<string | RegExp>;
45
+ /** Do not send Heartbeat requests to the server. */
18
46
  noHeartbeat?: boolean;
47
+ /** Send Heartbeat requests when the website tab is not active in the browser. */
19
48
  heartbeatOnBackground?: boolean;
20
49
  }
50
+ export declare const defaultPageActions: {
51
+ stop(): void;
52
+ };
21
53
  export declare class Lib {
22
54
  private projectID;
23
55
  private options?;
24
56
  private pageData;
25
57
  private pageViewsOptions;
58
+ private perfStatsCollected;
26
59
  constructor(projectID: string, options?: LibOptions | undefined);
27
60
  track(event: TrackEventOptions): void;
28
- trackPageViews(options?: PageViewsOptions): void | object;
61
+ trackPageViews(options?: PageViewsOptions): PageActions;
62
+ getPerformanceStats(): object;
29
63
  private heartbeat;
30
64
  private checkIgnore;
31
65
  private trackPathChange;
@@ -1,4 +1,7 @@
1
1
  import { isInBrowser, isLocalhost, isAutomated, getLocale, getTimezone, getReferrer, getUTMCampaign, getUTMMedium, getUTMSource, getPath, } from './utils';
2
+ export const defaultPageActions = {
3
+ stop() { },
4
+ };
2
5
  const DEFAULT_API_HOST = 'https://api.swetrix.com/log';
3
6
  export class Lib {
4
7
  constructor(projectID, options) {
@@ -6,6 +9,7 @@ export class Lib {
6
9
  this.options = options;
7
10
  this.pageData = null;
8
11
  this.pageViewsOptions = null;
12
+ this.perfStatsCollected = false;
9
13
  this.trackPathChange = this.trackPathChange.bind(this);
10
14
  this.heartbeat = this.heartbeat.bind(this);
11
15
  }
@@ -21,7 +25,7 @@ export class Lib {
21
25
  }
22
26
  trackPageViews(options) {
23
27
  if (!this.canTrack()) {
24
- return;
28
+ return defaultPageActions;
25
29
  }
26
30
  if (this.pageData) {
27
31
  return this.pageData.actions;
@@ -48,6 +52,37 @@ export class Lib {
48
52
  this.trackPage(path, options?.unique);
49
53
  return this.pageData.actions;
50
54
  }
55
+ getPerformanceStats() {
56
+ if (!this.canTrack() || this.perfStatsCollected || !window.performance?.getEntriesByType) {
57
+ return {};
58
+ }
59
+ const perf = window.performance.getEntriesByType('navigation')[0];
60
+ if (!perf) {
61
+ return {};
62
+ }
63
+ this.perfStatsCollected = true;
64
+ return {
65
+ // Network
66
+ // @ts-ignore
67
+ dns: perf.domainLookupEnd - perf.domainLookupStart,
68
+ // @ts-ignore
69
+ tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0,
70
+ // @ts-ignore
71
+ conn: perf.secureConnectionStart ? perf.secureConnectionStart - perf.connectStart : perf.connectEnd - perf.connectStart,
72
+ // @ts-ignore
73
+ response: perf.responseEnd - perf.responseStart,
74
+ // Frontend
75
+ // @ts-ignore
76
+ render: perf.domComplete - perf.domContentLoadedEventEnd,
77
+ // @ts-ignore
78
+ dom_load: perf.domContentLoadedEventEnd - perf.responseEnd,
79
+ // @ts-ignore
80
+ page_load: perf.loadEventStart,
81
+ // Backend
82
+ // @ts-ignore
83
+ ttfb: perf.responseStart - perf.requestStart,
84
+ };
85
+ }
51
86
  heartbeat() {
52
87
  if (!this.pageViewsOptions?.heartbeatOnBackground && document.visibilityState === 'hidden') {
53
88
  return;
@@ -63,6 +98,7 @@ export class Lib {
63
98
  for (let i = 0; i < ignore.length; ++i) {
64
99
  if (ignore[i] === path)
65
100
  return true;
101
+ // @ts-ignore
66
102
  if (ignore[i] instanceof RegExp && ignore[i].test(path))
67
103
  return true;
68
104
  }
@@ -85,6 +121,7 @@ export class Lib {
85
121
  this.pageData.path = pg;
86
122
  if (this.checkIgnore(pg))
87
123
  return;
124
+ const perf = this.getPerformanceStats();
88
125
  const data = {
89
126
  pid: this.projectID,
90
127
  lc: getLocale(),
@@ -95,6 +132,7 @@ export class Lib {
95
132
  ca: getUTMCampaign(),
96
133
  unique,
97
134
  pg,
135
+ perf,
98
136
  };
99
137
  this.sendRequest('', data);
100
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Lib.js","sourceRoot":"","sources":["../../src/Lib.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Lib.js","sourceRoot":"","sources":["../../src/Lib.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,27 @@
1
- import { Lib, LibOptions, TrackEventOptions, PageViewsOptions } from './Lib';
1
+ import { Lib, LibOptions, TrackEventOptions, PageViewsOptions, PageActions } from './Lib';
2
2
  export declare let LIB_INSTANCE: Lib | null;
3
+ /**
4
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
5
+ *
6
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
7
+ * @param {LibOptions} options Options related to the tracking.
8
+ * @returns {Lib} Instance of the Swetrix.js.
9
+ */
3
10
  export declare function init(pid: string, options?: LibOptions): Lib;
11
+ /**
12
+ * With this function you are able to track any custom events you want.
13
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
14
+ * The total number of track calls and their conversion rate will be saved.
15
+ *
16
+ * @param {TrackEventOptions} event The options related to the custom event.
17
+ */
4
18
  export declare function track(event: TrackEventOptions): void;
5
- export declare function trackViews(options?: PageViewsOptions): void;
19
+ /**
20
+ * With this function you are able to track any custom events you want.
21
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
22
+ * The total number of track calls and their conversion rate will be saved.
23
+ *
24
+ * @param {PageViewsOptions} options The options related to the custom event.
25
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
26
+ */
27
+ export declare function trackViews(options?: PageViewsOptions): Promise<PageActions>;
@@ -1,22 +1,54 @@
1
- import { Lib } from './Lib';
1
+ import { Lib, defaultPageActions, } from './Lib';
2
2
  export let LIB_INSTANCE = null;
3
- // Initialise the tracking library instance (other methods won't work if the library
4
- // is not initialised)
3
+ /**
4
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
5
+ *
6
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
7
+ * @param {LibOptions} options Options related to the tracking.
8
+ * @returns {Lib} Instance of the Swetrix.js.
9
+ */
5
10
  export function init(pid, options) {
6
11
  if (!LIB_INSTANCE) {
7
12
  LIB_INSTANCE = new Lib(pid, options);
8
13
  }
9
14
  return LIB_INSTANCE;
10
15
  }
11
- // Tracks custom events
16
+ /**
17
+ * With this function you are able to track any custom events you want.
18
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
19
+ * The total number of track calls and their conversion rate will be saved.
20
+ *
21
+ * @param {TrackEventOptions} event The options related to the custom event.
22
+ */
12
23
  export function track(event) {
13
24
  if (!LIB_INSTANCE)
14
25
  return;
15
26
  LIB_INSTANCE.track(event);
16
27
  }
28
+ /**
29
+ * With this function you are able to track any custom events you want.
30
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
31
+ * The total number of track calls and their conversion rate will be saved.
32
+ *
33
+ * @param {PageViewsOptions} options The options related to the custom event.
34
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
35
+ */
17
36
  export function trackViews(options) {
18
- if (!LIB_INSTANCE)
19
- return;
20
- LIB_INSTANCE.trackPageViews(options);
37
+ return new Promise((resolve) => {
38
+ if (!LIB_INSTANCE) {
39
+ resolve(defaultPageActions);
40
+ return;
41
+ }
42
+ // We need to verify that document.readyState is complete for the performance stats to be collected correctly.
43
+ if (document.readyState === 'complete') {
44
+ resolve(LIB_INSTANCE.trackPageViews(options));
45
+ }
46
+ else {
47
+ window.addEventListener('load', () => {
48
+ // @ts-ignore
49
+ resolve(LIB_INSTANCE.trackPageViews(options));
50
+ });
51
+ }
52
+ });
21
53
  }
22
54
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAmD,MAAM,OAAO,CAAA;AAE5E,MAAM,CAAC,IAAI,YAAY,GAAe,IAAI,CAAA;AAE1C,oFAAoF;AACpF,sBAAsB;AACtB,MAAM,UAAU,IAAI,CAAE,GAAW,EAAE,OAAoB;IACrD,IAAI,CAAC,YAAY,EAAE;QACjB,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;KACrC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,KAAK,CAAE,KAAwB;IAC7C,IAAI,CAAC,YAAY;QAAE,OAAM;IAEzB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,UAAU,CAAE,OAA0B;IACpD,IAAI,CAAC,YAAY;QAAE,OAAM;IAEzB,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;AACtC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAAgE,kBAAkB,GACtF,MAAM,OAAO,CAAA;AAEd,MAAM,CAAC,IAAI,YAAY,GAAe,IAAI,CAAA;AAE1C;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,OAAoB;IACpD,IAAI,CAAC,YAAY,EAAE;QACjB,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;KACrC;IAED,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,KAAwB;IAC5C,IAAI,CAAC,YAAY;QAAE,OAAM;IAEzB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,CAAC,YAAY,EAAE;YACjB,OAAO,CAAC,kBAAkB,CAAC,CAAA;YAC3B,OAAM;SACP;QAED,8GAA8G;QAC9G,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU,EAAE;YACtC,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;SAC9C;aAAM;YACL,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;gBACnC,aAAa;gBACb,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;YAC/C,CAAC,CAAC,CAAA;SACH;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /*! *****************************************************************************
5
+ /******************************************************************************
6
6
  Copyright (c) Microsoft Corporation.
7
7
 
8
8
  Permission to use, copy, modify, and/or distribute this software for any
@@ -66,6 +66,9 @@ var getPath = function () {
66
66
  return location.pathname || '';
67
67
  };
68
68
 
69
+ var defaultPageActions = {
70
+ stop: function () { },
71
+ };
69
72
  var DEFAULT_API_HOST = 'https://api.swetrix.com/log';
70
73
  var Lib = /** @class */ (function () {
71
74
  function Lib(projectID, options) {
@@ -73,6 +76,7 @@ var Lib = /** @class */ (function () {
73
76
  this.options = options;
74
77
  this.pageData = null;
75
78
  this.pageViewsOptions = null;
79
+ this.perfStatsCollected = false;
76
80
  this.trackPathChange = this.trackPathChange.bind(this);
77
81
  this.heartbeat = this.heartbeat.bind(this);
78
82
  }
@@ -85,7 +89,7 @@ var Lib = /** @class */ (function () {
85
89
  };
86
90
  Lib.prototype.trackPageViews = function (options) {
87
91
  if (!this.canTrack()) {
88
- return;
92
+ return defaultPageActions;
89
93
  }
90
94
  if (this.pageData) {
91
95
  return this.pageData.actions;
@@ -112,6 +116,38 @@ var Lib = /** @class */ (function () {
112
116
  this.trackPage(path, options === null || options === void 0 ? void 0 : options.unique);
113
117
  return this.pageData.actions;
114
118
  };
119
+ Lib.prototype.getPerformanceStats = function () {
120
+ var _a;
121
+ if (!this.canTrack() || this.perfStatsCollected || !((_a = window.performance) === null || _a === void 0 ? void 0 : _a.getEntriesByType)) {
122
+ return {};
123
+ }
124
+ var perf = window.performance.getEntriesByType('navigation')[0];
125
+ if (!perf) {
126
+ return {};
127
+ }
128
+ this.perfStatsCollected = true;
129
+ return {
130
+ // Network
131
+ // @ts-ignore
132
+ dns: perf.domainLookupEnd - perf.domainLookupStart,
133
+ // @ts-ignore
134
+ tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0,
135
+ // @ts-ignore
136
+ conn: perf.secureConnectionStart ? perf.secureConnectionStart - perf.connectStart : perf.connectEnd - perf.connectStart,
137
+ // @ts-ignore
138
+ response: perf.responseEnd - perf.responseStart,
139
+ // Frontend
140
+ // @ts-ignore
141
+ render: perf.domComplete - perf.domContentLoadedEventEnd,
142
+ // @ts-ignore
143
+ dom_load: perf.domContentLoadedEventEnd - perf.responseEnd,
144
+ // @ts-ignore
145
+ page_load: perf.loadEventStart,
146
+ // Backend
147
+ // @ts-ignore
148
+ ttfb: perf.responseStart - perf.requestStart,
149
+ };
150
+ };
115
151
  Lib.prototype.heartbeat = function () {
116
152
  var _a;
117
153
  if (!((_a = this.pageViewsOptions) === null || _a === void 0 ? void 0 : _a.heartbeatOnBackground) && document.visibilityState === 'hidden') {
@@ -129,6 +165,7 @@ var Lib = /** @class */ (function () {
129
165
  for (var i = 0; i < ignore.length; ++i) {
130
166
  if (ignore[i] === path)
131
167
  return true;
168
+ // @ts-ignore
132
169
  if (ignore[i] instanceof RegExp && ignore[i].test(path))
133
170
  return true;
134
171
  }
@@ -152,6 +189,7 @@ var Lib = /** @class */ (function () {
152
189
  this.pageData.path = pg;
153
190
  if (this.checkIgnore(pg))
154
191
  return;
192
+ var perf = this.getPerformanceStats();
155
193
  var data = {
156
194
  pid: this.projectID,
157
195
  lc: getLocale(),
@@ -162,6 +200,7 @@ var Lib = /** @class */ (function () {
162
200
  ca: getUTMCampaign(),
163
201
  unique: unique,
164
202
  pg: pg,
203
+ perf: perf,
165
204
  };
166
205
  this.sendRequest('', data);
167
206
  };
@@ -206,24 +245,56 @@ var Lib = /** @class */ (function () {
206
245
  }());
207
246
 
208
247
  exports.LIB_INSTANCE = null;
209
- // Initialise the tracking library instance (other methods won't work if the library
210
- // is not initialised)
248
+ /**
249
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
250
+ *
251
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
252
+ * @param {LibOptions} options Options related to the tracking.
253
+ * @returns {Lib} Instance of the Swetrix.js.
254
+ */
211
255
  function init(pid, options) {
212
256
  if (!exports.LIB_INSTANCE) {
213
257
  exports.LIB_INSTANCE = new Lib(pid, options);
214
258
  }
215
259
  return exports.LIB_INSTANCE;
216
260
  }
217
- // Tracks custom events
261
+ /**
262
+ * With this function you are able to track any custom events you want.
263
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
264
+ * The total number of track calls and their conversion rate will be saved.
265
+ *
266
+ * @param {TrackEventOptions} event The options related to the custom event.
267
+ */
218
268
  function track(event) {
219
269
  if (!exports.LIB_INSTANCE)
220
270
  return;
221
271
  exports.LIB_INSTANCE.track(event);
222
272
  }
273
+ /**
274
+ * With this function you are able to track any custom events you want.
275
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
276
+ * The total number of track calls and their conversion rate will be saved.
277
+ *
278
+ * @param {PageViewsOptions} options The options related to the custom event.
279
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
280
+ */
223
281
  function trackViews(options) {
224
- if (!exports.LIB_INSTANCE)
225
- return;
226
- exports.LIB_INSTANCE.trackPageViews(options);
282
+ return new Promise(function (resolve) {
283
+ if (!exports.LIB_INSTANCE) {
284
+ resolve(defaultPageActions);
285
+ return;
286
+ }
287
+ // We need to verify that document.readyState is complete for the performance stats to be collected correctly.
288
+ if (document.readyState === 'complete') {
289
+ resolve(exports.LIB_INSTANCE.trackPageViews(options));
290
+ }
291
+ else {
292
+ window.addEventListener('load', function () {
293
+ // @ts-ignore
294
+ resolve(exports.LIB_INSTANCE.trackPageViews(options));
295
+ });
296
+ }
297
+ });
227
298
  }
228
299
 
229
300
  exports.init = init;
@@ -1,4 +1,4 @@
1
- /*! *****************************************************************************
1
+ /******************************************************************************
2
2
  Copyright (c) Microsoft Corporation.
3
3
 
4
4
  Permission to use, copy, modify, and/or distribute this software for any
@@ -62,6 +62,9 @@ var getPath = function () {
62
62
  return location.pathname || '';
63
63
  };
64
64
 
65
+ var defaultPageActions = {
66
+ stop: function () { },
67
+ };
65
68
  var DEFAULT_API_HOST = 'https://api.swetrix.com/log';
66
69
  var Lib = /** @class */ (function () {
67
70
  function Lib(projectID, options) {
@@ -69,6 +72,7 @@ var Lib = /** @class */ (function () {
69
72
  this.options = options;
70
73
  this.pageData = null;
71
74
  this.pageViewsOptions = null;
75
+ this.perfStatsCollected = false;
72
76
  this.trackPathChange = this.trackPathChange.bind(this);
73
77
  this.heartbeat = this.heartbeat.bind(this);
74
78
  }
@@ -81,7 +85,7 @@ var Lib = /** @class */ (function () {
81
85
  };
82
86
  Lib.prototype.trackPageViews = function (options) {
83
87
  if (!this.canTrack()) {
84
- return;
88
+ return defaultPageActions;
85
89
  }
86
90
  if (this.pageData) {
87
91
  return this.pageData.actions;
@@ -108,6 +112,38 @@ var Lib = /** @class */ (function () {
108
112
  this.trackPage(path, options === null || options === void 0 ? void 0 : options.unique);
109
113
  return this.pageData.actions;
110
114
  };
115
+ Lib.prototype.getPerformanceStats = function () {
116
+ var _a;
117
+ if (!this.canTrack() || this.perfStatsCollected || !((_a = window.performance) === null || _a === void 0 ? void 0 : _a.getEntriesByType)) {
118
+ return {};
119
+ }
120
+ var perf = window.performance.getEntriesByType('navigation')[0];
121
+ if (!perf) {
122
+ return {};
123
+ }
124
+ this.perfStatsCollected = true;
125
+ return {
126
+ // Network
127
+ // @ts-ignore
128
+ dns: perf.domainLookupEnd - perf.domainLookupStart,
129
+ // @ts-ignore
130
+ tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0,
131
+ // @ts-ignore
132
+ conn: perf.secureConnectionStart ? perf.secureConnectionStart - perf.connectStart : perf.connectEnd - perf.connectStart,
133
+ // @ts-ignore
134
+ response: perf.responseEnd - perf.responseStart,
135
+ // Frontend
136
+ // @ts-ignore
137
+ render: perf.domComplete - perf.domContentLoadedEventEnd,
138
+ // @ts-ignore
139
+ dom_load: perf.domContentLoadedEventEnd - perf.responseEnd,
140
+ // @ts-ignore
141
+ page_load: perf.loadEventStart,
142
+ // Backend
143
+ // @ts-ignore
144
+ ttfb: perf.responseStart - perf.requestStart,
145
+ };
146
+ };
111
147
  Lib.prototype.heartbeat = function () {
112
148
  var _a;
113
149
  if (!((_a = this.pageViewsOptions) === null || _a === void 0 ? void 0 : _a.heartbeatOnBackground) && document.visibilityState === 'hidden') {
@@ -125,6 +161,7 @@ var Lib = /** @class */ (function () {
125
161
  for (var i = 0; i < ignore.length; ++i) {
126
162
  if (ignore[i] === path)
127
163
  return true;
164
+ // @ts-ignore
128
165
  if (ignore[i] instanceof RegExp && ignore[i].test(path))
129
166
  return true;
130
167
  }
@@ -148,6 +185,7 @@ var Lib = /** @class */ (function () {
148
185
  this.pageData.path = pg;
149
186
  if (this.checkIgnore(pg))
150
187
  return;
188
+ var perf = this.getPerformanceStats();
151
189
  var data = {
152
190
  pid: this.projectID,
153
191
  lc: getLocale(),
@@ -158,6 +196,7 @@ var Lib = /** @class */ (function () {
158
196
  ca: getUTMCampaign(),
159
197
  unique: unique,
160
198
  pg: pg,
199
+ perf: perf,
161
200
  };
162
201
  this.sendRequest('', data);
163
202
  };
@@ -202,24 +241,56 @@ var Lib = /** @class */ (function () {
202
241
  }());
203
242
 
204
243
  var LIB_INSTANCE = null;
205
- // Initialise the tracking library instance (other methods won't work if the library
206
- // is not initialised)
244
+ /**
245
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
246
+ *
247
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
248
+ * @param {LibOptions} options Options related to the tracking.
249
+ * @returns {Lib} Instance of the Swetrix.js.
250
+ */
207
251
  function init(pid, options) {
208
252
  if (!LIB_INSTANCE) {
209
253
  LIB_INSTANCE = new Lib(pid, options);
210
254
  }
211
255
  return LIB_INSTANCE;
212
256
  }
213
- // Tracks custom events
257
+ /**
258
+ * With this function you are able to track any custom events you want.
259
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
260
+ * The total number of track calls and their conversion rate will be saved.
261
+ *
262
+ * @param {TrackEventOptions} event The options related to the custom event.
263
+ */
214
264
  function track(event) {
215
265
  if (!LIB_INSTANCE)
216
266
  return;
217
267
  LIB_INSTANCE.track(event);
218
268
  }
269
+ /**
270
+ * With this function you are able to track any custom events you want.
271
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
272
+ * The total number of track calls and their conversion rate will be saved.
273
+ *
274
+ * @param {PageViewsOptions} options The options related to the custom event.
275
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
276
+ */
219
277
  function trackViews(options) {
220
- if (!LIB_INSTANCE)
221
- return;
222
- LIB_INSTANCE.trackPageViews(options);
278
+ return new Promise(function (resolve) {
279
+ if (!LIB_INSTANCE) {
280
+ resolve(defaultPageActions);
281
+ return;
282
+ }
283
+ // We need to verify that document.readyState is complete for the performance stats to be collected correctly.
284
+ if (document.readyState === 'complete') {
285
+ resolve(LIB_INSTANCE.trackPageViews(options));
286
+ }
287
+ else {
288
+ window.addEventListener('load', function () {
289
+ // @ts-ignore
290
+ resolve(LIB_INSTANCE.trackPageViews(options));
291
+ });
292
+ }
293
+ });
223
294
  }
224
295
 
225
296
  export { LIB_INSTANCE, init, track, trackViews };
package/dist/swetrix.js CHANGED
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).swetrix={})}(this,function(i){"use strict";function n(t){return(t=location.search.match(t))&&t[2]||void 0}function a(){return location.pathname||""}var e=function(){return(e=Object.assign||function(t){for(var e,i=1,n=arguments.length;i<n;i++)for(var a in e=arguments[i])Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a]);return t}).apply(this,arguments)},o=/[?&](ref|source|utm_source)=([^?&]+)/,r=/[?&](utm_campaign)=([^?&]+)/,s=/[?&](utm_medium)=([^?&]+)/,c=(t.prototype.track=function(t){this.canTrack()&&(t=e({pid:this.projectID},t),this.sendRequest("custom",t))},t.prototype.trackPageViews=function(t){if(this.canTrack()){if(this.pageData)return this.pageData.actions;var e,i;null!=(this.pageViewsOptions=t)&&t.unique||(i=setInterval(this.trackPathChange,2e3)),null!=t&&t.noHeartbeat||(setTimeout(this.heartbeat,3e3),e=setInterval(this.heartbeat,28e3));var n=a();return this.pageData={path:n,actions:{stop:function(){clearInterval(i),clearInterval(e)}}},this.trackPage(n,null==t?void 0:t.unique),this.pageData.actions}},t.prototype.heartbeat=function(){var t;(null!==(t=this.pageViewsOptions)&&void 0!==t&&t.heartbeatOnBackground||"hidden"!==document.visibilityState)&&(t={pid:this.projectID},this.sendRequest("hb",t))},t.prototype.checkIgnore=function(t){var e,i=null===(e=this.pageViewsOptions)||void 0===e?void 0:e.ignore;if(Array.isArray(i))for(var n=0;n<i.length;++n){if(i[n]===t)return!0;if(i[n]instanceof RegExp&&i[n].test(t))return!0}return!1},t.prototype.trackPathChange=function(){var t;this.pageData&&(t=a(),this.pageData.path!==t&&this.trackPage(t,!1))},t.prototype.trackPage=function(t,e){void 0===e&&(e=!1),this.pageData&&(this.pageData.path=t,this.checkIgnore(t)||(t={pid:this.projectID,lc:void 0!==navigator.languages?navigator.languages[0]:navigator.language,tz:function(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch(t){return}}(),ref:document.referrer||void 0,so:n(o),me:n(s),ca:n(r),unique:e,pg:t},this.sendRequest("",t)))},t.prototype.debug=function(t){var e;null!==(e=this.options)&&void 0!==e&&e.debug&&console.log("[Swetrix]",t)},t.prototype.canTrack=function(){var t,e;return null!==(t=this.options)&&void 0!==t&&t.disabled?(this.debug("Tracking disabled: the 'disabled' setting is set to true."),!1):"undefined"==typeof window?(this.debug("Tracking disabled: script does not run in browser environment."),!1):null!==(t=this.options)&&void 0!==t&&t.respectDNT&&"1"===(null===(e=window.navigator)||void 0===e?void 0:e.doNotTrack)?(this.debug("Tracking disabled: respecting user's 'Do Not Track' preference."),!1):!!(null!==(e=this.options)&&void 0!==e&&e.debug||"localhost"!==(null===location||void 0===location?void 0:location.hostname)&&"127.0.0.1"!==(null===location||void 0===location?void 0:location.hostname)&&""!==(null===location||void 0===location?void 0:location.hostname))&&(null===navigator||void 0===navigator||!navigator.webdriver||(this.debug("Tracking disabled: navigation is automated by WebDriver."),!1))},t.prototype.sendRequest=function(t,e){var i=(null===(n=this.options)||void 0===n?void 0:n.apiURL)||"https://api.swetrix.com/log",n=new XMLHttpRequest;n.open("POST","".concat(i,"/").concat(t),!0),n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(e))},t);function t(t,e){this.projectID=t,this.options=e,this.pageData=null,this.pageViewsOptions=null,this.trackPathChange=this.trackPathChange.bind(this),this.heartbeat=this.heartbeat.bind(this)}i.LIB_INSTANCE=null,i.init=function(t,e){return i.LIB_INSTANCE||(i.LIB_INSTANCE=new c(t,e)),i.LIB_INSTANCE},i.track=function(t){i.LIB_INSTANCE&&i.LIB_INSTANCE.track(t)},i.trackViews=function(t){i.LIB_INSTANCE&&i.LIB_INSTANCE.trackPageViews(t)},Object.defineProperty(i,"__esModule",{value:!0})});
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).swetrix={})}(this,function(n){"use strict";function o(t){return(t=location.search.match(t))&&t[2]||void 0}function a(){return location.pathname||""}var e=function(){return(e=Object.assign||function(t){for(var e,n=1,o=arguments.length;n<o;n++)for(var a in e=arguments[n])Object.prototype.hasOwnProperty.call(e,a)&&(t[a]=e[a]);return t}).apply(this,arguments)},i=/[?&](ref|source|utm_source)=([^?&]+)/,r=/[?&](utm_campaign)=([^?&]+)/,s=/[?&](utm_medium)=([^?&]+)/,c={stop:function(){}},u=(t.prototype.track=function(t){this.canTrack()&&(t=e({pid:this.projectID},t),this.sendRequest("custom",t))},t.prototype.trackPageViews=function(t){var e,n,o;return this.canTrack()?(this.pageData||(null!=(this.pageViewsOptions=t)&&t.unique||(n=setInterval(this.trackPathChange,2e3)),null!=t&&t.noHeartbeat||(setTimeout(this.heartbeat,3e3),e=setInterval(this.heartbeat,28e3)),o=a(),this.pageData={path:o,actions:{stop:function(){clearInterval(n),clearInterval(e)}}},this.trackPage(o,null==t?void 0:t.unique)),this.pageData.actions):c},t.prototype.getPerformanceStats=function(){var t;return this.canTrack()&&!this.perfStatsCollected&&null!=(t=window.performance)&&t.getEntriesByType&&(t=window.performance.getEntriesByType("navigation")[0])?(this.perfStatsCollected=!0,{dns:t.domainLookupEnd-t.domainLookupStart,tls:t.secureConnectionStart?t.requestStart-t.secureConnectionStart:0,conn:t.secureConnectionStart?t.secureConnectionStart-t.connectStart:t.connectEnd-t.connectStart,response:t.responseEnd-t.responseStart,render:t.domComplete-t.domContentLoadedEventEnd,dom_load:t.domContentLoadedEventEnd-t.responseEnd,page_load:t.loadEventStart,ttfb:t.responseStart-t.requestStart}):{}},t.prototype.heartbeat=function(){var t;(null!=(t=this.pageViewsOptions)&&t.heartbeatOnBackground||"hidden"!==document.visibilityState)&&(t={pid:this.projectID},this.sendRequest("hb",t))},t.prototype.checkIgnore=function(t){var e,n=null==(e=this.pageViewsOptions)?void 0:e.ignore;if(Array.isArray(n))for(var o=0;o<n.length;++o){if(n[o]===t)return!0;if(n[o]instanceof RegExp&&n[o].test(t))return!0}return!1},t.prototype.trackPathChange=function(){var t;this.pageData&&(t=a(),this.pageData.path!==t)&&this.trackPage(t,!1)},t.prototype.trackPage=function(t,e){var n;void 0===e&&(e=!1),this.pageData&&(this.pageData.path=t,this.checkIgnore(t)||(n=this.getPerformanceStats(),e={pid:this.projectID,lc:void 0!==navigator.languages?navigator.languages[0]:navigator.language,tz:function(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone}catch(t){}}(),ref:document.referrer||void 0,so:o(i),me:o(s),ca:o(r),unique:e,pg:t,perf:n},this.sendRequest("",e)))},t.prototype.debug=function(t){var e;null!=(e=this.options)&&e.debug&&console.log("[Swetrix]",t)},t.prototype.canTrack=function(){var t;return null!=(t=this.options)&&t.disabled?(this.debug("Tracking disabled: the 'disabled' setting is set to true."),!1):"undefined"==typeof window?(this.debug("Tracking disabled: script does not run in browser environment."),!1):null!=(t=this.options)&&t.respectDNT&&"1"===(null==(t=window.navigator)?void 0:t.doNotTrack)?(this.debug("Tracking disabled: respecting user's 'Do Not Track' preference."),!1):!(!(null!=(t=this.options)&&t.debug||"localhost"!==(null===location||void 0===location?void 0:location.hostname)&&"127.0.0.1"!==(null===location||void 0===location?void 0:location.hostname)&&""!==(null===location||void 0===location?void 0:location.hostname))||null!==navigator&&void 0!==navigator&&navigator.webdriver&&(this.debug("Tracking disabled: navigation is automated by WebDriver."),1))},t.prototype.sendRequest=function(t,e){var n=(null==(n=this.options)?void 0:n.apiURL)||"https://api.swetrix.com/log",o=new XMLHttpRequest;o.open("POST","".concat(n,"/").concat(t),!0),o.setRequestHeader("Content-Type","application/json"),o.send(JSON.stringify(e))},t);function t(t,e){this.projectID=t,this.options=e,this.pageData=null,this.pageViewsOptions=null,this.perfStatsCollected=!1,this.trackPathChange=this.trackPathChange.bind(this),this.heartbeat=this.heartbeat.bind(this)}n.LIB_INSTANCE=null,n.init=function(t,e){return n.LIB_INSTANCE||(n.LIB_INSTANCE=new u(t,e)),n.LIB_INSTANCE},n.track=function(t){n.LIB_INSTANCE&&n.LIB_INSTANCE.track(t)},n.trackViews=function(e){return new Promise(function(t){n.LIB_INSTANCE?"complete"===document.readyState?t(n.LIB_INSTANCE.trackPageViews(e)):window.addEventListener("load",function(){t(n.LIB_INSTANCE.trackPageViews(e))}):t(c)})},Object.defineProperty(n,"__esModule",{value:!0})});
@@ -0,0 +1,308 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.swetrix = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+
22
+ var __assign = function() {
23
+ __assign = Object.assign || function __assign(t) {
24
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
25
+ s = arguments[i];
26
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
27
+ }
28
+ return t;
29
+ };
30
+ return __assign.apply(this, arguments);
31
+ };
32
+
33
+ var findInSearch = function (exp) {
34
+ var res = location.search.match(exp);
35
+ return (res && res[2]) || undefined;
36
+ };
37
+ var utmSourceRegex = /[?&](ref|source|utm_source)=([^?&]+)/;
38
+ var utmCampaignRegex = /[?&](utm_campaign)=([^?&]+)/;
39
+ var utmMediumRegex = /[?&](utm_medium)=([^?&]+)/;
40
+ var isInBrowser = function () {
41
+ return typeof window !== 'undefined';
42
+ };
43
+ var isLocalhost = function () {
44
+ return (location === null || location === void 0 ? void 0 : location.hostname) === 'localhost' || (location === null || location === void 0 ? void 0 : location.hostname) === '127.0.0.1' || (location === null || location === void 0 ? void 0 : location.hostname) === '';
45
+ };
46
+ var isAutomated = function () {
47
+ return navigator === null || navigator === void 0 ? void 0 : navigator.webdriver;
48
+ };
49
+ var getLocale = function () {
50
+ return typeof navigator.languages !== 'undefined' ? navigator.languages[0] : navigator.language;
51
+ };
52
+ var getTimezone = function () {
53
+ try {
54
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
55
+ }
56
+ catch (e) {
57
+ return;
58
+ }
59
+ };
60
+ var getReferrer = function () {
61
+ return document.referrer || undefined;
62
+ };
63
+ var getUTMSource = function () { return findInSearch(utmSourceRegex); };
64
+ var getUTMMedium = function () { return findInSearch(utmMediumRegex); };
65
+ var getUTMCampaign = function () { return findInSearch(utmCampaignRegex); };
66
+ var getPath = function () {
67
+ // TODO: Maybe we should also include such data as location.hash or location.search
68
+ return location.pathname || '';
69
+ };
70
+
71
+ var defaultPageActions = {
72
+ stop: function () { },
73
+ };
74
+ var DEFAULT_API_HOST = 'https://api.swetrix.com/log';
75
+ var Lib = /** @class */ (function () {
76
+ function Lib(projectID, options) {
77
+ this.projectID = projectID;
78
+ this.options = options;
79
+ this.pageData = null;
80
+ this.pageViewsOptions = null;
81
+ this.perfStatsCollected = false;
82
+ this.trackPathChange = this.trackPathChange.bind(this);
83
+ this.heartbeat = this.heartbeat.bind(this);
84
+ }
85
+ Lib.prototype.track = function (event) {
86
+ if (!this.canTrack()) {
87
+ return;
88
+ }
89
+ var data = __assign({ pid: this.projectID }, event);
90
+ this.sendRequest('custom', data);
91
+ };
92
+ Lib.prototype.trackPageViews = function (options) {
93
+ if (!this.canTrack()) {
94
+ return defaultPageActions;
95
+ }
96
+ if (this.pageData) {
97
+ return this.pageData.actions;
98
+ }
99
+ this.pageViewsOptions = options;
100
+ var hbInterval, interval;
101
+ if (!(options === null || options === void 0 ? void 0 : options.unique)) {
102
+ interval = setInterval(this.trackPathChange, 2000);
103
+ }
104
+ if (!(options === null || options === void 0 ? void 0 : options.noHeartbeat)) {
105
+ setTimeout(this.heartbeat, 3000);
106
+ hbInterval = setInterval(this.heartbeat, 28000);
107
+ }
108
+ var path = getPath();
109
+ this.pageData = {
110
+ path: path,
111
+ actions: {
112
+ stop: function () {
113
+ clearInterval(interval);
114
+ clearInterval(hbInterval);
115
+ },
116
+ },
117
+ };
118
+ this.trackPage(path, options === null || options === void 0 ? void 0 : options.unique);
119
+ return this.pageData.actions;
120
+ };
121
+ Lib.prototype.getPerformanceStats = function () {
122
+ var _a;
123
+ if (!this.canTrack() || this.perfStatsCollected || !((_a = window.performance) === null || _a === void 0 ? void 0 : _a.getEntriesByType)) {
124
+ return {};
125
+ }
126
+ var perf = window.performance.getEntriesByType('navigation')[0];
127
+ if (!perf) {
128
+ return {};
129
+ }
130
+ this.perfStatsCollected = true;
131
+ return {
132
+ // Network
133
+ // @ts-ignore
134
+ dns: perf.domainLookupEnd - perf.domainLookupStart,
135
+ // @ts-ignore
136
+ tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0,
137
+ // @ts-ignore
138
+ conn: perf.secureConnectionStart ? perf.secureConnectionStart - perf.connectStart : perf.connectEnd - perf.connectStart,
139
+ // @ts-ignore
140
+ response: perf.responseEnd - perf.responseStart,
141
+ // Frontend
142
+ // @ts-ignore
143
+ render: perf.domComplete - perf.domContentLoadedEventEnd,
144
+ // @ts-ignore
145
+ dom_load: perf.domContentLoadedEventEnd - perf.responseEnd,
146
+ // @ts-ignore
147
+ page_load: perf.loadEventStart,
148
+ // Backend
149
+ // @ts-ignore
150
+ ttfb: perf.responseStart - perf.requestStart,
151
+ };
152
+ };
153
+ Lib.prototype.heartbeat = function () {
154
+ var _a;
155
+ if (!((_a = this.pageViewsOptions) === null || _a === void 0 ? void 0 : _a.heartbeatOnBackground) && document.visibilityState === 'hidden') {
156
+ return;
157
+ }
158
+ var data = {
159
+ pid: this.projectID,
160
+ };
161
+ this.sendRequest('hb', data);
162
+ };
163
+ Lib.prototype.checkIgnore = function (path) {
164
+ var _a;
165
+ var ignore = (_a = this.pageViewsOptions) === null || _a === void 0 ? void 0 : _a.ignore;
166
+ if (Array.isArray(ignore)) {
167
+ for (var i = 0; i < ignore.length; ++i) {
168
+ if (ignore[i] === path)
169
+ return true;
170
+ // @ts-ignore
171
+ if (ignore[i] instanceof RegExp && ignore[i].test(path))
172
+ return true;
173
+ }
174
+ }
175
+ return false;
176
+ };
177
+ // Tracking path changes. If path changes -> calling this.trackPage method
178
+ Lib.prototype.trackPathChange = function () {
179
+ if (!this.pageData)
180
+ return;
181
+ var newPath = getPath();
182
+ var path = this.pageData.path;
183
+ if (path !== newPath) {
184
+ this.trackPage(newPath, false);
185
+ }
186
+ };
187
+ Lib.prototype.trackPage = function (pg, unique) {
188
+ if (unique === void 0) { unique = false; }
189
+ if (!this.pageData)
190
+ return;
191
+ this.pageData.path = pg;
192
+ if (this.checkIgnore(pg))
193
+ return;
194
+ var perf = this.getPerformanceStats();
195
+ var data = {
196
+ pid: this.projectID,
197
+ lc: getLocale(),
198
+ tz: getTimezone(),
199
+ ref: getReferrer(),
200
+ so: getUTMSource(),
201
+ me: getUTMMedium(),
202
+ ca: getUTMCampaign(),
203
+ unique: unique,
204
+ pg: pg,
205
+ perf: perf,
206
+ };
207
+ this.sendRequest('', data);
208
+ };
209
+ Lib.prototype.debug = function (message) {
210
+ var _a;
211
+ if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.debug) {
212
+ console.log('[Swetrix]', message);
213
+ }
214
+ };
215
+ Lib.prototype.canTrack = function () {
216
+ var _a, _b, _c, _d;
217
+ if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.disabled) {
218
+ this.debug('Tracking disabled: the \'disabled\' setting is set to true.');
219
+ return false;
220
+ }
221
+ if (!isInBrowser()) {
222
+ this.debug('Tracking disabled: script does not run in browser environment.');
223
+ return false;
224
+ }
225
+ if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.respectDNT) && ((_c = window.navigator) === null || _c === void 0 ? void 0 : _c.doNotTrack) === '1') {
226
+ this.debug('Tracking disabled: respecting user\'s \'Do Not Track\' preference.');
227
+ return false;
228
+ }
229
+ if (!((_d = this.options) === null || _d === void 0 ? void 0 : _d.debug) && isLocalhost()) {
230
+ return false;
231
+ }
232
+ if (isAutomated()) {
233
+ this.debug('Tracking disabled: navigation is automated by WebDriver.');
234
+ return false;
235
+ }
236
+ return true;
237
+ };
238
+ Lib.prototype.sendRequest = function (path, body) {
239
+ var _a;
240
+ var host = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.apiURL) || DEFAULT_API_HOST;
241
+ var req = new XMLHttpRequest();
242
+ req.open('POST', "".concat(host, "/").concat(path), true);
243
+ req.setRequestHeader('Content-Type', 'application/json');
244
+ req.send(JSON.stringify(body));
245
+ };
246
+ return Lib;
247
+ }());
248
+
249
+ exports.LIB_INSTANCE = null;
250
+ /**
251
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
252
+ *
253
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
254
+ * @param {LibOptions} options Options related to the tracking.
255
+ * @returns {Lib} Instance of the Swetrix.js.
256
+ */
257
+ function init(pid, options) {
258
+ if (!exports.LIB_INSTANCE) {
259
+ exports.LIB_INSTANCE = new Lib(pid, options);
260
+ }
261
+ return exports.LIB_INSTANCE;
262
+ }
263
+ /**
264
+ * With this function you are able to track any custom events you want.
265
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
266
+ * The total number of track calls and their conversion rate will be saved.
267
+ *
268
+ * @param {TrackEventOptions} event The options related to the custom event.
269
+ */
270
+ function track(event) {
271
+ if (!exports.LIB_INSTANCE)
272
+ return;
273
+ exports.LIB_INSTANCE.track(event);
274
+ }
275
+ /**
276
+ * With this function you are able to track any custom events you want.
277
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
278
+ * The total number of track calls and their conversion rate will be saved.
279
+ *
280
+ * @param {PageViewsOptions} options The options related to the custom event.
281
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
282
+ */
283
+ function trackViews(options) {
284
+ return new Promise(function (resolve) {
285
+ if (!exports.LIB_INSTANCE) {
286
+ resolve(defaultPageActions);
287
+ return;
288
+ }
289
+ // We need to verify that document.readyState is complete for the performance stats to be collected correctly.
290
+ if (document.readyState === 'complete') {
291
+ resolve(exports.LIB_INSTANCE.trackPageViews(options));
292
+ }
293
+ else {
294
+ window.addEventListener('load', function () {
295
+ // @ts-ignore
296
+ resolve(exports.LIB_INSTANCE.trackPageViews(options));
297
+ });
298
+ }
299
+ });
300
+ }
301
+
302
+ exports.init = init;
303
+ exports.track = track;
304
+ exports.trackViews = trackViews;
305
+
306
+ Object.defineProperty(exports, '__esModule', { value: true });
307
+
308
+ }));
package/package.json CHANGED
@@ -1,41 +1,51 @@
1
1
  {
2
2
  "name": "swetrix",
3
- "version": "1.3.1",
3
+ "version": "2.0.0",
4
4
  "description": "The JavaScript analytics client for Swetrix Analytics",
5
5
  "main": "dist/swetrix.cjs.js",
6
6
  "module": "dist/swetrix.es5.js",
7
7
  "browser": "dist/swetrix.js",
8
+ "origbrowser": "dist/swetrix.orig.js",
8
9
  "esnext": "dist/esnext/index.js",
9
10
  "typings": "dist/esnext/index.d.ts",
10
- "scripts": {
11
- "prebuild": "rimraf dist",
12
- "prepublish": "npm run build",
13
- "build": "rollup -c && tsc -p tsconfig.esnext.json",
14
- "start": "rollup -c -w",
15
- "tsc": "tsc -p tsconfig.esnext.json"
16
- },
11
+ "keywords": [
12
+ "swetrix",
13
+ "analytics",
14
+ "monitoring",
15
+ "metrics",
16
+ "privacy"
17
+ ],
17
18
  "repository": {
18
19
  "type": "git",
19
20
  "url": "git+https://github.com/Swetrix/swetrix-js.git"
20
21
  },
21
22
  "author": "Andrii R. <contact@swetrix.com>",
23
+ "funding": "https://ko-fi.com/andriir",
22
24
  "license": "MIT",
23
25
  "bugs": {
24
26
  "url": "https://github.com/Swetrix/swetrix-js/issues"
25
27
  },
26
28
  "homepage": "https://swetrix.com/docs",
27
29
  "dependencies": {
28
- "@types/node": "^14.18.0"
30
+ "@types/node": "^18.11.18",
31
+ "tslib": "^2.4.1"
29
32
  },
30
33
  "devDependencies": {
31
- "@rollup/plugin-commonjs": "^21.0.1",
32
- "@rollup/plugin-node-resolve": "^13.0.6",
34
+ "@rollup/plugin-commonjs": "^24.0.0",
35
+ "@rollup/plugin-node-resolve": "^15.0.1",
33
36
  "rimraf": "^3.0.2",
34
- "rollup": "^2.61.1",
37
+ "rollup": "^2.79.1",
35
38
  "rollup-plugin-node-resolve": "^5.2.0",
36
39
  "rollup-plugin-sourcemaps": "^0.6.3",
37
- "rollup-plugin-typescript2": "^0.30.0",
40
+ "rollup-plugin-typescript2": "^0.34.1",
38
41
  "rollup-plugin-uglify": "^6.0.4",
39
- "typescript": "^4.5.3"
42
+ "typescript": "^4.9.4"
43
+ },
44
+ "scripts": {
45
+ "prebuild": "rimraf dist",
46
+ "prepublish": "npm run build",
47
+ "build": "rollup -c && tsc -p tsconfig.esnext.json",
48
+ "start": "rollup -c -w",
49
+ "tsc": "tsc -p tsconfig.esnext.json"
40
50
  }
41
- }
51
+ }
package/rollup.config.js CHANGED
@@ -11,6 +11,7 @@ export default [
11
11
  output: [
12
12
  { file: pkg.main, format: 'cjs' },
13
13
  { file: pkg.module, format: 'es' },
14
+ { file: pkg.origbrowser, format: 'umd', name: 'swetrix' },
14
15
  ],
15
16
  plugins: [
16
17
  typescript(), nodeResolve(), commonjs(), sourceMaps(),
package/src/Lib.ts CHANGED
@@ -4,58 +4,77 @@ import {
4
4
  } from './utils'
5
5
 
6
6
  export interface LibOptions {
7
- // When set to `true`, all tracking logs will be
8
- // printed to console and localhost events will be sent to server.
7
+ /**
8
+ * When set to `true`, all tracking logs will be printed to console and localhost events will be sent to server.
9
+ */
9
10
  debug?: boolean
10
11
 
11
- // When set to `true`, the tracking library won't send any data to server.
12
- // Useful for development purposes when this value is set based on `.env` var.
12
+ /**
13
+ * When set to `true`, the tracking library won't send any data to server.
14
+ * Useful for development purposes when this value is set based on `.env` var.
15
+ */
13
16
  disabled?: boolean
14
17
 
15
- // By setting this flag to `true`, we will not collect ANY kind of data about the user
16
- // with the DNT setting.
18
+ /**
19
+ * By setting this flag to `true`, we will not collect ANY kind of data about the user with the DNT setting.
20
+ */
17
21
  respectDNT?: boolean
18
22
 
19
- // Set a custom URL of the API server (for selfhosted variants of Swetrix)
23
+ /** Set a custom URL of the API server (for selfhosted variants of Swetrix). */
20
24
  apiURL?: string
21
25
  }
22
26
 
23
27
  export interface TrackEventOptions {
24
- // The event name
28
+ /** The custom event name. */
25
29
  ev: string
26
30
 
27
- // If true, only 1 event with the same ID will be saved per user session
31
+ /** If set to `true`, only 1 event with the same ID will be saved per user session. */
28
32
  unique?: boolean
29
33
  }
30
34
 
35
+ /**
36
+ * The object returned by `trackPageViews()`, used to stop tracking pages.
37
+ */
38
+ export interface PageActions {
39
+ /** Stops the tracking of pages. */
40
+ stop: () => void
41
+ }
42
+
31
43
  export interface PageData {
32
- // Current URL path
44
+ /** Current URL path. */
33
45
  path: string
34
46
 
35
- // Object with actions related to tracking page views which are abailable to end user
36
- actions: object
47
+ /** The object returned by `trackPageViews()`, used to stop tracking pages. */
48
+ actions: PageActions
37
49
  }
38
50
 
39
51
  export interface PageViewsOptions {
40
- // If true, only unique events will be saved
41
- // This param is useful when tracking single-page landing websites
52
+ /**
53
+ * If set to `true`, only unique events will be saved.
54
+ * This param is useful when tracking single-page landing websites.
55
+ */
42
56
  unique?: boolean
43
57
 
44
- // A list of Regular Expressions or string pathes to ignore
45
- ignore?: Array<any>
58
+ /** A list of Regular Expressions or string pathes to ignore. */
59
+ ignore?: Array<string | RegExp>
46
60
 
47
- // Do not send Heartbeat requests to the server
61
+ /** Do not send Heartbeat requests to the server. */
48
62
  noHeartbeat?: boolean
49
63
 
50
- // Send Heartbeat requests when the website tab is not active in the browser
64
+ /** Send Heartbeat requests when the website tab is not active in the browser. */
51
65
  heartbeatOnBackground?: boolean
52
66
  }
53
67
 
68
+ export const defaultPageActions = {
69
+ stop() {},
70
+ }
71
+
54
72
  const DEFAULT_API_HOST = 'https://api.swetrix.com/log'
55
73
 
56
74
  export class Lib {
57
75
  private pageData: PageData | null = null
58
76
  private pageViewsOptions: PageViewsOptions | null | undefined = null
77
+ private perfStatsCollected: Boolean = false
59
78
 
60
79
  constructor(private projectID: string, private options?: LibOptions) {
61
80
  this.trackPathChange = this.trackPathChange.bind(this)
@@ -74,9 +93,9 @@ export class Lib {
74
93
  this.sendRequest('custom', data)
75
94
  }
76
95
 
77
- trackPageViews(options?: PageViewsOptions): void | object {
96
+ trackPageViews(options?: PageViewsOptions): PageActions {
78
97
  if (!this.canTrack()) {
79
- return
98
+ return defaultPageActions
80
99
  }
81
100
 
82
101
  if (this.pageData) {
@@ -110,6 +129,45 @@ export class Lib {
110
129
  return this.pageData.actions
111
130
  }
112
131
 
132
+ getPerformanceStats(): object {
133
+ if (!this.canTrack() || this.perfStatsCollected || !window.performance?.getEntriesByType) {
134
+ return {}
135
+ }
136
+
137
+ const perf = window.performance.getEntriesByType('navigation')[0]
138
+
139
+ if (!perf) {
140
+ return {}
141
+ }
142
+
143
+ this.perfStatsCollected = true
144
+
145
+ return {
146
+ // Network
147
+ // @ts-ignore
148
+ dns: perf.domainLookupEnd - perf.domainLookupStart, // DNS Resolution
149
+ // @ts-ignore
150
+ tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0, // TLS Setup; checking if secureConnectionStart is not 0 (it's 0 for non-https websites)
151
+ // @ts-ignore
152
+ conn: perf.secureConnectionStart ? perf.secureConnectionStart - perf.connectStart : perf.connectEnd - perf.connectStart, // Connection time
153
+ // @ts-ignore
154
+ response: perf.responseEnd - perf.responseStart, // Response Time (Download)
155
+
156
+ // Frontend
157
+ // @ts-ignore
158
+ render: perf.domComplete - perf.domContentLoadedEventEnd, // Browser rendering the HTML time
159
+ // @ts-ignore
160
+ dom_load: perf.domContentLoadedEventEnd - perf.responseEnd, // DOM loading timing
161
+ // @ts-ignore
162
+ page_load: perf.loadEventStart, // Page load time
163
+
164
+ // Backend
165
+ // @ts-ignore
166
+ ttfb: perf.responseStart - perf.requestStart,
167
+ }
168
+ }
169
+
170
+
113
171
  private heartbeat(): void {
114
172
  if (!this.pageViewsOptions?.heartbeatOnBackground && document.visibilityState === 'hidden') {
115
173
  return
@@ -128,6 +186,7 @@ export class Lib {
128
186
  if (Array.isArray(ignore)) {
129
187
  for (let i = 0; i < ignore.length; ++i) {
130
188
  if (ignore[i] === path) return true
189
+ // @ts-ignore
131
190
  if (ignore[i] instanceof RegExp && ignore[i].test(path)) return true
132
191
  }
133
192
  }
@@ -151,6 +210,8 @@ export class Lib {
151
210
 
152
211
  if (this.checkIgnore(pg)) return
153
212
 
213
+ const perf = this.getPerformanceStats()
214
+
154
215
  const data = {
155
216
  pid: this.projectID,
156
217
  lc: getLocale(),
@@ -161,6 +222,7 @@ export class Lib {
161
222
  ca: getUTMCampaign(),
162
223
  unique,
163
224
  pg,
225
+ perf,
164
226
  }
165
227
 
166
228
  this.sendRequest('', data)
package/src/index.ts CHANGED
@@ -1,10 +1,17 @@
1
- import { Lib, LibOptions, TrackEventOptions, PageViewsOptions } from './Lib'
1
+ import {
2
+ Lib, LibOptions, TrackEventOptions, PageViewsOptions, PageActions, defaultPageActions,
3
+ } from './Lib'
2
4
 
3
5
  export let LIB_INSTANCE: Lib | null = null
4
6
 
5
- // Initialise the tracking library instance (other methods won't work if the library
6
- // is not initialised)
7
- export function init (pid: string, options?: LibOptions): Lib {
7
+ /**
8
+ * Initialise the tracking library instance (other methods won't work if the library is not initialised).
9
+ *
10
+ * @param {string} pid The Project ID to link the instance of Swetrix.js to.
11
+ * @param {LibOptions} options Options related to the tracking.
12
+ * @returns {Lib} Instance of the Swetrix.js.
13
+ */
14
+ export function init(pid: string, options?: LibOptions): Lib {
8
15
  if (!LIB_INSTANCE) {
9
16
  LIB_INSTANCE = new Lib(pid, options)
10
17
  }
@@ -12,15 +19,42 @@ export function init (pid: string, options?: LibOptions): Lib {
12
19
  return LIB_INSTANCE
13
20
  }
14
21
 
15
- // Tracks custom events
16
- export function track (event: TrackEventOptions): void {
22
+ /**
23
+ * With this function you are able to track any custom events you want.
24
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
25
+ * The total number of track calls and their conversion rate will be saved.
26
+ *
27
+ * @param {TrackEventOptions} event The options related to the custom event.
28
+ */
29
+ export function track(event: TrackEventOptions): void {
17
30
  if (!LIB_INSTANCE) return
18
31
 
19
32
  LIB_INSTANCE.track(event)
20
33
  }
21
34
 
22
- export function trackViews (options?: PageViewsOptions): void {
23
- if (!LIB_INSTANCE) return
35
+ /**
36
+ * With this function you are able to track any custom events you want.
37
+ * You should never send any identifiable data (like User ID, email, session cookie, etc.) as an event name.
38
+ * The total number of track calls and their conversion rate will be saved.
39
+ *
40
+ * @param {PageViewsOptions} options The options related to the custom event.
41
+ * @returns {PageActions} The actions related to the tracking. Used to stop tracking pages.
42
+ */
43
+ export function trackViews(options?: PageViewsOptions): Promise<PageActions> {
44
+ return new Promise((resolve) => {
45
+ if (!LIB_INSTANCE) {
46
+ resolve(defaultPageActions)
47
+ return
48
+ }
24
49
 
25
- LIB_INSTANCE.trackPageViews(options)
26
- }
50
+ // We need to verify that document.readyState is complete for the performance stats to be collected correctly.
51
+ if (document.readyState === 'complete') {
52
+ resolve(LIB_INSTANCE.trackPageViews(options))
53
+ } else {
54
+ window.addEventListener('load', () => {
55
+ // @ts-ignore
56
+ resolve(LIB_INSTANCE.trackPageViews(options))
57
+ })
58
+ }
59
+ })
60
+ }