@mparticle/web-sdk 2.63.0 → 2.64.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/src/forwarders.js CHANGED
@@ -1,9 +1,17 @@
1
- import Types from './types';
2
1
  import filteredMparticleUser from './filteredMparticleUser';
3
- import { isEmpty } from './utils';
2
+ import { isEmpty, extend } from './utils';
4
3
  import KitFilterHelper from './kitFilterHelper';
5
4
  import Constants from './constants';
6
5
  import APIClient from './apiClient';
6
+ import {
7
+ isBlockedByForwardingRule,
8
+ isBlockedByEventFilter,
9
+ filterEventAttributes,
10
+ filterUserIdentities,
11
+ isBatchEventAllowed,
12
+ filterBatchEventAttributes,
13
+ filterBatchIdentities,
14
+ } from './forwarder-utils';
7
15
 
8
16
  const { Modify, Identify, Login, Logout } = Constants.IdentityMethods;
9
17
 
@@ -65,7 +73,7 @@ export default function Forwarders(mpInstance, kitBlocker) {
65
73
  userIdentities,
66
74
  forwarder.userIdentityFilters
67
75
  );
68
- var filteredUserAttributes = mpInstance._Helpers.filterUserAttributes(
76
+ const filteredUserAttributes = KitFilterHelper.filterUserAttributes(
69
77
  user ? user.getAllUserAttributes() : {},
70
78
  forwarder.userAttributeFilters
71
79
  );
@@ -177,64 +185,9 @@ export default function Forwarders(mpInstance, kitBlocker) {
177
185
  };
178
186
 
179
187
  this.sendEventToForwarders = function(event) {
180
- var clonedEvent,
181
- hashedEventName,
182
- hashedEventType,
183
- filterUserIdentities = function(event, filterList) {
184
- if (event.UserIdentities && event.UserIdentities.length) {
185
- event.UserIdentities.forEach(function(userIdentity, i) {
186
- if (
187
- mpInstance._Helpers.inArray(
188
- filterList,
189
- KitFilterHelper.hashUserIdentity(
190
- userIdentity.Type
191
- )
192
- )
193
- ) {
194
- event.UserIdentities.splice(i, 1);
195
-
196
- if (i > 0) {
197
- i--;
198
- }
199
- }
200
- });
201
- }
202
- },
203
- filterAttributes = function(event, filterList) {
204
- var hash;
205
-
206
- if (!filterList) {
207
- return;
208
- }
209
-
210
- for (var attrName in event.EventAttributes) {
211
- if (event.EventAttributes.hasOwnProperty(attrName)) {
212
- hash = KitFilterHelper.hashEventAttributeKey(
213
- event.EventCategory,
214
- event.EventName,
215
- attrName
216
- );
217
-
218
- if (mpInstance._Helpers.inArray(filterList, hash)) {
219
- delete event.EventAttributes[attrName];
220
- }
221
- }
222
- }
223
- },
224
- inFilteredList = function(filterList, hash) {
225
- if (filterList && filterList.length) {
226
- if (mpInstance._Helpers.inArray(filterList, hash)) {
227
- return true;
228
- }
229
- }
230
-
231
- return false;
232
- },
233
- forwardingRuleMessageTypes = [
234
- Types.MessageType.PageEvent,
235
- Types.MessageType.PageView,
236
- Types.MessageType.Commerce,
237
- ];
188
+ let clonedEvent;
189
+ let hashedEventName;
190
+ let hashedEventType;
238
191
 
239
192
  if (
240
193
  !mpInstance._Store.webviewBridgeEnabled &&
@@ -249,153 +202,61 @@ export default function Forwarders(mpInstance, kitBlocker) {
249
202
  );
250
203
 
251
204
  for (
252
- var i = 0;
205
+ let i = 0;
253
206
  i < mpInstance._Store.activeForwarders.length;
254
207
  i++
255
208
  ) {
256
- // Check attribute forwarding rule. This rule allows users to only forward an event if a
257
- // specific attribute exists and has a specific value. Alternatively, they can specify
258
- // that an event not be forwarded if the specified attribute name and value exists.
259
- // The two cases are controlled by the "includeOnMatch" boolean value.
260
- // Supported message types for attribute forwarding rules are defined in the forwardingRuleMessageTypes array
209
+ const forwarder = mpInstance._Store.activeForwarders[i];
261
210
 
262
211
  if (
263
- forwardingRuleMessageTypes.indexOf(event.EventDataType) >
264
- -1 &&
265
- mpInstance._Store.activeForwarders[i]
266
- .filteringEventAttributeValue &&
267
- mpInstance._Store.activeForwarders[i]
268
- .filteringEventAttributeValue.eventAttributeName &&
269
- mpInstance._Store.activeForwarders[i]
270
- .filteringEventAttributeValue.eventAttributeValue
212
+ isBlockedByForwardingRule(
213
+ event.EventDataType,
214
+ event.EventAttributes,
215
+ forwarder
216
+ )
271
217
  ) {
272
- var foundProp = null;
273
-
274
- // Attempt to find the attribute in the collection of event attributes
275
- if (event.EventAttributes) {
276
- for (var prop in event.EventAttributes) {
277
- var hashedEventAttributeName;
278
- hashedEventAttributeName = KitFilterHelper.hashAttributeConditionalForwarding(
279
- prop
280
- );
281
-
282
- if (
283
- hashedEventAttributeName ===
284
- mpInstance._Store.activeForwarders[i]
285
- .filteringEventAttributeValue
286
- .eventAttributeName
287
- ) {
288
- foundProp = {
289
- name: hashedEventAttributeName,
290
- value: KitFilterHelper.hashAttributeConditionalForwarding(
291
- event.EventAttributes[prop]
292
- ),
293
- };
294
- }
295
-
296
- if (foundProp) {
297
- break;
298
- }
299
- }
300
- }
301
-
302
- var isMatch =
303
- foundProp !== null &&
304
- foundProp.value ===
305
- mpInstance._Store.activeForwarders[i]
306
- .filteringEventAttributeValue
307
- .eventAttributeValue;
308
-
309
- var shouldInclude =
310
- mpInstance._Store.activeForwarders[i]
311
- .filteringEventAttributeValue.includeOnMatch ===
312
- true
313
- ? isMatch
314
- : !isMatch;
315
-
316
- if (!shouldInclude) {
317
- continue;
318
- }
218
+ continue;
319
219
  }
320
220
 
321
221
  // Clone the event object, as we could be sending different attributes to each forwarder
322
- clonedEvent = {};
323
- clonedEvent = mpInstance._Helpers.extend(
324
- true,
325
- clonedEvent,
326
- event
327
- );
328
- // Check event filtering rules
222
+ clonedEvent = extend(true, {}, event);
223
+
329
224
  if (
330
- event.EventDataType === Types.MessageType.PageEvent &&
331
- (inFilteredList(
332
- mpInstance._Store.activeForwarders[i].eventNameFilters,
333
- hashedEventName
334
- ) ||
335
- inFilteredList(
336
- mpInstance._Store.activeForwarders[i]
337
- .eventTypeFilters,
338
- hashedEventType
339
- ))
340
- ) {
341
- continue;
342
- } else if (
343
- event.EventDataType === Types.MessageType.Commerce &&
344
- inFilteredList(
345
- mpInstance._Store.activeForwarders[i].eventTypeFilters,
346
- hashedEventType
347
- )
348
- ) {
349
- continue;
350
- } else if (
351
- event.EventDataType === Types.MessageType.PageView &&
352
- inFilteredList(
353
- mpInstance._Store.activeForwarders[i].screenNameFilters,
354
- hashedEventName
225
+ isBlockedByEventFilter(
226
+ event.EventDataType,
227
+ hashedEventName,
228
+ hashedEventType,
229
+ forwarder
355
230
  )
356
231
  ) {
357
232
  continue;
358
233
  }
359
234
 
360
- // Check attribute filtering rules
361
- if (clonedEvent.EventAttributes) {
362
- if (event.EventDataType === Types.MessageType.PageEvent) {
363
- filterAttributes(
364
- clonedEvent,
365
- mpInstance._Store.activeForwarders[i]
366
- .attributeFilters
367
- );
368
- } else if (
369
- event.EventDataType === Types.MessageType.PageView
370
- ) {
371
- filterAttributes(
372
- clonedEvent,
373
- mpInstance._Store.activeForwarders[i]
374
- .screenAttributeFilters
375
- );
376
- }
377
- }
235
+ clonedEvent.EventAttributes = filterEventAttributes(
236
+ event.EventDataType,
237
+ event.EventCategory,
238
+ event.EventName,
239
+ clonedEvent.EventAttributes,
240
+ forwarder
241
+ );
378
242
 
379
243
  // Check user identity filtering rules
380
- filterUserIdentities(
381
- clonedEvent,
382
- mpInstance._Store.activeForwarders[i].userIdentityFilters
244
+ clonedEvent.UserIdentities = filterUserIdentities(
245
+ clonedEvent.UserIdentities,
246
+ forwarder.userIdentityFilters
383
247
  );
384
248
 
385
249
  // Check user attribute filtering rules
386
- clonedEvent.UserAttributes = mpInstance._Helpers.filterUserAttributes(
250
+ clonedEvent.UserAttributes = KitFilterHelper.filterUserAttributes(
387
251
  clonedEvent.UserAttributes,
388
- mpInstance._Store.activeForwarders[i].userAttributeFilters
252
+ forwarder.userAttributeFilters
389
253
  );
390
254
 
391
- if (mpInstance._Store.activeForwarders[i].process) {
255
+ if (forwarder.process) {
392
256
  mpInstance.Logger.verbose(
393
- 'Sending message to forwarder: ' +
394
- mpInstance._Store.activeForwarders[i].name
395
- );
396
- var result = mpInstance._Store.activeForwarders[i].process(
397
- clonedEvent
257
+ 'Sending message to forwarder: ' + forwarder.name
398
258
  );
259
+ const result = forwarder.process(clonedEvent);
399
260
 
400
261
  if (result) {
401
262
  mpInstance.Logger.verbose(result);
@@ -414,21 +275,48 @@ export default function Forwarders(mpInstance, kitBlocker) {
414
275
  }
415
276
 
416
277
  for (const forwarder of mpInstance._Store.activeForwarders) {
417
- if (forwarder.processBatch) {
418
- try {
419
- const batchCopy = mpInstance._Helpers.extend(
420
- true,
421
- {},
422
- batch
278
+ if (!forwarder.processBatch) {
279
+ continue;
280
+ }
281
+
282
+ try {
283
+ const batchCopy = extend(true, {}, batch);
284
+
285
+ if (batchCopy.events) {
286
+ batchCopy.events = batchCopy.events.filter(function(
287
+ batchEvent
288
+ ) {
289
+ return isBatchEventAllowed(batchEvent, forwarder);
290
+ });
291
+
292
+ batchCopy.events.forEach(function(batchEvent) {
293
+ filterBatchEventAttributes(batchEvent, forwarder);
294
+ });
295
+ }
296
+
297
+ batchCopy.user_identities = filterBatchIdentities(
298
+ batchCopy.user_identities,
299
+ forwarder.userIdentityFilters
300
+ );
301
+
302
+ if (batchCopy.user_attributes) {
303
+ batchCopy.user_attributes = KitFilterHelper.filterUserAttributes(
304
+ batchCopy.user_attributes,
305
+ forwarder.userAttributeFilters
423
306
  );
424
- const result = forwarder.processBatch(batchCopy);
307
+ }
425
308
 
426
- if (result) {
427
- mpInstance.Logger.verbose(result);
428
- }
429
- } catch (e) {
430
- mpInstance.Logger.verbose(e);
309
+ if (!batchCopy.events || batchCopy.events.length === 0) {
310
+ continue;
311
+ }
312
+
313
+ const result = forwarder.processBatch(batchCopy);
314
+
315
+ if (result) {
316
+ mpInstance.Logger.verbose(result);
431
317
  }
318
+ } catch (e) {
319
+ mpInstance.Logger.verbose(e);
432
320
  }
433
321
  }
434
322
  };
package/src/helpers.js CHANGED
@@ -99,154 +99,7 @@ export default function Helpers(mpInstance) {
99
99
  }
100
100
  };
101
101
 
102
- // https://go.mparticle.com/work/SQDSDKS-6047
103
- // Standalone version of jQuery.extend, from https://github.com/dansdom/extend
104
- this.extend = function() {
105
- var options,
106
- name,
107
- src,
108
- copy,
109
- copyIsArray,
110
- clone,
111
- target = arguments[0] || {},
112
- i = 1,
113
- length = arguments.length,
114
- deep = false,
115
- // helper which replicates the jquery internal functions
116
- objectHelper = {
117
- hasOwn: Object.prototype.hasOwnProperty,
118
- class2type: {},
119
- type: function(obj) {
120
- return obj == null
121
- ? String(obj)
122
- : objectHelper.class2type[
123
- Object.prototype.toString.call(obj)
124
- ] || 'object';
125
- },
126
- isPlainObject: function(obj) {
127
- if (
128
- !obj ||
129
- objectHelper.type(obj) !== 'object' ||
130
- obj.nodeType ||
131
- objectHelper.isWindow(obj)
132
- ) {
133
- return false;
134
- }
135
-
136
- try {
137
- if (
138
- obj.constructor &&
139
- !objectHelper.hasOwn.call(obj, 'constructor') &&
140
- !objectHelper.hasOwn.call(
141
- obj.constructor.prototype,
142
- 'isPrototypeOf'
143
- )
144
- ) {
145
- return false;
146
- }
147
- } catch (e) {
148
- return false;
149
- }
150
-
151
- var key;
152
- for (key in obj) {
153
- } // eslint-disable-line no-empty
154
-
155
- return (
156
- key === undefined || objectHelper.hasOwn.call(obj, key)
157
- );
158
- },
159
- isArray:
160
- Array.isArray ||
161
- function(obj) {
162
- return objectHelper.type(obj) === 'array';
163
- },
164
- isFunction: function(obj) {
165
- return objectHelper.type(obj) === 'function';
166
- },
167
- isWindow: function(obj) {
168
- return obj != null && obj == obj.window;
169
- },
170
- }; // end of objectHelper
171
-
172
- // Handle a deep copy situation
173
- if (typeof target === 'boolean') {
174
- deep = target;
175
- target = arguments[1] || {};
176
- // skip the boolean and the target
177
- i = 2;
178
- }
179
-
180
- // Handle case when target is a string or something (possible in deep copy)
181
- if (typeof target !== 'object' && !objectHelper.isFunction(target)) {
182
- target = {};
183
- }
184
-
185
- // If no second argument is used then this can extend an object that is using this method
186
- if (length === i) {
187
- target = this;
188
- --i;
189
- }
190
-
191
- for (; i < length; i++) {
192
- // Only deal with non-null/undefined values
193
- if ((options = arguments[i]) != null) {
194
- // Extend the base object
195
- for (name in options) {
196
- // Prevent prototype pollution
197
- // https://github.com/advisories/GHSA-jf85-cpcp-j695
198
- if (
199
- name === '__proto__' ||
200
- name === 'constructor' ||
201
- name === 'prototype'
202
- ) {
203
- continue;
204
- }
205
-
206
- // Only copy own properties
207
- if (!Object.prototype.hasOwnProperty.call(options, name)) {
208
- continue;
209
- }
210
-
211
- src = target[name];
212
- copy = options[name];
213
-
214
- // Prevent never-ending loop
215
- if (target === copy) {
216
- continue;
217
- }
218
-
219
- // Recurse if we're merging plain objects or arrays
220
- if (
221
- deep &&
222
- copy &&
223
- (objectHelper.isPlainObject(copy) ||
224
- (copyIsArray = objectHelper.isArray(copy)))
225
- ) {
226
- if (copyIsArray) {
227
- copyIsArray = false;
228
- clone = src && objectHelper.isArray(src) ? src : [];
229
- } else {
230
- clone =
231
- src && objectHelper.isPlainObject(src)
232
- ? src
233
- : {};
234
- }
235
-
236
- // Never move original objects, clone them
237
- target[name] = self.extend(deep, clone, copy);
238
-
239
- // Don't bring in undefined values
240
- } else if (copy !== undefined) {
241
- target[name] = copy;
242
- }
243
- }
244
- }
245
- }
246
-
247
- // Return the modified object
248
- return target;
249
- };
102
+ this.extend = utils.extend;
250
103
 
251
104
  this.createServiceUrl = function(secureServiceUrl, devToken) {
252
105
  var serviceScheme =
@@ -5,6 +5,7 @@ import { SDKEvent, BaseEvent } from './sdkRuntimeModels';
5
5
  import { convertEvents } from './sdkToEventsApiConverter';
6
6
  import { Batch } from '@mparticle/event-models';
7
7
  import { IMParticleWebSDKInstance } from './mp-instance';
8
+ import { extend } from './utils';
8
9
 
9
10
  const mockFunction = function() {
10
11
  return null;
@@ -22,7 +23,7 @@ export default class _BatchValidator {
22
23
  generateUniqueId: function() {
23
24
  return 'mockId';
24
25
  },
25
- extend: (window.mParticle.getInstance() as unknown as IMParticleWebSDKInstance)._Helpers.extend,
26
+ extend,
26
27
  createServiceUrl: mockFunction,
27
28
  parseNumber: mockFunction,
28
29
  isObject: mockFunction,
@@ -36,7 +36,7 @@ import Consent, { IConsent } from './consent';
36
36
  import KitBlocker from './kitBlocking';
37
37
  import ConfigAPIClient, { IKitConfigs } from './configAPIClient';
38
38
  import IdentityAPIClient from './identityApiClient';
39
- import { isFunction, parseConfig, valueof, generateDeprecationMessage } from './utils';
39
+ import { isFunction, parseConfig, valueof, generateDeprecationMessage, extend } from './utils';
40
40
  import { DisabledVault, LocalStorageVault } from './vault';
41
41
  import { removeExpiredIdentityCacheDates, hasExplicitIdentifier } from './identity-utils';
42
42
  import IntegrationCapture from './integrationCapture';
@@ -228,7 +228,7 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan
228
228
  );
229
229
 
230
230
  configApiClient.getSDKConfiguration().then(result => {
231
- const mergedConfig = this._Helpers.extend(
231
+ const mergedConfig = extend(
232
232
  {},
233
233
  config,
234
234
  result
@@ -49,7 +49,7 @@ export default function _Persistence(mpInstance) {
49
49
  if (localStorageData) {
50
50
  if (cookies) {
51
51
  // https://go.mparticle.com/work/SQDSDKS-6047
52
- allData = mpInstance._Helpers.extend(
52
+ allData = Utils.extend(
53
53
  false,
54
54
  localStorageData,
55
55
  cookies
@@ -68,7 +68,7 @@ export default function _Persistence(mpInstance) {
68
68
  if (cookies) {
69
69
  if (localStorageData) {
70
70
  // https://go.mparticle.com/work/SQDSDKS-6047
71
- allData = mpInstance._Helpers.extend(
71
+ allData = Utils.extend(
72
72
  false,
73
73
  localStorageData,
74
74
  cookies
@@ -255,7 +255,7 @@ export default function _Persistence(mpInstance) {
255
255
  }
256
256
 
257
257
  if (Object.keys(mpInstance._Store.nonCurrentUserMPIDs).length) {
258
- localStorageData = mpInstance._Helpers.extend(
258
+ localStorageData = Utils.extend(
259
259
  {},
260
260
  localStorageData,
261
261
  mpInstance._Store.nonCurrentUserMPIDs
@@ -451,7 +451,7 @@ export default function _Persistence(mpInstance) {
451
451
  cookies = setGlobalStorageAttributes(cookies);
452
452
 
453
453
  if (Object.keys(mpInstance._Store.nonCurrentUserMPIDs).length) {
454
- cookies = mpInstance._Helpers.extend(
454
+ cookies = Utils.extend(
455
455
  {},
456
456
  cookies,
457
457
  mpInstance._Store.nonCurrentUserMPIDs
@@ -11,7 +11,7 @@ import {
11
11
  SDKGDPRConsentState,
12
12
  SDKCCPAConsentState,
13
13
  } from './consent';
14
- import Types from './types';
14
+ import Types, { getEventCategoryFromCustomEventType } from './types';
15
15
  import { Dictionary, isEmpty } from './utils';
16
16
  import { ISDKUserIdentity } from './identity-user-interfaces';
17
17
  import { SDKIdentityTypeEnum } from './identity.interfaces';
@@ -795,3 +795,57 @@ export function convertUserIdentityTypeToServerIdentityType(
795
795
  return EventsApi.IdentityTypeEnum.phoneNumber3;
796
796
  }
797
797
  }
798
+
799
+ export function getEventNameFromBatchEvent(
800
+ batchEvent: EventsApi.BaseEvent
801
+ ): string {
802
+ if (!batchEvent || !(batchEvent as any).data) {
803
+ return '';
804
+ }
805
+ if ((batchEvent as any).event_type === 'screen_view') {
806
+ return (batchEvent as any).data.screen_name || '';
807
+ }
808
+ return (batchEvent as any).data.event_name || '';
809
+ }
810
+
811
+ export function getEventCategoryFromBatchEvent(
812
+ batchEvent: EventsApi.BaseEvent
813
+ ): number {
814
+ if (!batchEvent || !(batchEvent as any).data) {
815
+ return Types.EventType.Unknown;
816
+ }
817
+
818
+ const data = (batchEvent as any).data;
819
+
820
+ if (data.custom_event_type) {
821
+ return getEventCategoryFromCustomEventType(data.custom_event_type);
822
+ }
823
+
824
+ if ((batchEvent as any).event_type === 'commerce_event') {
825
+ return getCommerceEventCategory(data);
826
+ }
827
+
828
+ return Types.EventType.Unknown;
829
+ }
830
+
831
+ function getCommerceEventCategory(data: any): number {
832
+ if (data.product_action && data.product_action.action) {
833
+ return getEventCategoryFromCustomEventType(
834
+ data.product_action.action
835
+ );
836
+ }
837
+
838
+ const promoAction = data.promotion_action && data.promotion_action.action;
839
+ if (promoAction === 'view') {
840
+ return Types.CommerceEventType.PromotionView;
841
+ }
842
+ if (promoAction === 'click') {
843
+ return Types.CommerceEventType.PromotionClick;
844
+ }
845
+
846
+ if (data.product_impressions) {
847
+ return Types.CommerceEventType.ProductImpression;
848
+ }
849
+
850
+ return Types.EventType.Unknown;
851
+ }
@@ -16,6 +16,7 @@ import {
16
16
  parseStringOrNumber,
17
17
  Dictionary,
18
18
  isValidCustomFlagProperty,
19
+ extend,
19
20
  } from './utils';
20
21
  import { IntegrationAttributes, ServerSettings } from './store';
21
22
  import { MPID } from '@mparticle/web-sdk';
@@ -379,7 +380,7 @@ export default function ServerModel(
379
380
 
380
381
  uploadObject.Timestamp = mpInstance._Store.dateLastEventSent.getTime();
381
382
 
382
- return mpInstance._Helpers.extend({}, eventObject, uploadObject);
383
+ return extend({}, eventObject, uploadObject);
383
384
  }
384
385
 
385
386
  return null;
package/src/store.ts CHANGED
@@ -28,9 +28,8 @@ import {
28
28
  moveElementToEnd,
29
29
  parseNumber,
30
30
  returnConvertedBoolean,
31
- isValidAttributeValue,
32
- findKeyInObject,
33
31
  AttributeValue,
32
+ extend,
34
33
  } from './utils';
35
34
  import { IMinifiedConsentJSONObject, SDKConsentState } from './consent';
36
35
  import { ConfiguredKit, MPForwarder, UnregisteredKit } from './forwarders.interfaces';
@@ -650,7 +649,7 @@ export default function Store(
650
649
  this.syncPersistenceData = () => {
651
650
  const persistenceData = mpInstance._Persistence.getPersistence();
652
651
 
653
- this.persistenceData = mpInstance._Helpers.extend(
652
+ this.persistenceData = extend(
654
653
  {},
655
654
  this.persistenceData,
656
655
  persistenceData,