coveo.analytics 2.28.14 → 2.28.16

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.
@@ -3,9 +3,10 @@ import { EventType, IRequestPayload } from '../events';
3
3
  export declare class AnalyticsBeaconClient implements AnalyticsRequestClient {
4
4
  private opts;
5
5
  constructor(opts: IAnalyticsClientOptions);
6
- sendEvent(eventType: EventType, payload: IRequestPayload): Promise<void>;
6
+ sendEvent(eventType: EventType, originalPayload: IRequestPayload): Promise<void>;
7
7
  isAvailable(): boolean;
8
8
  deleteHttpCookieVisitorId(): Promise<void>;
9
+ private preProcessRequestAsPotentialJSONString;
9
10
  private encodeForEventType;
10
11
  private getQueryParamsForEventType;
11
12
  private isEventTypeLegacy;
@@ -1 +1 @@
1
- export declare const libVersion = "2.28.14";
1
+ export declare const libVersion = "2.28.16";
@@ -731,7 +731,7 @@ function sha1(bytes) {
731
731
  const v5 = v35('v5', 0x50, sha1);
732
732
  var uuidv5 = v5;
733
733
 
734
- var libVersion = "2.28.14" ;
734
+ var libVersion = "2.28.16" ;
735
735
 
736
736
  var getFormattedLocation = function (location) {
737
737
  return "".concat(location.protocol, "//").concat(location.hostname).concat(location.pathname.indexOf('/') === 0 ? location.pathname : "/".concat(location.pathname)).concat(location.search);
@@ -1205,37 +1205,26 @@ var AnalyticsBeaconClient = (function () {
1205
1205
  function AnalyticsBeaconClient(opts) {
1206
1206
  this.opts = opts;
1207
1207
  }
1208
- AnalyticsBeaconClient.prototype.sendEvent = function (eventType, payload) {
1208
+ AnalyticsBeaconClient.prototype.sendEvent = function (eventType, originalPayload) {
1209
1209
  return __awaiter(this, void 0, void 0, function () {
1210
- var _a, baseUrl, preprocessRequest, parsedRequestData, paramsFragments, defaultOptions, _b, url, body, _c, _d;
1211
- return __generator(this, function (_e) {
1212
- switch (_e.label) {
1210
+ var _a, baseUrl, preprocessRequest, paramsFragments, _b, url, payload, parsedRequestData, body;
1211
+ return __generator(this, function (_c) {
1212
+ switch (_c.label) {
1213
1213
  case 0:
1214
1214
  if (!this.isAvailable()) {
1215
1215
  throw new Error("navigator.sendBeacon is not supported in this browser. Consider adding a polyfill like \"sendbeacon-polyfill\".");
1216
1216
  }
1217
1217
  _a = this.opts, baseUrl = _a.baseUrl, preprocessRequest = _a.preprocessRequest;
1218
- parsedRequestData = this.encodeForEventType(eventType, payload);
1219
1218
  return [4, this.getQueryParamsForEventType(eventType)];
1220
1219
  case 1:
1221
- paramsFragments = _e.sent();
1222
- defaultOptions = {
1223
- url: "".concat(baseUrl, "/analytics/").concat(eventType, "?").concat(paramsFragments),
1224
- body: new Blob([parsedRequestData], {
1225
- type: 'application/x-www-form-urlencoded',
1226
- }),
1227
- };
1228
- _c = [__assign({}, defaultOptions)];
1229
- if (!preprocessRequest) return [3, 3];
1230
- return [4, preprocessRequest(defaultOptions, 'analyticsBeacon')];
1220
+ paramsFragments = _c.sent();
1221
+ return [4, this.preProcessRequestAsPotentialJSONString("".concat(baseUrl, "/analytics/").concat(eventType, "?").concat(paramsFragments), originalPayload, preprocessRequest)];
1231
1222
  case 2:
1232
- _d = _e.sent();
1233
- return [3, 4];
1234
- case 3:
1235
- _d = {};
1236
- _e.label = 4;
1237
- case 4:
1238
- _b = __assign.apply(void 0, _c.concat([(_d)])), url = _b.url, body = _b.body;
1223
+ _b = _c.sent(), url = _b.url, payload = _b.payload;
1224
+ parsedRequestData = this.encodeForEventType(eventType, payload);
1225
+ body = new Blob([parsedRequestData], {
1226
+ type: 'application/x-www-form-urlencoded',
1227
+ });
1239
1228
  navigator.sendBeacon(url, body);
1240
1229
  return [2];
1241
1230
  }
@@ -1248,6 +1237,35 @@ var AnalyticsBeaconClient = (function () {
1248
1237
  AnalyticsBeaconClient.prototype.deleteHttpCookieVisitorId = function () {
1249
1238
  return Promise.resolve();
1250
1239
  };
1240
+ AnalyticsBeaconClient.prototype.preProcessRequestAsPotentialJSONString = function (originalURL, originalPayload, preprocessRequest) {
1241
+ return __awaiter(this, void 0, void 0, function () {
1242
+ var returnedUrl, returnedPayload, processedRequest, processedURL, processedBody;
1243
+ return __generator(this, function (_a) {
1244
+ switch (_a.label) {
1245
+ case 0:
1246
+ returnedUrl = originalURL;
1247
+ returnedPayload = originalPayload;
1248
+ if (!preprocessRequest) return [3, 2];
1249
+ return [4, preprocessRequest({ url: originalURL, body: JSON.stringify(originalPayload) }, 'analyticsBeacon')];
1250
+ case 1:
1251
+ processedRequest = _a.sent();
1252
+ processedURL = processedRequest.url, processedBody = processedRequest.body;
1253
+ returnedUrl = processedURL || originalURL;
1254
+ try {
1255
+ returnedPayload = JSON.parse(processedBody);
1256
+ }
1257
+ catch (e) {
1258
+ console.error('Unable to process the request body as a JSON string', e);
1259
+ }
1260
+ _a.label = 2;
1261
+ case 2: return [2, {
1262
+ payload: returnedPayload,
1263
+ url: returnedUrl,
1264
+ }];
1265
+ }
1266
+ });
1267
+ });
1268
+ };
1251
1269
  AnalyticsBeaconClient.prototype.encodeForEventType = function (eventType, payload) {
1252
1270
  return this.isEventTypeLegacy(eventType)
1253
1271
  ? this.encodeForLegacyType(eventType, payload)
@@ -658,7 +658,7 @@ const addPageViewToHistory = (pageViewValue) => __awaiter(void 0, void 0, void 0
658
658
  yield store.addElementAsync(historyElement);
659
659
  });
660
660
 
661
- const libVersion = "2.28.14" ;
661
+ const libVersion = "2.28.16" ;
662
662
 
663
663
  const getFormattedLocation = (location) => `${location.protocol}//${location.hostname}${location.pathname.indexOf('/') === 0 ? location.pathname : `/${location.pathname}`}${location.search}`;
664
664
 
@@ -1069,21 +1069,18 @@ class AnalyticsBeaconClient {
1069
1069
  constructor(opts) {
1070
1070
  this.opts = opts;
1071
1071
  }
1072
- sendEvent(eventType, payload) {
1072
+ sendEvent(eventType, originalPayload) {
1073
1073
  return __awaiter(this, void 0, void 0, function* () {
1074
1074
  if (!this.isAvailable()) {
1075
1075
  throw new Error(`navigator.sendBeacon is not supported in this browser. Consider adding a polyfill like "sendbeacon-polyfill".`);
1076
1076
  }
1077
1077
  const { baseUrl, preprocessRequest } = this.opts;
1078
- const parsedRequestData = this.encodeForEventType(eventType, payload);
1079
1078
  const paramsFragments = yield this.getQueryParamsForEventType(eventType);
1080
- const defaultOptions = {
1081
- url: `${baseUrl}/analytics/${eventType}?${paramsFragments}`,
1082
- body: new Blob([parsedRequestData], {
1083
- type: 'application/x-www-form-urlencoded',
1084
- }),
1085
- };
1086
- const { url, body } = Object.assign(Object.assign({}, defaultOptions), (preprocessRequest ? yield preprocessRequest(defaultOptions, 'analyticsBeacon') : {}));
1079
+ const { url, payload } = yield this.preProcessRequestAsPotentialJSONString(`${baseUrl}/analytics/${eventType}?${paramsFragments}`, originalPayload, preprocessRequest);
1080
+ const parsedRequestData = this.encodeForEventType(eventType, payload);
1081
+ const body = new Blob([parsedRequestData], {
1082
+ type: 'application/x-www-form-urlencoded',
1083
+ });
1087
1084
  navigator.sendBeacon(url, body);
1088
1085
  return;
1089
1086
  });
@@ -1094,6 +1091,27 @@ class AnalyticsBeaconClient {
1094
1091
  deleteHttpCookieVisitorId() {
1095
1092
  return Promise.resolve();
1096
1093
  }
1094
+ preProcessRequestAsPotentialJSONString(originalURL, originalPayload, preprocessRequest) {
1095
+ return __awaiter(this, void 0, void 0, function* () {
1096
+ let returnedUrl = originalURL;
1097
+ let returnedPayload = originalPayload;
1098
+ if (preprocessRequest) {
1099
+ const processedRequest = yield preprocessRequest({ url: originalURL, body: JSON.stringify(originalPayload) }, 'analyticsBeacon');
1100
+ const { url: processedURL, body: processedBody } = processedRequest;
1101
+ returnedUrl = processedURL || originalURL;
1102
+ try {
1103
+ returnedPayload = JSON.parse(processedBody);
1104
+ }
1105
+ catch (e) {
1106
+ console.error('Unable to process the request body as a JSON string', e);
1107
+ }
1108
+ }
1109
+ return {
1110
+ payload: returnedPayload,
1111
+ url: returnedUrl,
1112
+ };
1113
+ });
1114
+ }
1097
1115
  encodeForEventType(eventType, payload) {
1098
1116
  return this.isEventTypeLegacy(eventType)
1099
1117
  ? this.encodeForLegacyType(eventType, payload)
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "modules",
3
+ "private": true,
4
+ "main": "../dist/library.cjs",
5
+ "module": "../dist/library.mjs",
6
+ "browser": "../dist/browser.mjs",
7
+ "types": "../dist/definitions/coveoua/library.d.ts",
8
+ "files": [
9
+ "../dist"
10
+ ]
11
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "coveo.analytics",
3
- "version": "2.28.14",
3
+ "version": "2.28.16",
4
4
  "description": "📈 Coveo analytics client (node and browser compatible) ",
5
- "main": "dist/library.js",
6
- "module": "dist/library.es.js",
5
+ "main": "dist/library.cjs",
6
+ "module": "dist/browser.mjs",
7
7
  "browser": "dist/coveoua.browser.js",
8
8
  "types": "dist/definitions/coveoua/library.d.ts",
9
9
  "scripts": {
@@ -65,9 +65,10 @@
65
65
  "plist": "3.0.5"
66
66
  },
67
67
  "files": [
68
+ "modules/",
68
69
  "dist/**/*.d.ts",
69
- "dist/**/*.js",
70
- "dist/**/*.js.map",
70
+ "dist/**/*.{js, mjs, cjs}",
71
+ "dist/**/*.{js, mjs, cjs}.map",
71
72
  "src/**/*.ts",
72
73
  "react-native/",
73
74
  "LICENSE"
@@ -1,6 +1,6 @@
1
1
  import {AnalyticsBeaconClient} from './analyticsBeaconClient';
2
2
  import {EventType} from '../events';
3
- import {AnalyticsClientOrigin, IAnalyticsRequestOptions} from './analyticsRequestClient';
3
+ import {AnalyticsClientOrigin, IAnalyticsRequestOptions, PreprocessAnalyticsRequest} from './analyticsRequestClient';
4
4
 
5
5
  describe('AnalyticsBeaconClient', () => {
6
6
  const baseUrl = 'https://bloup.com';
@@ -99,33 +99,94 @@ describe('AnalyticsBeaconClient', () => {
99
99
  );
100
100
  });
101
101
 
102
- it('should preprocess the request with the preprocessRequest', async () => {
103
- let clientOrigin: AnalyticsClientOrigin;
104
- const processedRequest: IAnalyticsRequestOptions = {
105
- url: 'https://www.myownanalytics.com/endpoint',
106
- body: JSON.stringify({
107
- test: 'custom',
108
- }),
109
- };
110
- const client = new AnalyticsBeaconClient({
111
- baseUrl,
112
- token,
113
- visitorIdProvider: {
114
- getCurrentVisitorId: () => {
115
- return Promise.resolve(currentVisitorId);
102
+ describe('allows to preprocessRequest', () => {
103
+ const setupClient = (preprocessRequest: PreprocessAnalyticsRequest) => {
104
+ return new AnalyticsBeaconClient({
105
+ baseUrl,
106
+ token,
107
+ visitorIdProvider: {
108
+ getCurrentVisitorId: () => {
109
+ return Promise.resolve(currentVisitorId);
110
+ },
111
+ setCurrentVisitorId: () => {},
116
112
  },
117
- setCurrentVisitorId: () => {},
118
- },
119
- preprocessRequest: (_request, type) => {
113
+ preprocessRequest,
114
+ });
115
+ };
116
+
117
+ it('to modify the origin and the body of the request', async () => {
118
+ let clientOrigin: AnalyticsClientOrigin;
119
+ const processedRequest: IAnalyticsRequestOptions = {
120
+ url: 'https://www.myownanalytics.com/endpoint',
121
+ body: JSON.stringify({
122
+ test: 'custom',
123
+ }),
124
+ };
125
+ const client = setupClient((_request, type) => {
120
126
  clientOrigin = type;
121
127
  return processedRequest;
122
- },
128
+ });
129
+
130
+ await client.sendEvent(EventType.collect, {});
131
+
132
+ expect(clientOrigin!).toBe('analyticsBeacon');
133
+ expect(sendBeaconMock).toHaveBeenCalledWith(processedRequest.url, expect.anything());
134
+ expect(await getSendBeaconFirstCallBlobArgument()).toContain('test=custom');
123
135
  });
124
136
 
125
- await client.sendEvent(EventType.collect, {});
137
+ it('to modify the request body as a JSON string for a collect event', async () => {
138
+ const client = setupClient((request) => {
139
+ const bodyShouldBeAvailableAsJSONString = JSON.parse(request.body as string);
140
+ expect(bodyShouldBeAvailableAsJSONString).toEqual({foo: 'bar'});
141
+ bodyShouldBeAvailableAsJSONString.foo = 'baz';
142
+ request.body = JSON.stringify(bodyShouldBeAvailableAsJSONString);
143
+ return request;
144
+ });
145
+
146
+ await client.sendEvent(EventType.collect, {foo: 'bar'});
147
+ expect(await getSendBeaconFirstCallBlobArgument()).toContain(`foo=baz`);
148
+ });
149
+
150
+ it('to modify the request body as a JSON string for a click event', async () => {
151
+ const client = setupClient((request) => {
152
+ const bodyParsedAsJSON = JSON.parse(request.body as string);
153
+ expect(bodyParsedAsJSON).toEqual({actionCause: 'foo'});
154
+ bodyParsedAsJSON.actionCause = 'bar';
155
+ request.body = JSON.stringify(bodyParsedAsJSON);
156
+ return request;
157
+ });
158
+
159
+ await client.sendEvent(EventType.click, {actionCause: 'foo'});
160
+ expect(await getSendBeaconFirstCallBlobArgument()).toContain(
161
+ `clickEvent=${encodeURIComponent(`{"actionCause":"bar"}`)}`
162
+ );
163
+ });
126
164
 
127
- expect(clientOrigin!).toBe('analyticsBeacon');
128
- expect(sendBeaconMock).toHaveBeenCalledWith(processedRequest.url, processedRequest.body);
165
+ it('to augment the request body as a JSON string for a click event', async () => {
166
+ const client = setupClient((request) => {
167
+ const bodyParsedAsJSON = JSON.parse(request.body as string);
168
+ bodyParsedAsJSON.aNewProperty = 'bar';
169
+ request.body = JSON.stringify(bodyParsedAsJSON);
170
+ return request;
171
+ });
172
+
173
+ await client.sendEvent(EventType.click, {actionCause: 'foo'});
174
+ expect(await getSendBeaconFirstCallBlobArgument()).toContain(
175
+ `clickEvent=${encodeURIComponent(`{"actionCause":"foo","aNewProperty":"bar"}`)}`
176
+ );
177
+ });
178
+
179
+ it('should keep original request body if preprocessRequest returns an invalid JSON string', async () => {
180
+ const client = setupClient((request) => {
181
+ request.body = 'invalid JSON string';
182
+ return request;
183
+ });
184
+
185
+ await client.sendEvent(EventType.click, {actionCause: 'bar'});
186
+ expect(await getSendBeaconFirstCallBlobArgument()).toContain(
187
+ `clickEvent=${encodeURIComponent(`{"actionCause":"bar"}`)}`
188
+ );
189
+ });
129
190
  });
130
191
 
131
192
  const getSendBeaconFirstCallBlobArgument = async () => {
@@ -1,10 +1,10 @@
1
- import {AnalyticsRequestClient, IAnalyticsRequestOptions, IAnalyticsClientOptions} from './analyticsRequestClient';
1
+ import {AnalyticsRequestClient, IAnalyticsClientOptions, PreprocessAnalyticsRequest} from './analyticsRequestClient';
2
2
  import {EventType, IRequestPayload} from '../events';
3
3
 
4
4
  export class AnalyticsBeaconClient implements AnalyticsRequestClient {
5
5
  constructor(private opts: IAnalyticsClientOptions) {}
6
6
 
7
- public async sendEvent(eventType: EventType, payload: IRequestPayload): Promise<void> {
7
+ public async sendEvent(eventType: EventType, originalPayload: IRequestPayload): Promise<void> {
8
8
  if (!this.isAvailable()) {
9
9
  throw new Error(
10
10
  `navigator.sendBeacon is not supported in this browser. Consider adding a polyfill like "sendbeacon-polyfill".`
@@ -12,18 +12,19 @@ export class AnalyticsBeaconClient implements AnalyticsRequestClient {
12
12
  }
13
13
 
14
14
  const {baseUrl, preprocessRequest} = this.opts;
15
- const parsedRequestData = this.encodeForEventType(eventType, payload);
15
+
16
16
  const paramsFragments = await this.getQueryParamsForEventType(eventType);
17
- const defaultOptions: IAnalyticsRequestOptions = {
18
- url: `${baseUrl}/analytics/${eventType}?${paramsFragments}`,
19
- body: new Blob([parsedRequestData], {
20
- type: 'application/x-www-form-urlencoded',
21
- }),
22
- };
23
- const {url, body}: IAnalyticsRequestOptions = {
24
- ...defaultOptions,
25
- ...(preprocessRequest ? await preprocessRequest(defaultOptions, 'analyticsBeacon') : {}),
26
- };
17
+
18
+ const {url, payload} = await this.preProcessRequestAsPotentialJSONString(
19
+ `${baseUrl}/analytics/${eventType}?${paramsFragments}`,
20
+ originalPayload,
21
+ preprocessRequest
22
+ );
23
+
24
+ const parsedRequestData = this.encodeForEventType(eventType, payload);
25
+ const body = new Blob([parsedRequestData], {
26
+ type: 'application/x-www-form-urlencoded',
27
+ });
27
28
 
28
29
  navigator.sendBeacon(url, body as any); // https://github.com/microsoft/TypeScript/issues/38715
29
30
  return;
@@ -37,6 +38,34 @@ export class AnalyticsBeaconClient implements AnalyticsRequestClient {
37
38
  return Promise.resolve();
38
39
  }
39
40
 
41
+ private async preProcessRequestAsPotentialJSONString(
42
+ originalURL: string,
43
+ originalPayload: IRequestPayload,
44
+ preprocessRequest?: PreprocessAnalyticsRequest
45
+ ): Promise<{url: string; payload: IRequestPayload}> {
46
+ let returnedUrl = originalURL;
47
+ let returnedPayload = originalPayload;
48
+
49
+ if (preprocessRequest) {
50
+ const processedRequest = await preprocessRequest(
51
+ {url: originalURL, body: JSON.stringify(originalPayload)},
52
+ 'analyticsBeacon'
53
+ );
54
+ const {url: processedURL, body: processedBody} = processedRequest;
55
+ returnedUrl = processedURL || originalURL;
56
+ try {
57
+ returnedPayload = JSON.parse(processedBody as string);
58
+ } catch (e) {
59
+ console.error('Unable to process the request body as a JSON string', e);
60
+ }
61
+ }
62
+
63
+ return {
64
+ payload: returnedPayload,
65
+ url: returnedUrl,
66
+ };
67
+ }
68
+
40
69
  private encodeForEventType(eventType: EventType, payload: IRequestPayload): string {
41
70
  return this.isEventTypeLegacy(eventType)
42
71
  ? this.encodeForLegacyType(eventType, payload)