swetrix 2.4.0 → 3.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.
- package/.prettierrc.js +13 -0
- package/dist/esnext/Lib.d.ts +32 -14
- package/dist/esnext/Lib.js +38 -78
- package/dist/esnext/Lib.js.map +1 -1
- package/dist/esnext/index.js +1 -1
- package/dist/esnext/index.js.map +1 -1
- package/dist/esnext/utils.js.map +1 -1
- package/dist/swetrix.cjs.js +40 -83
- package/dist/swetrix.es5.js +40 -83
- package/dist/swetrix.js +1 -1
- package/dist/swetrix.orig.js +40 -83
- package/package.json +5 -5
- package/src/Lib.ts +88 -99
- package/src/index.ts +2 -4
package/src/Lib.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
isInBrowser,
|
|
3
|
-
|
|
2
|
+
isInBrowser,
|
|
3
|
+
isLocalhost,
|
|
4
|
+
isAutomated,
|
|
5
|
+
getLocale,
|
|
6
|
+
getTimezone,
|
|
7
|
+
getReferrer,
|
|
8
|
+
getUTMCampaign,
|
|
9
|
+
getUTMMedium,
|
|
10
|
+
getUTMSource,
|
|
11
|
+
getPath,
|
|
4
12
|
} from './utils'
|
|
5
13
|
|
|
6
14
|
export interface LibOptions {
|
|
7
15
|
/**
|
|
8
|
-
* When set to `true`,
|
|
16
|
+
* When set to `true`, localhost events will be sent to server.
|
|
9
17
|
*/
|
|
10
|
-
|
|
18
|
+
devMode?: boolean
|
|
11
19
|
|
|
12
20
|
/**
|
|
13
21
|
* When set to `true`, the tracking library won't send any data to server.
|
|
@@ -37,6 +45,29 @@ export interface TrackEventOptions {
|
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
47
|
|
|
48
|
+
// Partial user-editable pageview payload
|
|
49
|
+
export interface IPageViewPayload {
|
|
50
|
+
lc: string | undefined
|
|
51
|
+
tz: string | undefined
|
|
52
|
+
ref: string | undefined
|
|
53
|
+
so: string | undefined
|
|
54
|
+
me: string | undefined
|
|
55
|
+
ca: string | undefined
|
|
56
|
+
pg: string
|
|
57
|
+
prev: string | null | undefined
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface IPerfPayload {
|
|
61
|
+
dns: number
|
|
62
|
+
tls: number
|
|
63
|
+
conn: number
|
|
64
|
+
response: number
|
|
65
|
+
render: number
|
|
66
|
+
dom_load: number
|
|
67
|
+
page_load: number
|
|
68
|
+
ttfb: number
|
|
69
|
+
}
|
|
70
|
+
|
|
40
71
|
/**
|
|
41
72
|
* The object returned by `trackPageViews()`, used to stop tracking pages.
|
|
42
73
|
*/
|
|
@@ -60,21 +91,9 @@ export interface PageViewsOptions {
|
|
|
60
91
|
*/
|
|
61
92
|
unique?: boolean
|
|
62
93
|
|
|
63
|
-
/** A list of Regular Expressions or string pathes to ignore. */
|
|
64
|
-
ignore?: Array<string | RegExp>
|
|
65
|
-
|
|
66
|
-
/** Do not send paths from ignore list to API. If set to `false`, the page view information will be sent to the Swetrix API, but the page will be displayed as a 'Redacted page' in the dashboard. */
|
|
67
|
-
doNotAnonymise?: boolean
|
|
68
|
-
|
|
69
|
-
/** Do not send Heartbeat requests to the server. */
|
|
70
|
-
noHeartbeat?: boolean
|
|
71
|
-
|
|
72
94
|
/** Send Heartbeat requests when the website tab is not active in the browser. */
|
|
73
95
|
heartbeatOnBackground?: boolean
|
|
74
96
|
|
|
75
|
-
/** Disable user-flow */
|
|
76
|
-
noUserFlow?: boolean
|
|
77
|
-
|
|
78
97
|
/**
|
|
79
98
|
* Set to `true` to enable hash-based routing.
|
|
80
99
|
* For example if you have pages like /#/path or want to track pages like /path#hash
|
|
@@ -86,6 +105,14 @@ export interface PageViewsOptions {
|
|
|
86
105
|
* For example if you have pages like /path?search
|
|
87
106
|
*/
|
|
88
107
|
search?: boolean
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Callback to edit / prevent sending pageviews.
|
|
111
|
+
*
|
|
112
|
+
* @param payload - The pageview payload.
|
|
113
|
+
* @returns The edited payload or `false` to prevent sending the pageview. If `true` is returned, the payload will be sent as-is.
|
|
114
|
+
*/
|
|
115
|
+
callback?: (payload: IPageViewPayload) => IPageViewPayload | boolean
|
|
89
116
|
}
|
|
90
117
|
|
|
91
118
|
export const defaultPageActions = {
|
|
@@ -111,6 +138,7 @@ export class Lib {
|
|
|
111
138
|
}
|
|
112
139
|
|
|
113
140
|
const data = {
|
|
141
|
+
...event,
|
|
114
142
|
pid: this.projectID,
|
|
115
143
|
pg: this.activePage,
|
|
116
144
|
lc: getLocale(),
|
|
@@ -119,7 +147,6 @@ export class Lib {
|
|
|
119
147
|
so: getUTMSource(),
|
|
120
148
|
me: getUTMMedium(),
|
|
121
149
|
ca: getUTMCampaign(),
|
|
122
|
-
...event,
|
|
123
150
|
}
|
|
124
151
|
this.sendRequest('custom', data)
|
|
125
152
|
}
|
|
@@ -134,15 +161,14 @@ export class Lib {
|
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
this.pageViewsOptions = options
|
|
137
|
-
let
|
|
164
|
+
let interval: NodeJS.Timeout
|
|
165
|
+
|
|
138
166
|
if (!options?.unique) {
|
|
139
167
|
interval = setInterval(this.trackPathChange, 2000)
|
|
140
168
|
}
|
|
141
169
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
hbInterval = setInterval(this.heartbeat, 28000)
|
|
145
|
-
}
|
|
170
|
+
setTimeout(this.heartbeat, 3000)
|
|
171
|
+
const hbInterval = setInterval(this.heartbeat, 28000)
|
|
146
172
|
|
|
147
173
|
const path = getPath({
|
|
148
174
|
hash: options?.hash,
|
|
@@ -163,12 +189,12 @@ export class Lib {
|
|
|
163
189
|
return this.pageData.actions
|
|
164
190
|
}
|
|
165
191
|
|
|
166
|
-
getPerformanceStats():
|
|
192
|
+
getPerformanceStats(): IPerfPayload | {} {
|
|
167
193
|
if (!this.canTrack() || this.perfStatsCollected || !window.performance?.getEntriesByType) {
|
|
168
194
|
return {}
|
|
169
195
|
}
|
|
170
196
|
|
|
171
|
-
const perf = window.performance.getEntriesByType('navigation')[0]
|
|
197
|
+
const perf = window.performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming
|
|
172
198
|
|
|
173
199
|
if (!perf) {
|
|
174
200
|
return {}
|
|
@@ -178,25 +204,19 @@ export class Lib {
|
|
|
178
204
|
|
|
179
205
|
return {
|
|
180
206
|
// Network
|
|
181
|
-
// @ts-ignore
|
|
182
207
|
dns: perf.domainLookupEnd - perf.domainLookupStart, // DNS Resolution
|
|
183
|
-
// @ts-ignore
|
|
184
208
|
tls: perf.secureConnectionStart ? perf.requestStart - perf.secureConnectionStart : 0, // TLS Setup; checking if secureConnectionStart is not 0 (it's 0 for non-https websites)
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
209
|
+
conn: perf.secureConnectionStart
|
|
210
|
+
? perf.secureConnectionStart - perf.connectStart
|
|
211
|
+
: perf.connectEnd - perf.connectStart, // Connection time
|
|
188
212
|
response: perf.responseEnd - perf.responseStart, // Response Time (Download)
|
|
189
213
|
|
|
190
214
|
// Frontend
|
|
191
|
-
// @ts-ignore
|
|
192
215
|
render: perf.domComplete - perf.domContentLoadedEventEnd, // Browser rendering the HTML time
|
|
193
|
-
// @ts-ignore
|
|
194
216
|
dom_load: perf.domContentLoadedEventEnd - perf.responseEnd, // DOM loading timing
|
|
195
|
-
// @ts-ignore
|
|
196
217
|
page_load: perf.loadEventStart, // Page load time
|
|
197
218
|
|
|
198
219
|
// Backend
|
|
199
|
-
// @ts-ignore
|
|
200
220
|
ttfb: perf.responseStart - perf.requestStart,
|
|
201
221
|
}
|
|
202
222
|
}
|
|
@@ -213,19 +233,6 @@ export class Lib {
|
|
|
213
233
|
this.sendRequest('hb', data)
|
|
214
234
|
}
|
|
215
235
|
|
|
216
|
-
private checkIgnore(path: string): boolean {
|
|
217
|
-
const ignore = this.pageViewsOptions?.ignore
|
|
218
|
-
|
|
219
|
-
if (Array.isArray(ignore)) {
|
|
220
|
-
for (let i = 0; i < ignore.length; ++i) {
|
|
221
|
-
if (ignore[i] === path) return true
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
if (ignore[i] instanceof RegExp && ignore[i].test(path)) return true
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return false
|
|
227
|
-
}
|
|
228
|
-
|
|
229
236
|
// Tracking path changes. If path changes -> calling this.trackPage method
|
|
230
237
|
private trackPathChange(): void {
|
|
231
238
|
if (!this.pageData) return
|
|
@@ -244,13 +251,7 @@ export class Lib {
|
|
|
244
251
|
// Assuming that this function is called in trackPage and this.activePage is not overwritten by new value yet
|
|
245
252
|
// That method of getting previous page works for SPA websites
|
|
246
253
|
if (this.activePage) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (shouldIgnore && this.pageViewsOptions?.doNotAnonymise) {
|
|
250
|
-
return null
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return shouldIgnore ? null : this.activePage
|
|
254
|
+
return this.activePage
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
// Checking if URL is supported by the browser (for example, IE11 does not support it)
|
|
@@ -272,13 +273,7 @@ export class Lib {
|
|
|
272
273
|
return null
|
|
273
274
|
}
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (shouldIgnore && this.pageViewsOptions?.doNotAnonymise) {
|
|
278
|
-
return null
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return shouldIgnore ? null : pathname
|
|
276
|
+
return pathname
|
|
282
277
|
} catch {
|
|
283
278
|
return null
|
|
284
279
|
}
|
|
@@ -291,68 +286,62 @@ export class Lib {
|
|
|
291
286
|
if (!this.pageData) return
|
|
292
287
|
this.pageData.path = pg
|
|
293
288
|
|
|
294
|
-
const shouldIgnore = this.checkIgnore(pg)
|
|
295
|
-
|
|
296
|
-
if (shouldIgnore && this.pageViewsOptions?.doNotAnonymise) return
|
|
297
|
-
|
|
298
289
|
const perf = this.getPerformanceStats()
|
|
299
290
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (!this.pageViewsOptions?.noUserFlow) {
|
|
303
|
-
prev = this.getPreviousPage()
|
|
304
|
-
}
|
|
291
|
+
const prev = this.getPreviousPage()
|
|
305
292
|
|
|
306
293
|
this.activePage = pg
|
|
307
|
-
this.submitPageView(
|
|
294
|
+
this.submitPageView(pg, prev, unique, perf, true)
|
|
308
295
|
}
|
|
309
296
|
|
|
310
|
-
submitPageView(
|
|
311
|
-
|
|
297
|
+
submitPageView(
|
|
298
|
+
pg: string,
|
|
299
|
+
prev: string | null | undefined,
|
|
300
|
+
unique: boolean,
|
|
301
|
+
perf: IPerfPayload | {},
|
|
302
|
+
evokeCallback?: boolean,
|
|
303
|
+
): void {
|
|
304
|
+
const privateData = {
|
|
312
305
|
pid: this.projectID,
|
|
306
|
+
perf,
|
|
307
|
+
unique,
|
|
308
|
+
}
|
|
309
|
+
const pvPayload = {
|
|
313
310
|
lc: getLocale(),
|
|
314
311
|
tz: getTimezone(),
|
|
315
312
|
ref: getReferrer(),
|
|
316
313
|
so: getUTMSource(),
|
|
317
314
|
me: getUTMMedium(),
|
|
318
315
|
ca: getUTMCampaign(),
|
|
319
|
-
unique,
|
|
320
316
|
pg,
|
|
321
|
-
perf,
|
|
322
317
|
prev,
|
|
323
318
|
}
|
|
324
319
|
|
|
325
|
-
this.
|
|
326
|
-
|
|
320
|
+
if (evokeCallback && this.pageViewsOptions?.callback) {
|
|
321
|
+
const callbackResult = this.pageViewsOptions.callback(pvPayload)
|
|
327
322
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
}
|
|
323
|
+
if (callbackResult === false) {
|
|
324
|
+
return
|
|
325
|
+
}
|
|
333
326
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return false
|
|
327
|
+
if (callbackResult && typeof callbackResult === 'object') {
|
|
328
|
+
Object.assign(pvPayload, callbackResult)
|
|
329
|
+
}
|
|
338
330
|
}
|
|
339
331
|
|
|
340
|
-
|
|
341
|
-
this.debug('Tracking disabled: script does not run in browser environment.')
|
|
342
|
-
return false
|
|
343
|
-
}
|
|
332
|
+
Object.assign(pvPayload, privateData)
|
|
344
333
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
return false
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (!this.options?.debug && isLocalhost()) {
|
|
351
|
-
return false
|
|
352
|
-
}
|
|
334
|
+
this.sendRequest('', pvPayload)
|
|
335
|
+
}
|
|
353
336
|
|
|
354
|
-
|
|
355
|
-
|
|
337
|
+
private canTrack(): boolean {
|
|
338
|
+
if (
|
|
339
|
+
this.options?.disabled ||
|
|
340
|
+
!isInBrowser() ||
|
|
341
|
+
(this.options?.respectDNT && window.navigator?.doNotTrack === '1') ||
|
|
342
|
+
(!this.options?.devMode && isLocalhost()) ||
|
|
343
|
+
isAutomated()
|
|
344
|
+
) {
|
|
356
345
|
return false
|
|
357
346
|
}
|
|
358
347
|
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Lib, LibOptions, TrackEventOptions, PageViewsOptions, PageActions, defaultPageActions,
|
|
3
|
-
} from './Lib'
|
|
1
|
+
import { Lib, LibOptions, TrackEventOptions, PageViewsOptions, PageActions, defaultPageActions } from './Lib'
|
|
4
2
|
|
|
5
3
|
export let LIB_INSTANCE: Lib | null = null
|
|
6
4
|
|
|
@@ -62,7 +60,7 @@ export function trackViews(options?: PageViewsOptions): Promise<PageActions> {
|
|
|
62
60
|
/**
|
|
63
61
|
* This function is used to manually track a page view event.
|
|
64
62
|
* It's useful if your application uses esoteric routing which is not supported by Swetrix by default.
|
|
65
|
-
*
|
|
63
|
+
*
|
|
66
64
|
* @param path Path of the page to track (this will be sent to the Swetrix API and displayed in the dashboard).
|
|
67
65
|
* @param prev Path of the previous page.
|
|
68
66
|
* @param unique If set to `true`, only 1 event with the same ID will be saved per user session.
|