@@ -407,19 +407,9 @@ Appboy.prototype.orderCompleted = function(track) {
407
407
del ( purchaseProperties , 'currency' ) ;
408
408
409
409
// we have to make a separate call to appboy for each product
410
- each ( function ( product ) {
411
- var track = new Track ( { properties : product } ) ;
412
- var productId = track . productId ( ) ;
413
- var price = track . price ( ) ;
414
- var quantity = track . quantity ( ) ;
415
- window . appboy . logPurchase (
416
- productId ,
417
- price ,
418
- currencyCode ,
419
- quantity ,
420
- purchaseProperties
421
- ) ;
422
- } , products ) ;
410
+ for ( var i = 0 ; i < products . length ; i ++ ) {
411
+ logProduct ( products [ i ] , currencyCode , purchaseProperties ) ;
412
+ }
423
413
} ;
424
414
425
415
/**
@@ -449,3 +439,92 @@ function getGender(gender) {
449
439
if ( otherGenders . indexOf ( gender . toLowerCase ( ) ) > - 1 )
450
440
return window . appboy . ab . User . Genders . OTHER ;
451
441
}
442
+
443
+ /**
444
+ * Logs a Purchase containing a product as described in Braze's documentation:
445
+ * https://js.appboycdn.com/web-sdk/latest/doc/module-appboy.html#.logPurchase
446
+ *
447
+ * @param {Object } product Product from the Order Completed call
448
+ * @param {String } currencyCode Currency code
449
+ * @param {Object } extraProperties Root properties from the track call
450
+ */
451
+ function logProduct ( product , currencyCode , extraProperties ) {
452
+ var track = new Track ( { properties : product } ) ;
453
+ var productId = track . productId ( ) ;
454
+ var price = track . price ( ) ;
455
+ var quantity = track . quantity ( ) ;
456
+ var productProperties = track . properties ( ) ;
457
+ var properties = { } ;
458
+
459
+ del ( productProperties , 'productId' ) ;
460
+ del ( productProperties , 'price' ) ;
461
+ del ( productProperties , 'quantity' ) ;
462
+
463
+ for ( var productProperty in productProperties ) {
464
+ if ( ! productProperties . hasOwnProperty ( productProperty ) ) {
465
+ continue ;
466
+ }
467
+
468
+ var value = productProperties [ productProperty ] ;
469
+ if ( isValidProperty ( productProperty , value ) ) {
470
+ properties [ productProperty ] = value ;
471
+ }
472
+ }
473
+
474
+ for ( var property in extraProperties ) {
475
+ if ( ! extraProperties . hasOwnProperty ( property ) ) {
476
+ continue ;
477
+ }
478
+
479
+ var val = extraProperties [ property ] ;
480
+ if (
481
+ ! productProperties . hasOwnProperty ( property ) &&
482
+ isValidProperty ( property , val )
483
+ ) {
484
+ properties [ property ] = val ;
485
+ }
486
+ }
487
+
488
+ window . appboy . logPurchase (
489
+ productId ,
490
+ price ,
491
+ currencyCode ,
492
+ quantity ,
493
+ properties
494
+ ) ;
495
+ }
496
+
497
+ /**
498
+ * Validates a name and value of a property, following Braze's restrictions:
499
+ *
500
+ * Names are limited to 255 characters in length, cannot begin with a $, and
501
+ * can only contain alphanumeric characters and punctuation. Values can be
502
+ * numeric, boolean, Date objects, or strings 255 characters or shorter.
503
+ *
504
+ * @param {String } name Name of the property.
505
+ * @param {* } value Value of the property.
506
+ *
507
+ * @return {boolean } <code>true</code> if the name and value are valid, <code>false</code> otherwise.
508
+ */
509
+ function isValidProperty ( name , value ) {
510
+ if ( name . length > 255 || name . startsWith ( '$' ) ) {
511
+ return false ;
512
+ }
513
+
514
+ if ( typeof value === 'number' || typeof value === 'boolean' ) {
515
+ return true ;
516
+ }
517
+
518
+ if ( typeof value === 'object' && value instanceof Date ) {
519
+ return true ;
520
+ }
521
+
522
+ if (
523
+ ( typeof value === 'string' || value instanceof String ) &&
524
+ value . length <= 255
525
+ ) {
526
+ return true ;
527
+ }
528
+
529
+ return false ;
530
+ }
0 commit comments