coveo.analytics 2.19.15 → 2.20.2
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/dist/coveoua.browser.js +1 -1
- package/dist/coveoua.browser.js.map +1 -1
- package/dist/coveoua.js +1 -1
- package/dist/coveoua.js.map +1 -1
- package/dist/definitions/insight/insightClient.d.ts +43 -0
- package/dist/definitions/src/insight/insightClient.d.ts +43 -0
- package/dist/library.es.js +3 -3
- package/dist/library.js +3 -3
- package/package.json +2 -2
- package/src/caseAssist/caseAssistClient.spec.ts +19 -2
- package/src/caseAssist/caseAssistClient.ts +2 -1
- package/src/insight/insightClient.spec.ts +223 -0
- package/src/insight/insightClient.ts +150 -0
- package/src/searchPage/searchPageClient.spec.ts +14 -1
- package/src/searchPage/searchPageClient.ts +3 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AnalyticsClient, ClientOptions } from '../client/analytics';
|
|
2
|
+
import { SearchEventRequest } from '../events';
|
|
3
|
+
import { FacetBaseMeta, FacetMetadata, FacetSortMeta, FacetStateMetadata, QueryErrorMeta, SearchPageEvents } from '../searchPage/searchPageEvents';
|
|
4
|
+
export interface InsightClientProvider {
|
|
5
|
+
getSearchEventRequestPayload: () => Omit<SearchEventRequest, 'actionCause' | 'searchQueryUid'>;
|
|
6
|
+
getSearchUID: () => string;
|
|
7
|
+
getBaseMetadata: () => Record<string, any>;
|
|
8
|
+
getPipeline: () => string;
|
|
9
|
+
getOriginContext?: () => string;
|
|
10
|
+
getOriginLevel1: () => string;
|
|
11
|
+
getOriginLevel2: () => string;
|
|
12
|
+
getOriginLevel3: () => string;
|
|
13
|
+
getLanguage: () => string;
|
|
14
|
+
getIsAnonymous: () => boolean;
|
|
15
|
+
getFacetState?: () => FacetStateMetadata[];
|
|
16
|
+
}
|
|
17
|
+
export interface InsightClientOptions extends ClientOptions {
|
|
18
|
+
enableAnalytics: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class CoveoInsightClient {
|
|
21
|
+
private opts;
|
|
22
|
+
private provider;
|
|
23
|
+
coveoAnalyticsClient: AnalyticsClient;
|
|
24
|
+
constructor(opts: Partial<InsightClientOptions>, provider: InsightClientProvider);
|
|
25
|
+
disable(): void;
|
|
26
|
+
enable(): void;
|
|
27
|
+
logInterfaceLoad(): Promise<void | import("../events").SearchEventResponse>;
|
|
28
|
+
logFetchMoreResults(): Promise<void | import("../events").CustomEventResponse>;
|
|
29
|
+
logFacetSelect(meta: FacetMetadata): Promise<void | import("../events").SearchEventResponse>;
|
|
30
|
+
logFacetDeselect(meta: FacetMetadata): Promise<void | import("../events").SearchEventResponse>;
|
|
31
|
+
logFacetUpdateSort(meta: FacetSortMeta): Promise<void | import("../events").SearchEventResponse>;
|
|
32
|
+
logFacetClearAll(meta: FacetBaseMeta): Promise<void | import("../events").SearchEventResponse>;
|
|
33
|
+
logFacetShowMore(meta: FacetBaseMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
34
|
+
logFacetShowLess(meta: FacetBaseMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
35
|
+
logQueryError(meta: QueryErrorMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
36
|
+
logCustomEvent(event: SearchPageEvents, metadata?: Record<string, any>): Promise<void | import("../events").CustomEventResponse>;
|
|
37
|
+
logSearchEvent(event: SearchPageEvents, metadata?: Record<string, any>): Promise<void | import("../events").SearchEventResponse>;
|
|
38
|
+
private getBaseCustomEventRequest;
|
|
39
|
+
private getBaseSearchEventRequest;
|
|
40
|
+
private getBaseEventRequest;
|
|
41
|
+
private getOrigins;
|
|
42
|
+
private getClientId;
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AnalyticsClient, ClientOptions } from '../client/analytics';
|
|
2
|
+
import { SearchEventRequest } from '../events';
|
|
3
|
+
import { FacetBaseMeta, FacetMetadata, FacetSortMeta, FacetStateMetadata, QueryErrorMeta, SearchPageEvents } from '../searchPage/searchPageEvents';
|
|
4
|
+
export interface InsightClientProvider {
|
|
5
|
+
getSearchEventRequestPayload: () => Omit<SearchEventRequest, 'actionCause' | 'searchQueryUid'>;
|
|
6
|
+
getSearchUID: () => string;
|
|
7
|
+
getBaseMetadata: () => Record<string, any>;
|
|
8
|
+
getPipeline: () => string;
|
|
9
|
+
getOriginContext?: () => string;
|
|
10
|
+
getOriginLevel1: () => string;
|
|
11
|
+
getOriginLevel2: () => string;
|
|
12
|
+
getOriginLevel3: () => string;
|
|
13
|
+
getLanguage: () => string;
|
|
14
|
+
getIsAnonymous: () => boolean;
|
|
15
|
+
getFacetState?: () => FacetStateMetadata[];
|
|
16
|
+
}
|
|
17
|
+
export interface InsightClientOptions extends ClientOptions {
|
|
18
|
+
enableAnalytics: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class CoveoInsightClient {
|
|
21
|
+
private opts;
|
|
22
|
+
private provider;
|
|
23
|
+
coveoAnalyticsClient: AnalyticsClient;
|
|
24
|
+
constructor(opts: Partial<InsightClientOptions>, provider: InsightClientProvider);
|
|
25
|
+
disable(): void;
|
|
26
|
+
enable(): void;
|
|
27
|
+
logInterfaceLoad(): Promise<void | import("../events").SearchEventResponse>;
|
|
28
|
+
logFetchMoreResults(): Promise<void | import("../events").CustomEventResponse>;
|
|
29
|
+
logFacetSelect(meta: FacetMetadata): Promise<void | import("../events").SearchEventResponse>;
|
|
30
|
+
logFacetDeselect(meta: FacetMetadata): Promise<void | import("../events").SearchEventResponse>;
|
|
31
|
+
logFacetUpdateSort(meta: FacetSortMeta): Promise<void | import("../events").SearchEventResponse>;
|
|
32
|
+
logFacetClearAll(meta: FacetBaseMeta): Promise<void | import("../events").SearchEventResponse>;
|
|
33
|
+
logFacetShowMore(meta: FacetBaseMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
34
|
+
logFacetShowLess(meta: FacetBaseMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
35
|
+
logQueryError(meta: QueryErrorMeta): Promise<void | import("../events").CustomEventResponse>;
|
|
36
|
+
logCustomEvent(event: SearchPageEvents, metadata?: Record<string, any>): Promise<void | import("../events").CustomEventResponse>;
|
|
37
|
+
logSearchEvent(event: SearchPageEvents, metadata?: Record<string, any>): Promise<void | import("../events").SearchEventResponse>;
|
|
38
|
+
private getBaseCustomEventRequest;
|
|
39
|
+
private getBaseSearchEventRequest;
|
|
40
|
+
private getBaseEventRequest;
|
|
41
|
+
private getOrigins;
|
|
42
|
+
private getClientId;
|
|
43
|
+
}
|
package/dist/library.es.js
CHANGED
|
@@ -1235,8 +1235,8 @@ class CoveoSearchPageClient {
|
|
|
1235
1235
|
constructor(opts, provider) {
|
|
1236
1236
|
this.opts = opts;
|
|
1237
1237
|
this.provider = provider;
|
|
1238
|
-
|
|
1239
|
-
|
|
1238
|
+
const shouldDisableAnalytics = opts.enableAnalytics === false || doNotTrack();
|
|
1239
|
+
this.coveoAnalyticsClient = shouldDisableAnalytics ? new NoopAnalytics() : new CoveoAnalyticsClient(opts);
|
|
1240
1240
|
}
|
|
1241
1241
|
disable() {
|
|
1242
1242
|
if (this.coveoAnalyticsClient instanceof CoveoAnalyticsClient) {
|
|
@@ -1681,7 +1681,7 @@ class CaseAssistClient {
|
|
|
1681
1681
|
var _a;
|
|
1682
1682
|
this.options = options;
|
|
1683
1683
|
this.provider = provider;
|
|
1684
|
-
const analyticsEnabled = (_a = options.enableAnalytics) !== null && _a !== void 0 ? _a : true;
|
|
1684
|
+
const analyticsEnabled = ((_a = options.enableAnalytics) !== null && _a !== void 0 ? _a : true) && !doNotTrack();
|
|
1685
1685
|
this.coveoAnalyticsClient = analyticsEnabled ? new CoveoAnalyticsClient(options) : new NoopAnalytics();
|
|
1686
1686
|
this.svc = new SVCPlugin({ client: this.coveoAnalyticsClient });
|
|
1687
1687
|
}
|
package/dist/library.js
CHANGED
|
@@ -83678,8 +83678,8 @@ var CoveoSearchPageClient = (function () {
|
|
|
83678
83678
|
function CoveoSearchPageClient(opts, provider) {
|
|
83679
83679
|
this.opts = opts;
|
|
83680
83680
|
this.provider = provider;
|
|
83681
|
-
|
|
83682
|
-
|
|
83681
|
+
var shouldDisableAnalytics = opts.enableAnalytics === false || doNotTrack();
|
|
83682
|
+
this.coveoAnalyticsClient = shouldDisableAnalytics ? new NoopAnalytics() : new CoveoAnalyticsClient(opts);
|
|
83683
83683
|
}
|
|
83684
83684
|
CoveoSearchPageClient.prototype.disable = function () {
|
|
83685
83685
|
if (this.coveoAnalyticsClient instanceof CoveoAnalyticsClient) {
|
|
@@ -84061,7 +84061,7 @@ var CaseAssistClient = (function () {
|
|
|
84061
84061
|
var _a;
|
|
84062
84062
|
this.options = options;
|
|
84063
84063
|
this.provider = provider;
|
|
84064
|
-
var analyticsEnabled = (_a = options.enableAnalytics) !== null && _a !== void 0 ? _a : true;
|
|
84064
|
+
var analyticsEnabled = ((_a = options.enableAnalytics) !== null && _a !== void 0 ? _a : true) && !doNotTrack();
|
|
84065
84065
|
this.coveoAnalyticsClient = analyticsEnabled ? new CoveoAnalyticsClient(options) : new NoopAnalytics();
|
|
84066
84066
|
this.svc = new SVCPlugin({ client: this.coveoAnalyticsClient });
|
|
84067
84067
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coveo.analytics",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.2",
|
|
4
4
|
"description": "📈 Coveo analytics client (node and browser compatible) ",
|
|
5
5
|
"main": "dist/library.js",
|
|
6
6
|
"module": "dist/library.es.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@react-native-async-storage/async-storage": "^1.17.
|
|
26
|
+
"@react-native-async-storage/async-storage": "^1.17.5",
|
|
27
27
|
"cross-fetch": "^3.1.5"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
@@ -6,11 +6,16 @@ import {
|
|
|
6
6
|
DocumentSuggestion,
|
|
7
7
|
FieldSuggestion,
|
|
8
8
|
} from './caseAssistActions';
|
|
9
|
-
|
|
10
9
|
import {mockFetch} from '../../tests/fetchMock';
|
|
11
10
|
import {TicketProperties} from '../plugins/svc';
|
|
12
|
-
|
|
13
11
|
const {fetchMock, fetchMockBeforeEach} = mockFetch();
|
|
12
|
+
import doNotTrack from '../donottrack';
|
|
13
|
+
jest.mock('../donottrack', () => {
|
|
14
|
+
return {
|
|
15
|
+
default: jest.fn(),
|
|
16
|
+
doNotTrack: jest.fn(),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
14
19
|
|
|
15
20
|
describe('CaseAssistClient', () => {
|
|
16
21
|
const defaultSearchHub = 'origin-level-1';
|
|
@@ -151,6 +156,18 @@ describe('CaseAssistClient', () => {
|
|
|
151
156
|
expect(fetchMock.called()).toBe(false);
|
|
152
157
|
});
|
|
153
158
|
|
|
159
|
+
it('should not send events when doNotTrack is enabled', async () => {
|
|
160
|
+
(doNotTrack as jest.Mock).mockImplementationOnce(() => true);
|
|
161
|
+
|
|
162
|
+
client = new CaseAssistClient({});
|
|
163
|
+
|
|
164
|
+
await client.logEnterInterface({
|
|
165
|
+
ticket: emptyTicket,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(fetchMock.called()).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
|
|
154
171
|
it('should not send events after #disable function is called', async () => {
|
|
155
172
|
client.disable();
|
|
156
173
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import CoveoAnalyticsClient, {AnalyticsClient, ClientOptions} from '../client/analytics';
|
|
2
2
|
import {NoopAnalytics} from '../client/noopAnalytics';
|
|
3
|
+
import doNotTrack from '../donottrack';
|
|
3
4
|
import {SVCPlugin} from '../plugins/svc';
|
|
4
5
|
import {
|
|
5
6
|
CaseAssistActions,
|
|
@@ -29,7 +30,7 @@ export class CaseAssistClient {
|
|
|
29
30
|
private svc: SVCPlugin;
|
|
30
31
|
|
|
31
32
|
constructor(private options: Partial<CaseAssistClientOptions>, private provider?: CaseAssistClientProvider) {
|
|
32
|
-
const analyticsEnabled = options.enableAnalytics ?? true;
|
|
33
|
+
const analyticsEnabled = (options.enableAnalytics ?? true) && !doNotTrack();
|
|
33
34
|
|
|
34
35
|
this.coveoAnalyticsClient = analyticsEnabled ? new CoveoAnalyticsClient(options) : new NoopAnalytics();
|
|
35
36
|
this.svc = new SVCPlugin({client: this.coveoAnalyticsClient});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import {mockFetch} from '../../tests/fetchMock';
|
|
2
|
+
import CoveoAnalyticsClient from '../client/analytics';
|
|
3
|
+
import {NoopAnalytics} from '../client/noopAnalytics';
|
|
4
|
+
import {CustomEventsTypes, SearchPageEvents} from '../searchPage/searchPageEvents';
|
|
5
|
+
import {CoveoInsightClient, InsightClientProvider} from './insightClient';
|
|
6
|
+
import doNotTrack from '../donottrack';
|
|
7
|
+
|
|
8
|
+
jest.mock('../donottrack', () => {
|
|
9
|
+
return {
|
|
10
|
+
default: jest.fn(),
|
|
11
|
+
doNotTrack: jest.fn(),
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const {fetchMock, fetchMockBeforeEach} = mockFetch();
|
|
16
|
+
describe('InsightClient', () => {
|
|
17
|
+
const fakeFacetState = [
|
|
18
|
+
{
|
|
19
|
+
valuePosition: 0,
|
|
20
|
+
value: 'foo',
|
|
21
|
+
state: 'selected' as const,
|
|
22
|
+
facetPosition: 1,
|
|
23
|
+
displayValue: 'foobar',
|
|
24
|
+
facetType: 'specific' as const,
|
|
25
|
+
field: '@foo',
|
|
26
|
+
id: 'bar',
|
|
27
|
+
title: 'title',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
let client: CoveoInsightClient;
|
|
32
|
+
|
|
33
|
+
const provider: InsightClientProvider = {
|
|
34
|
+
getBaseMetadata: () => ({foo: 'bar'}),
|
|
35
|
+
getSearchEventRequestPayload: () => ({
|
|
36
|
+
queryText: 'queryText',
|
|
37
|
+
responseTime: 123,
|
|
38
|
+
}),
|
|
39
|
+
getSearchUID: () => 'my-uid',
|
|
40
|
+
getPipeline: () => 'my-pipeline',
|
|
41
|
+
getOriginContext: () => 'origin-context',
|
|
42
|
+
getOriginLevel1: () => 'origin-level-1',
|
|
43
|
+
getOriginLevel2: () => 'origin-level-2',
|
|
44
|
+
getOriginLevel3: () => 'origin-level-3',
|
|
45
|
+
getLanguage: () => 'en',
|
|
46
|
+
getFacetState: () => fakeFacetState,
|
|
47
|
+
getIsAnonymous: () => false,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const initClient = () => {
|
|
51
|
+
return new CoveoInsightClient({}, provider);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const expectOrigins = () => ({
|
|
55
|
+
originContext: 'origin-context',
|
|
56
|
+
originLevel1: 'origin-level-1',
|
|
57
|
+
originLevel2: 'origin-level-2',
|
|
58
|
+
originLevel3: 'origin-level-3',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const expectMatchPayload = (actionCause: SearchPageEvents, meta = {}) => {
|
|
62
|
+
const [, {body}] = fetchMock.lastCall();
|
|
63
|
+
const customData = {foo: 'bar', ...meta};
|
|
64
|
+
expect(JSON.parse(body.toString())).toMatchObject({
|
|
65
|
+
queryText: 'queryText',
|
|
66
|
+
responseTime: 123,
|
|
67
|
+
queryPipeline: 'my-pipeline',
|
|
68
|
+
actionCause,
|
|
69
|
+
customData,
|
|
70
|
+
facetState: fakeFacetState,
|
|
71
|
+
language: 'en',
|
|
72
|
+
clientId: 'visitor-id',
|
|
73
|
+
...expectOrigins(),
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const expectMatchCustomEventPayload = (actionCause: SearchPageEvents, meta = {}) => {
|
|
78
|
+
const [, {body}] = fetchMock.lastCall();
|
|
79
|
+
const customData = {foo: 'bar', ...meta};
|
|
80
|
+
expect(JSON.parse(body.toString())).toMatchObject({
|
|
81
|
+
eventValue: actionCause,
|
|
82
|
+
eventType: CustomEventsTypes[actionCause],
|
|
83
|
+
lastSearchQueryUid: 'my-uid',
|
|
84
|
+
customData,
|
|
85
|
+
language: 'en',
|
|
86
|
+
clientId: 'visitor-id',
|
|
87
|
+
...expectOrigins(),
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
beforeEach(() => {
|
|
92
|
+
fetchMockBeforeEach();
|
|
93
|
+
|
|
94
|
+
client = initClient();
|
|
95
|
+
client.coveoAnalyticsClient.runtime.storage.setItem('visitorId', 'visitor-id');
|
|
96
|
+
fetchMock.mock(/.*/, {
|
|
97
|
+
visitId: 'visit-id',
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
afterEach(() => {
|
|
102
|
+
fetchMock.reset();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should send proper payload for #interfaceLoad', async () => {
|
|
106
|
+
await client.logInterfaceLoad();
|
|
107
|
+
expectMatchPayload(SearchPageEvents.interfaceLoad);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should send proper payload for #fetchMoreResults', async () => {
|
|
111
|
+
await client.logFetchMoreResults();
|
|
112
|
+
expectMatchCustomEventPayload(SearchPageEvents.pagerScrolling, {type: 'getMoreResults'});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should send proper payload for #logFacetSelect', async () => {
|
|
116
|
+
const meta = {
|
|
117
|
+
facetField: '@foo',
|
|
118
|
+
facetId: 'bar',
|
|
119
|
+
facetTitle: 'title',
|
|
120
|
+
facetValue: 'qwerty',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
await client.logFacetSelect(meta);
|
|
124
|
+
expectMatchPayload(SearchPageEvents.facetSelect, meta);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should send proper payload for #logFacetDeselect', async () => {
|
|
128
|
+
const meta = {
|
|
129
|
+
facetField: '@foo',
|
|
130
|
+
facetId: 'bar',
|
|
131
|
+
facetTitle: 'title',
|
|
132
|
+
facetValue: 'qwerty',
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
await client.logFacetDeselect(meta);
|
|
136
|
+
expectMatchPayload(SearchPageEvents.facetDeselect, meta);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should send proper payload for #logFacetUpdateSort', async () => {
|
|
140
|
+
const meta = {
|
|
141
|
+
facetField: '@foo',
|
|
142
|
+
facetId: 'bar',
|
|
143
|
+
facetTitle: 'title',
|
|
144
|
+
criteria: 'bazz',
|
|
145
|
+
};
|
|
146
|
+
await client.logFacetUpdateSort(meta);
|
|
147
|
+
expectMatchPayload(SearchPageEvents.facetUpdateSort, meta);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should send proper payload for #logFacetClearAll', async () => {
|
|
151
|
+
const meta = {
|
|
152
|
+
facetField: '@foo',
|
|
153
|
+
facetId: 'bar',
|
|
154
|
+
facetTitle: 'title',
|
|
155
|
+
};
|
|
156
|
+
await client.logFacetClearAll(meta);
|
|
157
|
+
expectMatchPayload(SearchPageEvents.facetClearAll, meta);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should send proper payload for #logFacetShowMore', async () => {
|
|
161
|
+
const meta = {
|
|
162
|
+
facetField: '@foo',
|
|
163
|
+
facetId: 'bar',
|
|
164
|
+
facetTitle: 'title',
|
|
165
|
+
};
|
|
166
|
+
await client.logFacetShowMore(meta);
|
|
167
|
+
expectMatchCustomEventPayload(SearchPageEvents.facetShowMore, meta);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should send proper payload for #logFacetShowLess', async () => {
|
|
171
|
+
const meta = {
|
|
172
|
+
facetField: '@foo',
|
|
173
|
+
facetId: 'bar',
|
|
174
|
+
facetTitle: 'title',
|
|
175
|
+
};
|
|
176
|
+
await client.logFacetShowLess(meta);
|
|
177
|
+
expectMatchCustomEventPayload(SearchPageEvents.facetShowLess, meta);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should send proper payload for #logQueryError', async () => {
|
|
181
|
+
const meta = {
|
|
182
|
+
query: 'q',
|
|
183
|
+
aq: 'aq',
|
|
184
|
+
cq: 'cq',
|
|
185
|
+
dq: 'dq',
|
|
186
|
+
errorMessage: 'boom',
|
|
187
|
+
errorType: 'a bad one',
|
|
188
|
+
};
|
|
189
|
+
await client.logQueryError(meta);
|
|
190
|
+
expectMatchCustomEventPayload(SearchPageEvents.queryError, meta);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should enable analytics tracking by default', () => {
|
|
194
|
+
const c = new CoveoInsightClient({}, provider);
|
|
195
|
+
expect(c.coveoAnalyticsClient instanceof CoveoAnalyticsClient).toBe(true);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should allow disabling analytics on initialization', () => {
|
|
199
|
+
const c = new CoveoInsightClient({enableAnalytics: false}, provider);
|
|
200
|
+
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should allow disabling analytics after initialization', () => {
|
|
204
|
+
const c = new CoveoInsightClient({enableAnalytics: true}, provider);
|
|
205
|
+
expect(c.coveoAnalyticsClient instanceof CoveoAnalyticsClient).toBe(true);
|
|
206
|
+
c.disable();
|
|
207
|
+
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should disable analytics when doNotTrack is enabled', async () => {
|
|
211
|
+
(doNotTrack as jest.Mock).mockImplementationOnce(() => true);
|
|
212
|
+
|
|
213
|
+
const c = new CoveoInsightClient({}, provider);
|
|
214
|
+
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should allow enabling analytics after initialization', () => {
|
|
218
|
+
const c = new CoveoInsightClient({enableAnalytics: false}, provider);
|
|
219
|
+
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
220
|
+
c.enable();
|
|
221
|
+
expect(c.coveoAnalyticsClient instanceof CoveoAnalyticsClient).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import CoveoAnalyticsClient, {AnalyticsClient, ClientOptions} from '../client/analytics';
|
|
2
|
+
import {NoopAnalytics} from '../client/noopAnalytics';
|
|
3
|
+
import doNotTrack from '../donottrack';
|
|
4
|
+
import {CustomEventRequest, SearchEventRequest} from '../events';
|
|
5
|
+
import {
|
|
6
|
+
CustomEventsTypes,
|
|
7
|
+
FacetBaseMeta,
|
|
8
|
+
FacetMetadata,
|
|
9
|
+
FacetSortMeta,
|
|
10
|
+
FacetStateMetadata,
|
|
11
|
+
QueryErrorMeta,
|
|
12
|
+
SearchPageEvents,
|
|
13
|
+
} from '../searchPage/searchPageEvents';
|
|
14
|
+
|
|
15
|
+
export interface InsightClientProvider {
|
|
16
|
+
getSearchEventRequestPayload: () => Omit<SearchEventRequest, 'actionCause' | 'searchQueryUid'>;
|
|
17
|
+
getSearchUID: () => string;
|
|
18
|
+
getBaseMetadata: () => Record<string, any>;
|
|
19
|
+
getPipeline: () => string;
|
|
20
|
+
getOriginContext?: () => string;
|
|
21
|
+
getOriginLevel1: () => string;
|
|
22
|
+
getOriginLevel2: () => string;
|
|
23
|
+
getOriginLevel3: () => string;
|
|
24
|
+
getLanguage: () => string;
|
|
25
|
+
getIsAnonymous: () => boolean;
|
|
26
|
+
getFacetState?: () => FacetStateMetadata[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface InsightClientOptions extends ClientOptions {
|
|
30
|
+
enableAnalytics: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class CoveoInsightClient {
|
|
34
|
+
public coveoAnalyticsClient: AnalyticsClient;
|
|
35
|
+
|
|
36
|
+
constructor(private opts: Partial<InsightClientOptions>, private provider: InsightClientProvider) {
|
|
37
|
+
const shouldDisableAnalytics = opts.enableAnalytics === false || doNotTrack();
|
|
38
|
+
this.coveoAnalyticsClient = shouldDisableAnalytics ? new NoopAnalytics() : new CoveoAnalyticsClient(opts);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public disable() {
|
|
42
|
+
if (this.coveoAnalyticsClient instanceof CoveoAnalyticsClient) {
|
|
43
|
+
this.coveoAnalyticsClient.clear();
|
|
44
|
+
}
|
|
45
|
+
this.coveoAnalyticsClient = new NoopAnalytics();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public enable() {
|
|
49
|
+
this.coveoAnalyticsClient = new CoveoAnalyticsClient(this.opts);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public logInterfaceLoad() {
|
|
53
|
+
return this.logSearchEvent(SearchPageEvents.interfaceLoad);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public logFetchMoreResults() {
|
|
57
|
+
return this.logCustomEvent(SearchPageEvents.pagerScrolling, {type: 'getMoreResults'});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public logFacetSelect(meta: FacetMetadata) {
|
|
61
|
+
return this.logSearchEvent(SearchPageEvents.facetSelect, meta);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public logFacetDeselect(meta: FacetMetadata) {
|
|
65
|
+
return this.logSearchEvent(SearchPageEvents.facetDeselect, meta);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public logFacetUpdateSort(meta: FacetSortMeta) {
|
|
69
|
+
return this.logSearchEvent(SearchPageEvents.facetUpdateSort, meta);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public logFacetClearAll(meta: FacetBaseMeta) {
|
|
73
|
+
return this.logSearchEvent(SearchPageEvents.facetClearAll, meta);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public logFacetShowMore(meta: FacetBaseMeta) {
|
|
77
|
+
return this.logCustomEvent(SearchPageEvents.facetShowMore, meta);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public logFacetShowLess(meta: FacetBaseMeta) {
|
|
81
|
+
return this.logCustomEvent(SearchPageEvents.facetShowLess, meta);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public logQueryError(meta: QueryErrorMeta) {
|
|
85
|
+
return this.logCustomEvent(SearchPageEvents.queryError, meta);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public async logCustomEvent(event: SearchPageEvents, metadata?: Record<string, any>) {
|
|
89
|
+
const customData = {...this.provider.getBaseMetadata(), ...metadata};
|
|
90
|
+
|
|
91
|
+
const payload: CustomEventRequest = {
|
|
92
|
+
...(await this.getBaseCustomEventRequest(customData)),
|
|
93
|
+
eventType: CustomEventsTypes[event]!,
|
|
94
|
+
eventValue: event,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return this.coveoAnalyticsClient.sendCustomEvent(payload);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public async logSearchEvent(event: SearchPageEvents, metadata?: Record<string, any>) {
|
|
101
|
+
return this.coveoAnalyticsClient.sendSearchEvent(await this.getBaseSearchEventRequest(event, metadata));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private async getBaseCustomEventRequest(metadata?: Record<string, any>) {
|
|
105
|
+
return {
|
|
106
|
+
...(await this.getBaseEventRequest(metadata)),
|
|
107
|
+
lastSearchQueryUid: this.provider.getSearchUID(),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async getBaseSearchEventRequest(
|
|
112
|
+
event: SearchPageEvents,
|
|
113
|
+
metadata?: Record<string, any>
|
|
114
|
+
): Promise<SearchEventRequest> {
|
|
115
|
+
return {
|
|
116
|
+
...(await this.getBaseEventRequest(metadata)),
|
|
117
|
+
...this.provider.getSearchEventRequestPayload(),
|
|
118
|
+
searchQueryUid: this.provider.getSearchUID(),
|
|
119
|
+
queryPipeline: this.provider.getPipeline(),
|
|
120
|
+
actionCause: event,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async getBaseEventRequest(metadata?: Record<string, any>) {
|
|
125
|
+
const customData = {...this.provider.getBaseMetadata(), ...metadata};
|
|
126
|
+
return {
|
|
127
|
+
...this.getOrigins(),
|
|
128
|
+
customData,
|
|
129
|
+
language: this.provider.getLanguage(),
|
|
130
|
+
facetState: this.provider.getFacetState ? this.provider.getFacetState() : [],
|
|
131
|
+
anonymous: this.provider.getIsAnonymous(),
|
|
132
|
+
clientId: await this.getClientId(),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private getOrigins() {
|
|
137
|
+
return {
|
|
138
|
+
originContext: this.provider.getOriginContext?.(),
|
|
139
|
+
originLevel1: this.provider.getOriginLevel1(),
|
|
140
|
+
originLevel2: this.provider.getOriginLevel2(),
|
|
141
|
+
originLevel3: this.provider.getOriginLevel3(),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private getClientId() {
|
|
146
|
+
return this.coveoAnalyticsClient instanceof CoveoAnalyticsClient
|
|
147
|
+
? this.coveoAnalyticsClient.getCurrentVisitorId()
|
|
148
|
+
: undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -10,7 +10,13 @@ import {
|
|
|
10
10
|
import CoveoAnalyticsClient from '../client/analytics';
|
|
11
11
|
import {NoopAnalytics} from '../client/noopAnalytics';
|
|
12
12
|
import {mockFetch} from '../../tests/fetchMock';
|
|
13
|
-
|
|
13
|
+
import doNotTrack from '../donottrack';
|
|
14
|
+
jest.mock('../donottrack', () => {
|
|
15
|
+
return {
|
|
16
|
+
default: jest.fn(),
|
|
17
|
+
doNotTrack: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
});
|
|
14
20
|
const {fetchMock, fetchMockBeforeEach} = mockFetch();
|
|
15
21
|
|
|
16
22
|
describe('SearchPageClient', () => {
|
|
@@ -651,6 +657,13 @@ describe('SearchPageClient', () => {
|
|
|
651
657
|
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
652
658
|
});
|
|
653
659
|
|
|
660
|
+
it('should disable analytics when doNotTrack is enabled', async () => {
|
|
661
|
+
(doNotTrack as jest.Mock).mockImplementationOnce(() => true);
|
|
662
|
+
|
|
663
|
+
const c = new CoveoSearchPageClient({}, provider);
|
|
664
|
+
expect(c.coveoAnalyticsClient instanceof NoopAnalytics).toBe(true);
|
|
665
|
+
});
|
|
666
|
+
|
|
654
667
|
it('should allow disabling analytics after initialization', () => {
|
|
655
668
|
const c = new CoveoSearchPageClient({enableAnalytics: true}, provider);
|
|
656
669
|
expect(c.coveoAnalyticsClient instanceof CoveoAnalyticsClient).toBe(true);
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from './searchPageEvents';
|
|
29
29
|
import {NoopAnalytics} from '../client/noopAnalytics';
|
|
30
30
|
import {formatOmniboxMetadata} from '../formatting/format-omnibox-metadata';
|
|
31
|
+
import doNotTrack from '../donottrack';
|
|
31
32
|
|
|
32
33
|
export interface SearchPageClientProvider {
|
|
33
34
|
getBaseMetadata: () => Record<string, any>;
|
|
@@ -51,8 +52,8 @@ export class CoveoSearchPageClient {
|
|
|
51
52
|
public coveoAnalyticsClient: AnalyticsClient;
|
|
52
53
|
|
|
53
54
|
constructor(private opts: Partial<SearchPageClientOptions>, private provider: SearchPageClientProvider) {
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const shouldDisableAnalytics = opts.enableAnalytics === false || doNotTrack();
|
|
56
|
+
this.coveoAnalyticsClient = shouldDisableAnalytics ? new NoopAnalytics() : new CoveoAnalyticsClient(opts);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
public disable() {
|