coveo.analytics 2.30.56 → 2.32.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/README.md +37 -43
- package/dist/browser.mjs +513 -357
- package/dist/coveoua.browser.js +1 -1
- package/dist/coveoua.browser.js.map +1 -1
- package/dist/coveoua.debug.js +542 -359
- package/dist/coveoua.debug.js.map +1 -1
- package/dist/coveoua.js +1 -1
- package/dist/coveoua.js.map +1 -1
- package/dist/definitions/client/analytics.d.ts +3 -2
- package/dist/definitions/client/runtimeEnvironment.d.ts +1 -1
- package/dist/definitions/donottrack.d.ts +1 -0
- package/dist/definitions/react-native/index.d.ts +1 -2
- package/dist/definitions/version.d.ts +1 -1
- package/dist/library.cjs +15350 -3699
- package/dist/library.es.js +513 -357
- package/dist/library.js +15350 -3699
- package/dist/library.mjs +15350 -3699
- package/dist/react-native.es.js +634 -460
- package/modules/package.json +9 -9
- package/package.json +60 -91
- package/react-native/package.json +7 -7
- package/src/caseAssist/caseAssistActions.ts +51 -50
- package/src/caseAssist/caseAssistClient.spec.ts +328 -297
- package/src/caseAssist/caseAssistClient.ts +201 -185
- package/src/client/analytics.spec.ts +724 -703
- package/src/client/analytics.ts +677 -602
- package/src/client/analyticsBeaconClient.spec.ts +195 -188
- package/src/client/analyticsBeaconClient.ts +99 -88
- package/src/client/analyticsFetchClient.ts +77 -61
- package/src/client/analyticsRequestClient.ts +17 -17
- package/src/client/location.ts +3 -3
- package/src/client/measurementProtocolMapper.ts +54 -45
- package/src/client/measurementProtocolMapping/baseMeasurementProtocolMapper.ts +48 -44
- package/src/client/measurementProtocolMapping/commerceMeasurementProtocolMapper.ts +133 -121
- package/src/client/measurementProtocolMapping/serviceMeasurementProtocolMapper.ts +17 -17
- package/src/client/noopAnalytics.ts +80 -68
- package/src/client/runtimeEnvironment.ts +50 -41
- package/src/client/utils.spec.ts +112 -97
- package/src/client/utils.ts +39 -39
- package/src/cookieutils.spec.ts +59 -0
- package/src/cookieutils.ts +40 -39
- package/src/coveoua/browser.ts +14 -12
- package/src/coveoua/library.ts +4 -4
- package/src/coveoua/plugins.ts +36 -34
- package/src/coveoua/simpleanalytics.spec.ts +467 -452
- package/src/coveoua/simpleanalytics.ts +146 -140
- package/src/detector.ts +17 -17
- package/src/donottrack.spec.ts +199 -121
- package/src/donottrack.ts +31 -8
- package/src/events.ts +86 -79
- package/src/formatting/format-array-for-coveo-custom-data.spec.ts +13 -12
- package/src/formatting/format-array-for-coveo-custom-data.ts +18 -18
- package/src/formatting/format-omnibox-metadata.ts +16 -12
- package/src/history.spec.ts +197 -195
- package/src/history.ts +143 -133
- package/src/hook/addDefaultValues.ts +13 -8
- package/src/hook/enhanceViewEvent.ts +17 -17
- package/src/insight/insightClient.spec.ts +1848 -1717
- package/src/insight/insightClient.ts +866 -761
- package/src/insight/insightEvents.ts +57 -56
- package/src/plugins/BasePlugin.ts +125 -121
- package/src/plugins/ec.spec.ts +457 -429
- package/src/plugins/ec.ts +202 -199
- package/src/plugins/link.spec.ts +183 -159
- package/src/plugins/link.ts +88 -85
- package/src/plugins/svc.spec.ts +161 -155
- package/src/plugins/svc.ts +93 -91
- package/src/react-native/index.ts +8 -1
- package/src/react-native/react-native-runtime.ts +33 -33
- package/src/react-native/react-native-utils.ts +1 -1
- package/src/react-native/react-native.spec.ts +31 -21
- package/src/searchPage/searchPageClient.spec.ts +1944 -1794
- package/src/searchPage/searchPageClient.ts +1261 -1040
- package/src/searchPage/searchPageEvents.ts +524 -511
- package/src/storage.spec.ts +51 -51
- package/src/storage.ts +47 -47
- package/dist/definitions/bundle/browser-fetch.d.ts +0 -1
- package/dist/definitions/src/coveoua/browser.d.ts +0 -6
- package/dist/definitions/src/coveoua/headless.d.ts +0 -6
- package/dist/definitions/src/coveoua/library.d.ts +0 -17
- package/dist/definitions/src/coveoua/plugins.d.ts +0 -10
- package/dist/definitions/src/coveoua/simpleanalytics.d.ts +0 -33
- package/dist/definitions/src/react-native/index.d.ts +0 -3
- package/dist/definitions/src/react-native/react-native-runtime.d.ts +0 -19
package/src/history.ts
CHANGED
|
@@ -6,164 +6,174 @@ export const MIN_THRESHOLD_FOR_DUPLICATE_VALUE: number = 1000 * 60;
|
|
|
6
6
|
export const MAX_VALUE_SIZE = 75;
|
|
7
7
|
|
|
8
8
|
export class HistoryStore {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
private store: WebStorage;
|
|
10
|
+
constructor(store?: WebStorage) {
|
|
11
|
+
this.store = store || getAvailableStorage();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated Synchronous method is deprecated, use addElementAsync instead. This method will NOT work with react-native.
|
|
16
|
+
*/
|
|
17
|
+
addElement(elem: HistoryElement) {
|
|
18
|
+
elem.internalTime = new Date().getTime();
|
|
19
|
+
elem = this.cropQueryElement(this.stripEmptyQuery(elem));
|
|
20
|
+
let currentHistory = this.getHistoryWithInternalTime();
|
|
21
|
+
if (currentHistory != null) {
|
|
22
|
+
if (this.isValidEntry(elem)) {
|
|
23
|
+
this.setHistory([elem].concat(currentHistory));
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
this.setHistory([elem]);
|
|
12
27
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} else {
|
|
26
|
-
this.setHistory([elem]);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async addElementAsync(elem: HistoryElement) {
|
|
31
|
-
elem.internalTime = new Date().getTime();
|
|
32
|
-
elem = this.cropQueryElement(this.stripEmptyQuery(elem));
|
|
33
|
-
let currentHistory = await this.getHistoryWithInternalTimeAsync();
|
|
34
|
-
if (currentHistory != null) {
|
|
35
|
-
if (this.isValidEntry(elem)) {
|
|
36
|
-
this.setHistory([elem].concat(currentHistory));
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
this.setHistory([elem]);
|
|
40
|
-
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async addElementAsync(elem: HistoryElement) {
|
|
31
|
+
elem.internalTime = new Date().getTime();
|
|
32
|
+
elem = this.cropQueryElement(this.stripEmptyQuery(elem));
|
|
33
|
+
let currentHistory = await this.getHistoryWithInternalTimeAsync();
|
|
34
|
+
if (currentHistory != null) {
|
|
35
|
+
if (this.isValidEntry(elem)) {
|
|
36
|
+
this.setHistory([elem].concat(currentHistory));
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
this.setHistory([elem]);
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated Synchronous method is deprecated, use getHistoryAsync instead. This method will NOT work with react-native.
|
|
45
|
+
*/
|
|
46
|
+
getHistory(): HistoryElement[] {
|
|
47
|
+
const history = this.getHistoryWithInternalTime();
|
|
48
|
+
return this.stripEmptyQueries(this.stripInternalTime(history));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async getHistoryAsync(): Promise<HistoryElement[]> {
|
|
52
|
+
const history = await this.getHistoryWithInternalTimeAsync();
|
|
53
|
+
return this.stripEmptyQueries(this.stripInternalTime(history));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private getHistoryWithInternalTime(): HistoryElement[] {
|
|
57
|
+
try {
|
|
58
|
+
const elements = this.store.getItem(STORE_KEY);
|
|
59
|
+
if (elements && typeof elements === 'string') {
|
|
60
|
+
return JSON.parse(elements) as HistoryElement[];
|
|
61
|
+
} else {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
// When using the Storage APIs (localStorage/sessionStorage)
|
|
66
|
+
// Safari says that those APIs are available but throws when making
|
|
67
|
+
// a call to them.
|
|
68
|
+
return [];
|
|
49
69
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private async getHistoryWithInternalTimeAsync(): Promise<HistoryElement[]> {
|
|
73
|
+
try {
|
|
74
|
+
const elements = await this.store.getItem(STORE_KEY);
|
|
75
|
+
if (elements) {
|
|
76
|
+
return JSON.parse(elements) as HistoryElement[];
|
|
77
|
+
} else {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// When using the Storage APIs (localStorage/sessionStorage)
|
|
82
|
+
// Safari says that those APIs are available but throws when making
|
|
83
|
+
// a call to them.
|
|
84
|
+
return [];
|
|
54
85
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// When using the Storage APIs (localStorage/sessionStorage)
|
|
66
|
-
// Safari says that those APIs are available but throws when making
|
|
67
|
-
// a call to them.
|
|
68
|
-
return [];
|
|
69
|
-
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setHistory(history: HistoryElement[]) {
|
|
89
|
+
try {
|
|
90
|
+
this.store.setItem(
|
|
91
|
+
STORE_KEY,
|
|
92
|
+
JSON.stringify(history.slice(0, MAX_NUMBER_OF_HISTORY_ELEMENTS))
|
|
93
|
+
);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
/* refer to this.getHistory() */
|
|
70
96
|
}
|
|
97
|
+
}
|
|
71
98
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} else {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
} catch (e) {
|
|
81
|
-
// When using the Storage APIs (localStorage/sessionStorage)
|
|
82
|
-
// Safari says that those APIs are available but throws when making
|
|
83
|
-
// a call to them.
|
|
84
|
-
return [];
|
|
85
|
-
}
|
|
99
|
+
clear() {
|
|
100
|
+
try {
|
|
101
|
+
this.store.removeItem(STORE_KEY);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
/* refer to this.getHistory() */
|
|
86
104
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
getMostRecentElement(): HistoryElement | null {
|
|
108
|
+
let currentHistory = this.getHistoryWithInternalTime();
|
|
109
|
+
if (Array.isArray(currentHistory)) {
|
|
110
|
+
const sorted = currentHistory.sort((first: HistoryElement, second: HistoryElement) => {
|
|
111
|
+
// Internal time might not be set for all history element (on upgrade).
|
|
112
|
+
// Ensure to return the most recent element for which we have a value for internalTime.
|
|
113
|
+
return (second.internalTime || 0) - (first.internalTime || 0);
|
|
114
|
+
});
|
|
115
|
+
return sorted[0];
|
|
94
116
|
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
95
119
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
} catch (e) {
|
|
100
|
-
/* refer to this.getHistory() */
|
|
101
|
-
}
|
|
120
|
+
private cropQueryElement(part: HistoryElement) {
|
|
121
|
+
if (part.name && part.value && part.name.toLowerCase() === 'query') {
|
|
122
|
+
part.value = part.value.slice(0, MAX_VALUE_SIZE);
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (Array.isArray(currentHistory)) {
|
|
107
|
-
const sorted = currentHistory.sort((first: HistoryElement, second: HistoryElement) => {
|
|
108
|
-
// Internal time might not be set for all history element (on upgrade).
|
|
109
|
-
// Ensure to return the most recent element for which we have a value for internalTime.
|
|
110
|
-
return (second.internalTime || 0) - (first.internalTime || 0);
|
|
111
|
-
});
|
|
112
|
-
return sorted[0];
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
125
|
+
return part;
|
|
126
|
+
}
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
part.value = part.value.slice(0, MAX_VALUE_SIZE);
|
|
120
|
-
}
|
|
128
|
+
private isValidEntry(elem: HistoryElement): boolean {
|
|
129
|
+
let lastEntry = this.getMostRecentElement();
|
|
121
130
|
|
|
122
|
-
|
|
131
|
+
if (lastEntry && lastEntry.value == elem.value) {
|
|
132
|
+
return (
|
|
133
|
+
(elem.internalTime || 0) - (lastEntry.internalTime || 0) > MIN_THRESHOLD_FOR_DUPLICATE_VALUE
|
|
134
|
+
);
|
|
123
135
|
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
124
138
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return true;
|
|
139
|
+
private stripInternalTime(history: HistoryElement[]): HistoryElement[] {
|
|
140
|
+
if (Array.isArray(history)) {
|
|
141
|
+
return history.map((part) => {
|
|
142
|
+
const {name, time, value} = part;
|
|
143
|
+
return {name, time, value};
|
|
144
|
+
});
|
|
132
145
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private stripEmptyQuery(part: HistoryElement) {
|
|
150
|
+
const {name, time, value} = part;
|
|
151
|
+
if (
|
|
152
|
+
name &&
|
|
153
|
+
typeof value === 'string' &&
|
|
154
|
+
name.toLowerCase() === 'query' &&
|
|
155
|
+
value.trim() === ''
|
|
156
|
+
) {
|
|
157
|
+
return {name, time};
|
|
142
158
|
}
|
|
143
159
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (name && typeof value === 'string' && name.toLowerCase() === 'query' && value.trim() === '') {
|
|
147
|
-
return {name, time};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return part;
|
|
151
|
-
}
|
|
160
|
+
return part;
|
|
161
|
+
}
|
|
152
162
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
163
|
+
private stripEmptyQueries(history: HistoryElement[]): HistoryElement[] {
|
|
164
|
+
return history.map((part) => this.stripEmptyQuery(part));
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
export interface HistoryElement {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
169
|
+
name: string;
|
|
170
|
+
value?: string;
|
|
171
|
+
time: string;
|
|
172
|
+
internalTime?: number;
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
export interface HistoryViewElement extends HistoryElement {
|
|
166
|
-
|
|
176
|
+
title?: string;
|
|
167
177
|
}
|
|
168
178
|
|
|
169
179
|
export default HistoryStore;
|
|
@@ -2,14 +2,19 @@ import {AnalyticsClientSendEventHook} from '../client/analytics';
|
|
|
2
2
|
import {hasDocument, hasNavigator} from '../detector';
|
|
3
3
|
import {EventType} from '../events';
|
|
4
4
|
|
|
5
|
-
const eventTypesForDefaultValues: string[] = [
|
|
5
|
+
const eventTypesForDefaultValues: string[] = [
|
|
6
|
+
EventType.click,
|
|
7
|
+
EventType.custom,
|
|
8
|
+
EventType.search,
|
|
9
|
+
EventType.view,
|
|
10
|
+
];
|
|
6
11
|
|
|
7
12
|
export const addDefaultValues: AnalyticsClientSendEventHook = (eventType, payload) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return eventTypesForDefaultValues.indexOf(eventType) !== -1
|
|
14
|
+
? {
|
|
15
|
+
language: hasDocument() ? document.documentElement.lang : 'unknown',
|
|
16
|
+
userAgent: hasNavigator() ? navigator.userAgent : 'unknown',
|
|
17
|
+
...payload,
|
|
18
|
+
}
|
|
19
|
+
: payload;
|
|
15
20
|
};
|
|
@@ -3,25 +3,25 @@ import {ViewEventRequest, EventType} from '../events';
|
|
|
3
3
|
import {HistoryStore, STORE_KEY} from '../history';
|
|
4
4
|
|
|
5
5
|
export const enhanceViewEvent: AnalyticsClientSendEventHook = async (eventType, payload) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
if (eventType === EventType.view) {
|
|
7
|
+
await addPageViewToHistory(payload.contentIdValue);
|
|
8
|
+
return {
|
|
9
|
+
location: window.location.toString(),
|
|
10
|
+
referrer: document.referrer,
|
|
11
|
+
title: document.title,
|
|
12
|
+
...payload,
|
|
13
|
+
} as ViewEventRequest;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
return payload;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const addPageViewToHistory = async (pageViewValue: string) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
const store = new HistoryStore();
|
|
21
|
+
const historyElement = {
|
|
22
|
+
name: 'PageView',
|
|
23
|
+
value: pageViewValue,
|
|
24
|
+
time: new Date().toISOString(),
|
|
25
|
+
};
|
|
26
|
+
await store.addElementAsync(historyElement);
|
|
27
27
|
};
|