@mparticle/web-amplitude-kit 2.1.0 → 2.2.1

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.
@@ -11,16 +11,6 @@ function isObject(val) {
11
11
  return val != null && typeof val === 'object' && Array.isArray(val) === false;
12
12
  }
13
13
 
14
- var isobject = /*#__PURE__*/Object.freeze({
15
- 'default': isObject
16
- });
17
-
18
- function getCjsExportFromNamespace (n) {
19
- return n && n['default'] || n;
20
- }
21
-
22
- var isobject$1 = getCjsExportFromNamespace(isobject);
23
-
24
14
  /* eslint-disable no-undef*/
25
15
  //
26
16
  // Copyright 2015 mParticle, Inc.
@@ -59,8 +49,26 @@ var constants = {
59
49
  other2: 'other2',
60
50
  other3: 'other3',
61
51
  other4: 'other4',
52
+ other5: 'other5',
53
+ other6: 'other6',
54
+ other7: 'other7',
55
+ other8: 'other8',
56
+ other9: 'other9',
57
+ other10: 'other10',
62
58
  };
63
59
 
60
+ var MP_AMP_SPLIT = 'mparticle_amplitude_should_split',
61
+ TOTAL_AMOUNT = 'Total Amount',
62
+ TOTAL = 'Total',
63
+ PRODUCTS = 'products',
64
+ REFUND = 'Refund',
65
+ PURCHASE = 'Purchase',
66
+ TOTAL_PRODUCT_AMOUNT = 'Total Product Amount';
67
+
68
+ var includeIndividualProductEvents,
69
+ shouldSendSeparateAmplitudeRevenueEvent,
70
+ enableTempAmplitudeEcommerce;
71
+
64
72
  /* eslint-disable */
65
73
  // prettier-ignore
66
74
  var renderSnippet = function() {
@@ -167,7 +175,8 @@ var constructor = function () {
167
175
  }
168
176
 
169
177
  function onUserIdentified(user) {
170
- var userIdMissing;
178
+ var userId;
179
+
171
180
  if (isInitialized) {
172
181
  var userIdentities = user.getUserIdentities().userIdentities;
173
182
 
@@ -179,67 +188,51 @@ var constructor = function () {
179
188
  try {
180
189
  switch (forwarderSettings.userIdentification) {
181
190
  case constants.MPID:
182
- return getInstance().setUserId(user.getMPID());
191
+ userId = user.getMPID();
192
+ break;
183
193
  // server returns `customerId` whereas key on userIdentities object is `customerid`
184
194
  case constants.customerId:
185
- if (userIdentities.customerid) {
186
- return getInstance().setUserId(
187
- userIdentities.customerid
188
- );
189
- } else {
190
- userIdMissing = true;
191
- }
195
+ userId = userIdentities.customerid;
192
196
  break;
193
197
  case constants.email:
194
- if (userIdentities.email) {
195
- return getInstance().setUserId(
196
- userIdentities.email
197
- );
198
- } else {
199
- userIdMissing = true;
200
- }
198
+ userId = userIdentities.email;
201
199
  break;
202
200
  case constants.other:
203
- if (userIdentities.other) {
204
- return getInstance().setUserId(
205
- userIdentities.other
206
- );
207
- } else {
208
- userIdMissing = true;
209
- }
201
+ userId = userIdentities.other;
210
202
  break;
211
203
  case constants.other2:
212
- if (userIdentities.other2) {
213
- return getInstance().setUserId(
214
- userIdentities.other2
215
- );
216
- } else {
217
- userIdMissing = true;
218
- }
204
+ userId = userIdentities.other2;
219
205
  break;
220
206
  case constants.other3:
221
- if (userIdentities.other3) {
222
- return getInstance().setUserId(
223
- userIdentities.other3
224
- );
225
- } else {
226
- userIdMissing = true;
227
- }
207
+ userId = userIdentities.other3;
228
208
  break;
229
209
  case constants.other4:
230
- if (userIdentities.other4) {
231
- return getInstance().setUserId(
232
- userIdentities.other4
233
- );
234
- } else {
235
- userIdMissing = true;
236
- }
210
+ userId = userIdentities.other4;
211
+ break;
212
+ case constants.other5:
213
+ userId = userIdentities.other5;
214
+ break;
215
+ case constants.other6:
216
+ userId = userIdentities.other6;
217
+ break;
218
+ case constants.other7:
219
+ userId = userIdentities.other7;
220
+ break;
221
+ case constants.other8:
222
+ userId = userIdentities.other8;
223
+ break;
224
+ case constants.other9:
225
+ userId = userIdentities.other9;
226
+ break;
227
+ case constants.other10:
228
+ userId = userIdentities.other10;
237
229
  break;
238
-
239
230
  default:
240
- return;
231
+ userId = null;
241
232
  }
242
- if (userIdMissing) {
233
+ if (userId) {
234
+ return getInstance().setUserId(userId);
235
+ } else {
243
236
  console.warn(
244
237
  'A user identification type of ' +
245
238
  forwarderSettings.userIdentification +
@@ -360,7 +353,7 @@ var constructor = function () {
360
353
  function createEcommerceAttributes(attributes) {
361
354
  var updatedAttributes = {};
362
355
  for (var key in attributes) {
363
- if (key !== 'Total Amount' && key !== 'Total Product Amount') {
356
+ if (key !== TOTAL_AMOUNT && key !== TOTAL_PRODUCT_AMOUNT) {
364
357
  updatedAttributes[key] = attributes[key];
365
358
  }
366
359
  }
@@ -370,62 +363,263 @@ var constructor = function () {
370
363
 
371
364
  function logCommerce(event) {
372
365
  var expandedEvents = mParticle.eCommerce.expandCommerceEvent(event);
366
+ // if Product Action exists, it's a regular product action commerce event
373
367
  if (event.ProductAction) {
374
- var isRefund, isPurchase, logRevenue;
375
- isRefund =
376
- event.ProductAction.ProductActionType ===
377
- mParticle.ProductActionType.Refund;
378
- isPurchase =
379
- event.ProductAction.ProductActionType ===
380
- mParticle.ProductActionType.Purchase;
381
- logRevenue = isRefund || isPurchase;
368
+ if (enableTempAmplitudeEcommerce) {
369
+ return processTemporaryProductAction(event, expandedEvents);
370
+ } else {
371
+ // TODO: Remove this old code path when Amplitude is ready
372
+ var isRefund, isPurchase, logRevenue;
373
+ isRefund =
374
+ event.ProductAction.ProductActionType ===
375
+ mParticle.ProductActionType.Refund;
376
+ isPurchase =
377
+ event.ProductAction.ProductActionType ===
378
+ mParticle.ProductActionType.Purchase;
379
+ logRevenue = isRefund || isPurchase;
380
+ expandedEvents.forEach(function (expandedEvt) {
381
+ // Exclude Totals from the attributes as we log it in the revenue call
382
+ var updatedAttributes = createEcommerceAttributes(
383
+ expandedEvt.EventAttributes
384
+ );
385
+
386
+ // Purchase and Refund events generate an additional 'Total' event
387
+ if (
388
+ logRevenue &&
389
+ expandedEvt.EventName.indexOf('Total') > -1
390
+ ) {
391
+ var revenueAmount =
392
+ (expandedEvt.EventAttributes['Total Amount'] || 0) *
393
+ (isRefund ? -1 : 1);
394
+ var revenue = new window.amplitude.Revenue()
395
+ .setPrice(revenueAmount)
396
+ .setEventProperties(updatedAttributes);
397
+ getInstance().logRevenueV2(revenue);
398
+ } else {
399
+ getInstance().logEvent(
400
+ expandedEvt.EventName,
401
+ updatedAttributes
402
+ );
403
+ }
404
+ });
405
+
406
+ return true;
407
+ }
408
+ }
409
+
410
+ // if it is not a product action, it is an impression or promotion commerce event
411
+ if (isNotProductAction(event)) {
382
412
  expandedEvents.forEach(function (expandedEvt) {
383
413
  // Exclude Totals from the attributes as we log it in the revenue call
384
414
  var updatedAttributes = createEcommerceAttributes(
385
415
  expandedEvt.EventAttributes
386
416
  );
387
417
 
388
- // Purchase and Refund events generate an additional 'Total' event
389
- if (logRevenue && expandedEvt.EventName.indexOf('Total') > -1) {
390
- var revenueAmount =
391
- (expandedEvt.EventAttributes['Total Amount'] || 0) *
392
- (isRefund ? -1 : 1);
393
- var revenue = new window.amplitude.Revenue()
394
- .setPrice(revenueAmount)
395
- .setEventProperties(updatedAttributes);
396
- getInstance().logRevenueV2(revenue);
397
- } else {
398
- getInstance().logEvent(
399
- expandedEvt.EventName,
400
- updatedAttributes
401
- );
402
- }
418
+ getInstance().logEvent(
419
+ expandedEvt.EventName,
420
+ updatedAttributes
421
+ );
403
422
  });
404
423
 
405
424
  return true;
406
425
  }
407
426
 
427
+ console.warn(
428
+ 'Commerce event does not conform to our expectations and was not forwarded to Amplitude. Please double-check your code.'
429
+ );
430
+
431
+ return false;
432
+ }
433
+
434
+ /*
435
+ When we process a product action event, Amplitude has a very specific way of
436
+ sending events to them:
437
+
438
+ 1. Send a summary event with event attributes from the MP event.
439
+ a. Add a key of `products` with a value of JSON.stringify(productArray).
440
+ b. Add a key of mparticle_amplitude_should_split with a value of `false`.
441
+
442
+ 2. Determine if we send product level events or not.
443
+ a. If includeIndividualProductEvents === true, send product level events
444
+ b. If includeIndividualProductEvents === false, do not send product level events
445
+
446
+ 3. Determine if we send an Amplitude revenue event or not.
447
+ a. If shouldSendSeparateAmplitudeRevenueEvent === true, send an Amplitude revenue event.
448
+ b. If shouldSendSeparateAmplitudeRevenueEvent === true, the summary event attribute should be `revenue`.
449
+ c. If shouldSendSeparateAmplitudeRevenueEvent === false, the summary event attribute should be `$revenue`
450
+
451
+ See test/AmplitudeCommerceEvent.MD for examples of what the expectations of the payload are.
452
+
453
+ */
454
+ function processTemporaryProductAction(
455
+ unexpandedCommerceEvent,
456
+ expandedEvents
457
+ ) {
458
+ var summaryEvent, isRefund, isPurchase, isMPRevenueEvent;
459
+
460
+ isRefund =
461
+ unexpandedCommerceEvent.ProductAction.ProductActionType ===
462
+ mParticle.ProductActionType.Refund;
463
+ isPurchase =
464
+ unexpandedCommerceEvent.ProductAction.ProductActionType ===
465
+ mParticle.ProductActionType.Purchase;
466
+ isMPRevenueEvent = isRefund || isPurchase;
467
+
468
+ // if the event is a revenue event, then we set it to the expanded `Total` event for backwards compatibility
408
469
  if (
470
+ isMPRevenueEvent &&
471
+ expandedEvents[0].EventName.indexOf(TOTAL) > -1
472
+ ) {
473
+ summaryEvent = expandedEvents[0];
474
+ sendMPRevenueSummaryEvent(
475
+ summaryEvent,
476
+ unexpandedCommerceEvent.ProductAction.ProductList,
477
+ isRefund,
478
+ shouldSendSeparateAmplitudeRevenueEvent
479
+ );
480
+ }
481
+
482
+ if (!isMPRevenueEvent) {
483
+ sendSummaryEvent(unexpandedCommerceEvent);
484
+ }
485
+
486
+ if (includeIndividualProductEvents) {
487
+ sendIndividualProductEvents(
488
+ expandedEvents,
489
+ isMPRevenueEvent,
490
+ shouldSendSeparateAmplitudeRevenueEvent,
491
+ isRefund
492
+ );
493
+ }
494
+
495
+ return true;
496
+ }
497
+
498
+ // If event.ProductAction does not exist, the commerce event is a promotion or impression event
499
+ function isNotProductAction(event) {
500
+ return (
409
501
  event.EventCategory ===
410
502
  mParticle.CommerceEventType.ProductImpression ||
411
503
  event.EventCategory === mParticle.CommerceEventType.PromotionView ||
412
504
  event.EventCategory === mParticle.CommerceEventType.PromotionClick
413
- ) {
414
- expandedEvents.forEach(function (expandedEvt) {
415
- // Exclude Totals from the attributes as we log it in the revenue call
416
- var updatedAttributes = createEcommerceAttributes(
505
+ );
506
+ }
507
+
508
+ // this function does not use Amplitude's logRevenueV2, but rather sends custom event names
509
+ function sendMPRevenueSummaryEvent(
510
+ summaryEvent,
511
+ products,
512
+ isRefund,
513
+ shouldSendSeparateAmplitudeRevenueEvent
514
+ ) {
515
+ // send the ecommerce - purchase event
516
+ var updatedAttributes = createMPRevenueEcommerceAttributes(
517
+ summaryEvent.EventAttributes,
518
+ shouldSendSeparateAmplitudeRevenueEvent,
519
+ isRefund
520
+ );
521
+ updatedAttributes[MP_AMP_SPLIT] = false;
522
+
523
+ updatedAttributes[PRODUCTS] = products;
524
+ var revenueEventLabel = isRefund ? REFUND : PURCHASE;
525
+ getInstance().logEvent(
526
+ 'eCommerce - ' + revenueEventLabel,
527
+ updatedAttributes
528
+ );
529
+ }
530
+
531
+ // revenue summary event will either have $price/price or $revenue/revenue depending on if
532
+ function createMPRevenueEcommerceAttributes(
533
+ attributes,
534
+ shouldSendSeparateAmplitudeRevenueEvent,
535
+ isRefund
536
+ ) {
537
+ var updatedAttributes = {};
538
+ for (var key in attributes) {
539
+ if (key === TOTAL_AMOUNT) {
540
+ // A purchase is a positive amount and a refund is negative
541
+ var revenueAmount = attributes[key] * (isRefund ? -1 : 1);
542
+ // If we send a separate Amplitude Revenue Event, Amplitude's
543
+ // SDK prefixes price/revenue with a $ for calculating things
544
+ // like LTV, so we do not want to prepend it as part of the
545
+ // summary event to avoid double counting
546
+ var revenueKey = shouldSendSeparateAmplitudeRevenueEvent
547
+ ? 'revenue'
548
+ : '$revenue';
549
+
550
+ updatedAttributes[revenueKey] = revenueAmount;
551
+ } else if (key !== TOTAL_AMOUNT) {
552
+ updatedAttributes[key] = attributes[key];
553
+ }
554
+ }
555
+
556
+ return convertJsonAttrs(updatedAttributes);
557
+ }
558
+
559
+ function createAttrsForAmplitudeRevenueEvent(attributes) {
560
+ var updatedAttributes = {};
561
+ for (var key in attributes) {
562
+ if (key !== TOTAL_AMOUNT) {
563
+ updatedAttributes[key] = attributes[key];
564
+ }
565
+ }
566
+
567
+ return convertJsonAttrs(updatedAttributes);
568
+ }
569
+
570
+ function sendSummaryEvent(summaryEvent) {
571
+ var updatedAttributes = createEcommerceAttributes(
572
+ summaryEvent.EventAttributes
573
+ );
574
+ updatedAttributes[MP_AMP_SPLIT] = false;
575
+ try {
576
+ updatedAttributes[PRODUCTS] =
577
+ summaryEvent.ProductAction.ProductList;
578
+ } catch (e) {
579
+ console.error('error adding Product List to summary event');
580
+ }
581
+
582
+ getInstance().logEvent(summaryEvent.EventName, updatedAttributes);
583
+ }
584
+
585
+ function sendIndividualProductEvents(
586
+ expandedEvents,
587
+ isMPRevenueEvent,
588
+ shouldSendSeparateAmplitudeRevenueEvent,
589
+ isRefund
590
+ ) {
591
+ expandedEvents.forEach(function (expandedEvt) {
592
+ var updatedAttributes;
593
+ // `Total` exists on an expanded event if it is part of a revenue/purchase event
594
+ // but not on other commerce events. This only needs to be fired if shouldSendSeparateAmplitudeRevenueEvent === True
595
+ if (
596
+ isMPRevenueEvent &&
597
+ // A purchase is a positive amount and a refund is negative
598
+ (expandedEvt.EventName.indexOf(TOTAL) > -1) &
599
+ shouldSendSeparateAmplitudeRevenueEvent
600
+ ) {
601
+ var revenueAmount =
602
+ // A purchase is a positive amount and a refund is negative
603
+ (expandedEvt.EventAttributes[TOTAL_AMOUNT] || 0) *
604
+ (isRefund ? -1 : 1);
605
+ updatedAttributes = createAttrsForAmplitudeRevenueEvent(
417
606
  expandedEvt.EventAttributes
418
607
  );
419
608
 
609
+ var revenue = new window.amplitude.Revenue()
610
+ .setPrice(revenueAmount)
611
+ .setEventProperties(updatedAttributes);
612
+ getInstance().logRevenueV2(revenue);
613
+ } else if (expandedEvt.EventName.indexOf(TOTAL) === -1) {
614
+ updatedAttributes = createEcommerceAttributes(
615
+ expandedEvt.EventAttributes
616
+ );
420
617
  getInstance().logEvent(
421
618
  expandedEvt.EventName,
422
619
  updatedAttributes
423
620
  );
424
- });
425
- return true;
426
- }
427
-
428
- return false;
621
+ }
622
+ });
429
623
  }
430
624
 
431
625
  function convertJsonAttrs(customAttributes) {
@@ -453,6 +647,15 @@ var constructor = function () {
453
647
  forwarderSettings = settings;
454
648
  reportingService = service;
455
649
 
650
+ // Changing this setting from a negative action to a positive action for readability
651
+ includeIndividualProductEvents =
652
+ forwarderSettings.excludeIndividualProductEvents === 'False';
653
+ // Only send separate amplitude revenue events when we includeIndividualProductEvents,
654
+ // so create this variable for clarity
655
+ shouldSendSeparateAmplitudeRevenueEvent = includeIndividualProductEvents;
656
+
657
+ enableTempAmplitudeEcommerce =
658
+ forwarderSettings.enableTempAmplitudeEcommerce === 'True';
456
659
  try {
457
660
  if (!window.amplitude) {
458
661
  if (testMode !== true) {
@@ -505,8 +708,7 @@ var constructor = function () {
505
708
  }
506
709
 
507
710
  if (forwarderSettings.baseUrl) {
508
- ampSettings.apiEndpoint =
509
- forwarderSettings.baseUrl;
711
+ ampSettings.apiEndpoint = forwarderSettings.baseUrl;
510
712
  }
511
713
 
512
714
  isDefaultInstance =
@@ -553,14 +755,14 @@ function register(config) {
553
755
  return;
554
756
  }
555
757
 
556
- if (!isobject$1(config)) {
758
+ if (!isObject(config)) {
557
759
  console.log(
558
760
  'The "config" must be an object. You passed in a ' + typeof config
559
761
  );
560
762
  return;
561
763
  }
562
764
 
563
- if (isobject$1(config.kits)) {
765
+ if (isObject(config.kits)) {
564
766
  config.kits[name] = {
565
767
  constructor: constructor,
566
768
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-amplitude-kit",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "author": "mParticle Developers <developers@mparticle.com> (https://www.mparticle.com)",
5
5
  "description": "mParticle integration sdk for Amplitude",
6
6
  "main": "dist/Amplitude.common.js",
package/CHANGELOG.md DELETED
@@ -1,45 +0,0 @@
1
- ## Releases
2
-
3
- --
4
- #### 2.1.0 - 2021-08-30
5
-
6
- - feat: Add support for EU Data Center
7
-
8
- #### 2.0.8 - 2021-05-26
9
-
10
- - Generate bundle that was not included in 2.0.7 release
11
-
12
- #### 2.0.7 - 2021-05-26
13
-
14
- - fix: Map impression and promotion events to align with server
15
-
16
- #### 2.0.6 - 2021-04-06
17
-
18
- - feat: Add includeEmailAsUserProperty and no longer set userIdentities as user properties to align with server
19
-
20
- - Previously the web kit set non-customerid user identities as user properties. This was not consistent with the server, and so this functionality has been removed from web SDK v2.
21
-
22
- - build: Update eslint/prettier config, fix linting errors
23
-
24
- #### 2.0.5 - 2021-01-11
25
-
26
- - Update Amplitude SDK to 7.2.1
27
- - Bugfix - Check window for node environments
28
- - Remove build file from root directory
29
-
30
- #### 2.0.4 - 2020-11-04
31
-
32
- - Bugfix - remove isTesting variable
33
-
34
- #### 2.0.3 - 2020-06-30
35
-
36
- - Feat: Support sending objects as custom attributes to Amplitude
37
-
38
- #### 2.0.2 - 2020-06-03
39
-
40
- - Update Amplitude SDK version to 6.2.0
41
- - Update test configuration
42
-
43
- #### 2.0.1 - 2020-02-03
44
-
45
- - Modify rollup settings - build dist files