Skip to content

Commit 90508fe

Browse files
authored
[DEST-698][CC-4865] Add product properties to Order Completed for Braze (#145)
* [DEST-698][CC-4865] Add product properties to Order Completed * Add validation of properties * Version 1.10.0
1 parent 4a8223a commit 90508fe

File tree

3 files changed

+113
-18
lines changed

3 files changed

+113
-18
lines changed

integrations/appboy/lib/index.js

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -407,19 +407,9 @@ Appboy.prototype.orderCompleted = function(track) {
407407
del(purchaseProperties, 'currency');
408408

409409
// 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+
}
423413
};
424414

425415
/**
@@ -449,3 +439,92 @@ function getGender(gender) {
449439
if (otherGenders.indexOf(gender.toLowerCase()) > -1)
450440
return window.appboy.ab.User.Genders.OTHER;
451441
}
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+
}

integrations/appboy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@segment/analytics.js-integration-appboy",
33
"description": "The Appboy analytics.js integration.",
4-
"version": "1.9.0",
4+
"version": "1.10.0",
55
"keywords": [
66
"analytics.js",
77
"analytics.js-integration",

integrations/appboy/test/index.test.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,27 +440,34 @@ describe('Appboy', function() {
440440
});
441441

442442
it('should call logPurchase for each product in a Completed Order event', function() {
443+
var today = new Date();
444+
443445
analytics.track('Order Completed', {
444446
total: 30,
445447
revenue: 25,
446448
shipping: 3,
447449
currency: 'USD',
450+
date: today,
451+
invalidPropertyLength: 'a'.repeat(500),
448452
products: [
449453
{
450454
product_id: '507f1f77bcf86cd799439011',
451455
sku: '45790-32',
452456
name: 'Monopoly: 3rd Edition',
453457
price: 19.23,
454458
quantity: 1,
455-
category: 'Games'
459+
category: 'Games',
460+
$invalidPropertyName: 3,
461+
invalidPropertyValue: ['red', 'blue']
456462
},
457463
{
458464
product_id: '505bd76785ebb509fc183733',
459465
sku: '46493-32',
460466
name: 'Uno Card Game',
461467
price: 3,
462468
quantity: 2,
463-
category: 'Games'
469+
category: 'Games',
470+
size: 6
464471
}
465472
]
466473
});
@@ -473,7 +480,11 @@ describe('Appboy', function() {
473480
{
474481
total: 30,
475482
revenue: 25,
476-
shipping: 3
483+
shipping: 3,
484+
sku: '45790-32',
485+
name: 'Monopoly: 3rd Edition',
486+
category: 'Games',
487+
date: today
477488
}
478489
);
479490
analytics.called(
@@ -485,7 +496,12 @@ describe('Appboy', function() {
485496
{
486497
total: 30,
487498
revenue: 25,
488-
shipping: 3
499+
shipping: 3,
500+
sku: '46493-32',
501+
name: 'Uno Card Game',
502+
category: 'Games',
503+
size: 6,
504+
date: today
489505
}
490506
);
491507
});

0 commit comments

Comments
 (0)