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
|
@@ -1,78 +1,94 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AnalyticsRequestClient,
|
|
3
|
+
IAnalyticsRequestOptions,
|
|
4
|
+
IAnalyticsClientOptions,
|
|
5
|
+
} from './analyticsRequestClient';
|
|
2
6
|
import {AnyEventResponse, EventType, IRequestPayload} from '../events';
|
|
3
7
|
import {fetch} from 'cross-fetch';
|
|
4
8
|
|
|
5
9
|
export class AnalyticsFetchClient implements AnalyticsRequestClient {
|
|
6
|
-
|
|
10
|
+
constructor(private opts: IAnalyticsClientOptions) {}
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
public async sendEvent(
|
|
13
|
+
eventType: EventType,
|
|
14
|
+
payload: IRequestPayload
|
|
15
|
+
): Promise<AnyEventResponse | void> {
|
|
16
|
+
const {baseUrl, visitorIdProvider, preprocessRequest} = this.opts;
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
const visitorIdParam = this.shouldAppendVisitorId(eventType)
|
|
19
|
+
? await this.getVisitorIdParam()
|
|
20
|
+
: '';
|
|
21
|
+
const defaultOptions: IAnalyticsRequestOptions = {
|
|
22
|
+
url: `${baseUrl}/analytics/${eventType}${visitorIdParam}`,
|
|
23
|
+
credentials: 'include',
|
|
24
|
+
mode: 'cors',
|
|
25
|
+
headers: this.getHeaders(),
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: JSON.stringify(payload),
|
|
28
|
+
};
|
|
29
|
+
const {url, ...fetchData}: IAnalyticsRequestOptions = {
|
|
30
|
+
...defaultOptions,
|
|
31
|
+
...(preprocessRequest ? await preprocessRequest(defaultOptions, 'analyticsFetch') : {}),
|
|
32
|
+
};
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
let response: Response;
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
try {
|
|
37
|
+
response = await fetch(url, fetchData);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('An error has occurred when sending the event.', error);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
if (response.ok) {
|
|
44
|
+
const visit = (await response.json()) as AnyEventResponse;
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
if (visit.visitorId) {
|
|
47
|
+
visitorIdProvider.setCurrentVisitorId(visit.visitorId);
|
|
48
|
+
}
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
return visit;
|
|
51
|
+
} else {
|
|
52
|
+
try {
|
|
53
|
+
response.json();
|
|
54
|
+
} catch {
|
|
55
|
+
/* If you don't parse the response, it won't appear in the network tab. */
|
|
56
|
+
}
|
|
57
|
+
console.error(
|
|
58
|
+
`An error has occurred when sending the "${eventType}" event.`,
|
|
59
|
+
response,
|
|
60
|
+
payload
|
|
61
|
+
);
|
|
62
|
+
throw new Error(
|
|
63
|
+
`An error has occurred when sending the "${eventType}" event. Check the console logs for more details.`
|
|
64
|
+
);
|
|
53
65
|
}
|
|
66
|
+
}
|
|
54
67
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
public async deleteHttpCookieVisitorId() {
|
|
69
|
+
const {baseUrl} = this.opts;
|
|
70
|
+
const url = `${baseUrl}/analytics/visit`;
|
|
71
|
+
await fetch(url, {headers: this.getHeaders(), method: 'DELETE'});
|
|
72
|
+
}
|
|
60
73
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
private shouldAppendVisitorId(eventType: EventType) {
|
|
75
|
+
return (
|
|
76
|
+
[EventType.click, EventType.custom, EventType.search, EventType.view].indexOf(eventType) !==
|
|
77
|
+
-1
|
|
78
|
+
);
|
|
79
|
+
}
|
|
64
80
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
private async getVisitorIdParam() {
|
|
82
|
+
const {visitorIdProvider} = this.opts;
|
|
83
|
+
const visitorId = await visitorIdProvider.getCurrentVisitorId();
|
|
84
|
+
return visitorId ? `?visitor=${visitorId}` : '';
|
|
85
|
+
}
|
|
70
86
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
private getHeaders(): Record<string, string> {
|
|
88
|
+
const {token} = this.opts;
|
|
89
|
+
return {
|
|
90
|
+
...(token ? {Authorization: `Bearer ${token}`} : {}),
|
|
91
|
+
'Content-Type': `application/json`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
78
94
|
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
import {AnyEventResponse, EventType, IRequestPayload} from '../events';
|
|
2
2
|
|
|
3
3
|
export interface VisitorIdProvider {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
getCurrentVisitorId: () => Promise<string>;
|
|
5
|
+
setCurrentVisitorId: (visitorId: string) => void;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export interface AnalyticsRequestClient {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
sendEvent(eventType: string, payload: IRequestPayload): Promise<AnyEventResponse | void>;
|
|
10
|
+
deleteHttpCookieVisitorId: () => Promise<void>;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface IAnalyticsClientOptions {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
token?: string;
|
|
16
|
+
visitorIdProvider: VisitorIdProvider;
|
|
17
|
+
preprocessRequest?: PreprocessAnalyticsRequest;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export type AnalyticsClientOrigin = 'analyticsFetch' | 'analyticsBeacon';
|
|
21
21
|
|
|
22
22
|
export type PreprocessAnalyticsRequest = (
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
request: IAnalyticsRequestOptions,
|
|
24
|
+
clientOrigin: AnalyticsClientOrigin
|
|
25
25
|
) => IAnalyticsRequestOptions | Promise<IAnalyticsRequestOptions>;
|
|
26
26
|
|
|
27
27
|
export interface IAnalyticsRequestOptions extends RequestInit {
|
|
28
|
-
|
|
28
|
+
url: string;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export class NoopAnalyticsClient implements AnalyticsRequestClient {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
public async sendEvent(_: EventType, __: IRequestPayload): Promise<void> {
|
|
33
|
+
return Promise.resolve();
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
public async deleteHttpCookieVisitorId() {
|
|
37
|
+
return Promise.resolve();
|
|
38
|
+
}
|
|
39
39
|
}
|
package/src/client/location.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export const getFormattedLocation = (location: Location) =>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
`${location.protocol}//${location.hostname}${
|
|
3
|
+
location.pathname.indexOf('/') === 0 ? location.pathname : `/${location.pathname}`
|
|
4
|
+
}${location.search}`;
|
|
@@ -1,71 +1,80 @@
|
|
|
1
|
-
import {isServiceKey, serviceActionsKeysMapping} from './measurementProtocolMapping/serviceMeasurementProtocolMapper';
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
isServiceKey,
|
|
3
|
+
serviceActionsKeysMapping,
|
|
4
|
+
} from './measurementProtocolMapping/serviceMeasurementProtocolMapper';
|
|
5
|
+
import {
|
|
6
|
+
commerceActionKeysMappingPerAction,
|
|
7
|
+
isCommerceKey,
|
|
8
|
+
isCustomCommerceKey,
|
|
6
9
|
} from './measurementProtocolMapping/commerceMeasurementProtocolMapper';
|
|
7
10
|
import {keysOf} from './utils';
|
|
8
11
|
import {baseMeasurementProtocolKeysMapping} from './measurementProtocolMapping/baseMeasurementProtocolMapper';
|
|
9
12
|
|
|
10
13
|
const measurementProtocolKeysMapping: {[name: string]: string} = {
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
...baseMeasurementProtocolKeysMapping,
|
|
15
|
+
...serviceActionsKeysMapping,
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
export const convertKeysToMeasurementProtocol = (params: any) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
19
|
+
const keysMappingForAction =
|
|
20
|
+
(!!params.action && commerceActionKeysMappingPerAction[params.action]) || {};
|
|
21
|
+
return keysOf(params).reduce((mappedKeys, key) => {
|
|
22
|
+
const newKey = keysMappingForAction[key] || measurementProtocolKeysMapping[key] || key;
|
|
23
|
+
return {
|
|
24
|
+
...mappedKeys,
|
|
25
|
+
[newKey]: params[key],
|
|
26
|
+
};
|
|
27
|
+
}, {});
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
const measurementProtocolKeysMappingValues = keysOf(measurementProtocolKeysMapping).map(
|
|
27
|
-
|
|
31
|
+
(key) => measurementProtocolKeysMapping[key]
|
|
28
32
|
);
|
|
29
33
|
|
|
30
|
-
const isKnownMeasurementProtocolKey = (key: string) =>
|
|
34
|
+
const isKnownMeasurementProtocolKey = (key: string) =>
|
|
35
|
+
measurementProtocolKeysMappingValues.indexOf(key) !== -1;
|
|
31
36
|
const isCustomKey = (key: string) => key === 'custom';
|
|
32
37
|
|
|
33
38
|
export const isMeasurementProtocolKey = (key: string): boolean => {
|
|
34
|
-
|
|
39
|
+
return [...isCommerceKey, ...isServiceKey, isKnownMeasurementProtocolKey, isCustomKey].some(
|
|
40
|
+
(test) => test(key)
|
|
41
|
+
);
|
|
35
42
|
};
|
|
36
43
|
|
|
37
|
-
export const convertCustomMeasurementProtocolKeys = (data: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
export const convertCustomMeasurementProtocolKeys = (data: {
|
|
45
|
+
[name: string]: string | {[name: string]: string};
|
|
46
|
+
}) => {
|
|
47
|
+
return keysOf(data).reduce((all, current) => {
|
|
48
|
+
const match = getFirstCustomMeasurementProtocolKeyMatch(current);
|
|
49
|
+
if (match) {
|
|
50
|
+
return {
|
|
51
|
+
...all,
|
|
52
|
+
...convertCustomObject(match, data[current] as {[name: string]: string}),
|
|
53
|
+
};
|
|
54
|
+
} else {
|
|
55
|
+
return {
|
|
56
|
+
...all,
|
|
57
|
+
[current]: data[current],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}, {});
|
|
52
61
|
};
|
|
53
62
|
|
|
54
63
|
const getFirstCustomMeasurementProtocolKeyMatch = (key: string): string | undefined => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
let matchedKey: string | undefined = undefined;
|
|
65
|
+
[...isCustomCommerceKey].every((regex) => {
|
|
66
|
+
matchedKey = regex.exec(key)?.[1];
|
|
67
|
+
return !matchedKey;
|
|
68
|
+
});
|
|
69
|
+
return matchedKey;
|
|
61
70
|
};
|
|
62
71
|
|
|
63
72
|
const convertCustomObject = (prefix: string, customData: {[name: string]: string}) => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
return keysOf(customData).reduce(
|
|
74
|
+
(allCustom, currentCustomKey) => ({
|
|
75
|
+
...allCustom,
|
|
76
|
+
[`${prefix}${currentCustomKey}`]: customData[currentCustomKey],
|
|
77
|
+
}),
|
|
78
|
+
{}
|
|
79
|
+
);
|
|
71
80
|
};
|
|
@@ -1,61 +1,65 @@
|
|
|
1
1
|
import {BasePlugin} from '../../plugins/BasePlugin';
|
|
2
2
|
|
|
3
|
-
type DefaultContextInformation = ReturnType<
|
|
4
|
-
|
|
3
|
+
type DefaultContextInformation = ReturnType<
|
|
4
|
+
typeof BasePlugin.prototype.getDefaultContextInformation
|
|
5
|
+
> &
|
|
6
|
+
ReturnType<typeof BasePlugin.prototype.getLocationInformation>;
|
|
5
7
|
|
|
6
8
|
const globalParamKeysMapping: {[name: string]: string} = {
|
|
7
|
-
|
|
9
|
+
anonymizeIp: 'aip',
|
|
8
10
|
};
|
|
9
11
|
|
|
10
12
|
const eventKeysMapping: {[name: string]: string} = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
eventCategory: 'ec',
|
|
14
|
+
eventAction: 'ea',
|
|
15
|
+
eventLabel: 'el',
|
|
16
|
+
eventValue: 'ev',
|
|
17
|
+
page: 'dp',
|
|
18
|
+
visitorId: 'cid',
|
|
19
|
+
clientId: 'cid',
|
|
20
|
+
userId: 'uid',
|
|
21
|
+
currencyCode: 'cu',
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
const contextInformationMapping: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
const contextInformationMapping: {
|
|
25
|
+
[key in keyof DefaultContextInformation]: string;
|
|
26
|
+
} = {
|
|
27
|
+
hitType: 't',
|
|
28
|
+
pageViewId: 'pid',
|
|
29
|
+
encoding: 'de',
|
|
30
|
+
location: 'dl',
|
|
31
|
+
referrer: 'dr',
|
|
32
|
+
screenColor: 'sd',
|
|
33
|
+
screenResolution: 'sr',
|
|
34
|
+
title: 'dt',
|
|
35
|
+
userAgent: 'ua',
|
|
36
|
+
language: 'ul',
|
|
37
|
+
eventId: 'z',
|
|
38
|
+
time: 'tm',
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
/* Those are extension keys that are supported by the Coveo collect protocol (but not Google's protocol). They will be forwarded as-is. */
|
|
38
42
|
const coveoExtensionsKeys = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
'contentId',
|
|
44
|
+
'contentIdKey',
|
|
45
|
+
'contentType',
|
|
46
|
+
'searchHub',
|
|
47
|
+
'tab',
|
|
48
|
+
'searchUid',
|
|
49
|
+
'permanentId',
|
|
50
|
+
'contentLocale',
|
|
51
|
+
'trackingId',
|
|
48
52
|
];
|
|
49
53
|
|
|
50
54
|
export const baseMeasurementProtocolKeysMapping: {[name: string]: string} = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
...globalParamKeysMapping,
|
|
56
|
+
...eventKeysMapping,
|
|
57
|
+
...contextInformationMapping,
|
|
58
|
+
...coveoExtensionsKeys.reduce(
|
|
59
|
+
(all, key) => ({
|
|
60
|
+
...all,
|
|
61
|
+
[key]: key,
|
|
62
|
+
}),
|
|
63
|
+
{}
|
|
64
|
+
),
|
|
61
65
|
};
|