coveo.analytics 2.23.6 → 2.23.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coveo.analytics",
3
- "version": "2.23.6",
3
+ "version": "2.23.8",
4
4
  "description": "📈 Coveo analytics client (node and browser compatible) ",
5
5
  "main": "dist/library.js",
6
6
  "module": "dist/library.es.js",
@@ -13,6 +13,10 @@ import {
13
13
  VisitResponse,
14
14
  IRequestPayload,
15
15
  VariableArgumentsPayload,
16
+ PreparedClickEventRequest,
17
+ PreparedCustomEventRequest,
18
+ PreparedViewEventRequest,
19
+ PreparedSearchEventRequest,
16
20
  } from '../events';
17
21
  import {IAnalyticsClientOptions, PreprocessAnalyticsRequest, VisitorIdProvider} from './analyticsRequestClient';
18
22
  import {hasWindow, hasDocument} from '../detector';
@@ -58,13 +62,34 @@ export type EventTypeConfig = {
58
62
  usesMeasurementProtocol?: boolean;
59
63
  };
60
64
 
65
+ export interface PreparedEvent<TPreparedRequest, TCompleteRequest, TResponse extends AnyEventResponse>
66
+ extends BufferedRequest {
67
+ log(remainingPayload: Omit<TCompleteRequest, keyof TPreparedRequest>): Promise<TResponse | void>;
68
+ }
69
+
61
70
  export interface AnalyticsClient {
62
71
  getPayload(eventType: string, ...payload: VariableArgumentsPayload): Promise<any>;
63
72
  getParameters(eventType: string, ...payload: VariableArgumentsPayload): Promise<any>;
73
+ makeEvent<TPreparedRequest, TCompleteRequest, TResponse extends AnyEventResponse>(
74
+ eventType: string,
75
+ ...payload: VariableArgumentsPayload
76
+ ): Promise<PreparedEvent<TPreparedRequest, TCompleteRequest, TResponse>>;
64
77
  sendEvent(eventType: string, ...payload: VariableArgumentsPayload): Promise<AnyEventResponse | void>;
78
+ makeSearchEvent(
79
+ request: PreparedSearchEventRequest
80
+ ): Promise<PreparedEvent<PreparedSearchEventRequest, SearchEventRequest, SearchEventResponse>>;
65
81
  sendSearchEvent(request: SearchEventRequest): Promise<SearchEventResponse | void>;
82
+ makeClickEvent(
83
+ request: PreparedClickEventRequest
84
+ ): Promise<PreparedEvent<PreparedClickEventRequest, ClickEventRequest, ClickEventResponse>>;
66
85
  sendClickEvent(request: ClickEventRequest): Promise<ClickEventResponse | void>;
86
+ makeCustomEvent(
87
+ request: PreparedCustomEventRequest
88
+ ): Promise<PreparedEvent<PreparedCustomEventRequest, CustomEventRequest, CustomEventResponse>>;
67
89
  sendCustomEvent(request: CustomEventRequest): Promise<CustomEventResponse | void>;
90
+ makeViewEvent(
91
+ request: PreparedViewEventRequest
92
+ ): Promise<PreparedEvent<PreparedViewEventRequest, ViewEventRequest, ViewEventResponse>>;
68
93
  sendViewEvent(request: ViewEventRequest): Promise<ViewEventResponse | void>;
69
94
  getVisit(): Promise<VisitResponse>;
70
95
  getHealth(): Promise<HealthResponse>;
@@ -285,25 +310,34 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
285
310
  return payloadToSend;
286
311
  }
287
312
 
288
- async sendEvent(
313
+ async makeEvent<TPreparedRequest, TCompleteRequest, TResponse extends AnyEventResponse>(
289
314
  eventType: EventType | string,
290
315
  ...payload: VariableArgumentsPayload
291
- ): Promise<AnyEventResponse | void> {
316
+ ): Promise<PreparedEvent<TPreparedRequest, TCompleteRequest, TResponse>> {
292
317
  const {newEventType: eventTypeToSend = eventType as EventType} = this.eventTypeMapping[eventType] || {};
293
318
 
294
319
  const parametersToSend = await this.resolveParameters(eventType, ...payload);
295
320
  const payloadToSend = await this.resolvePayloadForParameters(eventType, parametersToSend);
296
321
 
297
- this.bufferedRequests.push({
322
+ return {
298
323
  eventType: eventTypeToSend,
299
324
  payload: payloadToSend,
300
- });
301
-
302
- await Promise.all(this.afterSendHooks.map((hook) => hook(eventType, parametersToSend)));
303
-
304
- await this.deferExecution();
325
+ log: async (remainingPayload) => {
326
+ this.bufferedRequests.push(<BufferedRequest>{
327
+ eventType: eventTypeToSend,
328
+ payload: {...payloadToSend, ...remainingPayload},
329
+ });
330
+ await Promise.all(
331
+ this.afterSendHooks.map((hook) => hook(eventType, {...parametersToSend, ...remainingPayload}))
332
+ );
333
+ await this.deferExecution();
334
+ return (await this.sendFromBufferWithFetch()) as TResponse | void;
335
+ },
336
+ };
337
+ }
305
338
 
306
- return await this.sendFromBufferWithFetch();
339
+ async sendEvent(eventType: EventType | string, ...payload: VariableArgumentsPayload) {
340
+ return (await this.makeEvent<any, any, AnyEventResponse>(eventType, ...payload)).log({});
307
341
  }
308
342
 
309
343
  private deferExecution(): Promise<void> {
@@ -328,20 +362,45 @@ export class CoveoAnalyticsClient implements AnalyticsClient, VisitorIdProvider
328
362
  this.runtime.client.deleteHttpCookieVisitorId();
329
363
  }
330
364
 
331
- async sendSearchEvent(request: SearchEventRequest): Promise<SearchEventResponse | void> {
332
- return this.sendEvent(EventType.search, request);
365
+ async makeSearchEvent(request: PreparedSearchEventRequest) {
366
+ return this.makeEvent<PreparedSearchEventRequest, SearchEventRequest, SearchEventResponse>(
367
+ EventType.search,
368
+ request
369
+ );
370
+ }
371
+
372
+ async sendSearchEvent({searchQueryUid, ...preparedRequest}: SearchEventRequest) {
373
+ return (await this.makeSearchEvent(preparedRequest)).log({searchQueryUid});
374
+ }
375
+
376
+ async makeClickEvent(request: PreparedClickEventRequest) {
377
+ return this.makeEvent<PreparedClickEventRequest, ClickEventRequest, ClickEventResponse>(
378
+ EventType.click,
379
+ request
380
+ );
381
+ }
382
+
383
+ async sendClickEvent({searchQueryUid, ...preparedRequest}: ClickEventRequest) {
384
+ return (await this.makeClickEvent(preparedRequest)).log({searchQueryUid});
385
+ }
386
+
387
+ async makeCustomEvent(request: PreparedCustomEventRequest) {
388
+ return this.makeEvent<PreparedCustomEventRequest, CustomEventRequest, CustomEventResponse>(
389
+ EventType.custom,
390
+ request
391
+ );
333
392
  }
334
393
 
335
- async sendClickEvent(request: ClickEventRequest): Promise<ClickEventResponse | void> {
336
- return this.sendEvent(EventType.click, request);
394
+ async sendCustomEvent({lastSearchQueryUid, ...preparedRequest}: CustomEventRequest) {
395
+ return (await this.makeCustomEvent(preparedRequest)).log({lastSearchQueryUid});
337
396
  }
338
397
 
339
- async sendCustomEvent(request: CustomEventRequest): Promise<CustomEventResponse | void> {
340
- return this.sendEvent(EventType.custom, request);
398
+ async makeViewEvent(request: PreparedViewEventRequest) {
399
+ return this.makeEvent<PreparedViewEventRequest, ViewEventRequest, ViewEventResponse>(EventType.view, request);
341
400
  }
342
401
 
343
402
  async sendViewEvent(request: ViewEventRequest): Promise<ViewEventResponse | void> {
344
- return this.sendEvent(EventType.view, request);
403
+ return (await this.makeViewEvent(request)).log({});
345
404
  }
346
405
 
347
406
  async getVisit(): Promise<VisitResponse> {
@@ -1,4 +1,4 @@
1
- import {AnalyticsClient} from './analytics';
1
+ import {AnalyticsClient, PreparedEvent} from './analytics';
2
2
  import {
3
3
  AnyEventResponse,
4
4
  SearchEventResponse,
@@ -7,6 +7,15 @@ import {
7
7
  VisitResponse,
8
8
  HealthResponse,
9
9
  ViewEventResponse,
10
+ EventType,
11
+ PreparedSearchEventRequest,
12
+ SearchEventRequest,
13
+ ClickEventRequest,
14
+ CustomEventRequest,
15
+ PreparedClickEventRequest,
16
+ PreparedCustomEventRequest,
17
+ PreparedViewEventRequest,
18
+ ViewEventRequest,
10
19
  } from '../events';
11
20
  import {NoopRuntime} from './runtimeEnvironment';
12
21
 
@@ -17,18 +26,35 @@ export class NoopAnalytics implements AnalyticsClient {
17
26
  getParameters(): Promise<any> {
18
27
  return Promise.resolve();
19
28
  }
29
+ makeEvent<TPreparedRequest, TCompleteRequest, TResponse extends AnyEventResponse>(
30
+ eventType: EventType | string
31
+ ): Promise<PreparedEvent<TPreparedRequest, TCompleteRequest, TResponse>> {
32
+ return Promise.resolve({eventType: eventType as EventType, payload: null, log: () => Promise.resolve()});
33
+ }
20
34
  sendEvent(): Promise<AnyEventResponse | void> {
21
35
  return Promise.resolve();
22
36
  }
37
+ makeSearchEvent() {
38
+ return this.makeEvent<PreparedSearchEventRequest, SearchEventRequest, SearchEventResponse>(EventType.search);
39
+ }
23
40
  sendSearchEvent(): Promise<SearchEventResponse | void> {
24
41
  return Promise.resolve();
25
42
  }
43
+ makeClickEvent() {
44
+ return this.makeEvent<PreparedClickEventRequest, ClickEventRequest, ClickEventResponse>(EventType.click);
45
+ }
26
46
  sendClickEvent(): Promise<ClickEventResponse | void> {
27
47
  return Promise.resolve();
28
48
  }
49
+ makeCustomEvent() {
50
+ return this.makeEvent<PreparedCustomEventRequest, CustomEventRequest, CustomEventResponse>(EventType.custom);
51
+ }
29
52
  sendCustomEvent(): Promise<CustomEventResponse | void> {
30
53
  return Promise.resolve();
31
54
  }
55
+ makeViewEvent() {
56
+ return this.makeEvent<PreparedViewEventRequest, ViewEventRequest, ViewEventResponse>(EventType.view);
57
+ }
32
58
  sendViewEvent(): Promise<ViewEventResponse | void> {
33
59
  return Promise.resolve();
34
60
  }
package/src/events.ts CHANGED
@@ -68,6 +68,8 @@ export interface SearchEventRequest extends EventBaseRequest {
68
68
  facetState?: FacetStateRequest[];
69
69
  }
70
70
 
71
+ export interface PreparedSearchEventRequest extends Omit<SearchEventRequest, 'searchQueryUid'> {}
72
+
71
73
  export interface DocumentInformation {
72
74
  documentUri: string;
73
75
  documentUriHash: string;
@@ -86,12 +88,16 @@ export interface DocumentInformation {
86
88
 
87
89
  export interface ClickEventRequest extends EventBaseRequest, DocumentInformation {}
88
90
 
91
+ export interface PreparedClickEventRequest extends Omit<ClickEventRequest, 'searchQueryUid'> {}
92
+
89
93
  export interface CustomEventRequest extends EventBaseRequest {
90
94
  eventType: string;
91
95
  eventValue: string;
92
96
  lastSearchQueryUid?: string;
93
97
  }
94
98
 
99
+ export interface PreparedCustomEventRequest extends Omit<CustomEventRequest, 'lastSearchQueryUid'> {}
100
+
95
101
  export interface ViewEventRequest extends EventBaseRequest {
96
102
  location?: string;
97
103
  referrer?: string;
@@ -101,6 +107,8 @@ export interface ViewEventRequest extends EventBaseRequest {
101
107
  contentType?: string;
102
108
  }
103
109
 
110
+ export interface PreparedViewEventRequest extends ViewEventRequest {}
111
+
104
112
  export interface DefaultEventResponse {
105
113
  visitId: string;
106
114
  visitorId: string;
@@ -333,6 +333,25 @@ describe('InsightClient', () => {
333
333
  await client.logDocumentQuickview(fakeDocInfo, fakeDocID);
334
334
  expectMatchDocumentPayload(SearchPageEvents.documentQuickview, fakeDocInfo, expectedMetadata);
335
335
  });
336
+
337
+ it('should send proper payload for #caseAttach', async () => {
338
+ const expectedMetadata = {
339
+ ...fakeDocID,
340
+ documentTitle: fakeDocInfo.documentTitle,
341
+ documentURL: fakeDocInfo.documentUrl,
342
+ resultUriHash: fakeDocInfo.documentUriHash,
343
+ };
344
+ await client.logCaseAttach(fakeDocInfo, fakeDocID);
345
+ expectMatchDocumentPayload(SearchPageEvents.caseAttach, fakeDocInfo, expectedMetadata);
346
+ });
347
+
348
+ it('should send proper payload for #caseDetach', async () => {
349
+ const expectedMetadata = {
350
+ resultUriHash: fakeDocInfo.documentUriHash,
351
+ };
352
+ await client.logCaseDetach(fakeDocInfo.documentUriHash);
353
+ expectMatchCustomEventPayload(SearchPageEvents.caseDetach, expectedMetadata);
354
+ });
336
355
  });
337
356
 
338
357
  describe('when the case metadata is included', () => {
@@ -714,6 +733,31 @@ describe('InsightClient', () => {
714
733
  await client.logDocumentQuickview(fakeDocInfo, fakeDocID, metadata);
715
734
  expectMatchDocumentPayload(SearchPageEvents.documentQuickview, fakeDocInfo, expectedMetadata);
716
735
  });
736
+
737
+ it('should send proper payload for #caseAttach', async () => {
738
+ const metadata = baseCaseMetadata;
739
+
740
+ const expectedMetadata = {
741
+ ...fakeDocID,
742
+ ...expectedBaseCaseMetadata,
743
+ documentTitle: fakeDocInfo.documentTitle,
744
+ documentURL: fakeDocInfo.documentUrl,
745
+ resultUriHash: fakeDocInfo.documentUriHash,
746
+ };
747
+ await client.logCaseAttach(fakeDocInfo, fakeDocID, metadata);
748
+ expectMatchDocumentPayload(SearchPageEvents.caseAttach, fakeDocInfo, expectedMetadata);
749
+ });
750
+
751
+ it('should send proper payload for #caseDetach', async () => {
752
+ const metadata = baseCaseMetadata;
753
+
754
+ const expectedMetadata = {
755
+ ...expectedBaseCaseMetadata,
756
+ resultUriHash: fakeDocInfo.documentUriHash,
757
+ };
758
+ await client.logCaseDetach(fakeDocInfo.documentUriHash, metadata);
759
+ expectMatchCustomEventPayload(SearchPageEvents.caseDetach, expectedMetadata);
760
+ });
717
761
  });
718
762
 
719
763
  it('should enable analytics tracking by default', () => {
@@ -258,6 +258,32 @@ export class CoveoInsightClient {
258
258
  );
259
259
  }
260
260
 
261
+ public logCaseAttach(
262
+ info: PartialDocumentInformation,
263
+ identifier: DocumentIdentifier,
264
+ caseMetadata?: CaseMetadata
265
+ ) {
266
+ const metadata = {
267
+ documentTitle: info.documentTitle,
268
+ documentURL: info.documentUrl,
269
+ resultUriHash: info.documentUriHash,
270
+ };
271
+
272
+ return this.logClickEvent(
273
+ SearchPageEvents.caseAttach,
274
+ info,
275
+ identifier,
276
+ caseMetadata ? {...generateMetadataToSend(caseMetadata, false), ...metadata} : metadata
277
+ );
278
+ }
279
+
280
+ public logCaseDetach(resultUriHash: string, metadata?: CaseMetadata) {
281
+ return this.logCustomEvent(
282
+ SearchPageEvents.caseDetach,
283
+ metadata ? {...generateMetadataToSend(metadata, false), resultUriHash} : {resultUriHash}
284
+ );
285
+ }
286
+
261
287
  public async logCustomEvent(event: SearchPageEvents | InsightEvents, metadata?: Record<string, any>) {
262
288
  const customData = {...this.provider.getBaseMetadata(), ...metadata};
263
289