@mparticle/web-facebook-kit 2.3.0 → 3.2.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.
@@ -20,486 +20,585 @@ function getCjsExportFromNamespace (n) {
20
20
 
21
21
  var isobject$1 = getCjsExportFromNamespace(isobject);
22
22
 
23
- /* eslint-disable no-undef */
24
- // Copyright 2015 mParticle, Inc.
25
- //
26
- // Licensed under the Apache License, Version 2.0 (the "License");
27
- // you may not use this file except in compliance with the License.
28
- // You may obtain a copy of the License at
29
- //
30
- // http://www.apache.org/licenses/LICENSE-2.0
31
- //
32
- // Unless required by applicable law or agreed to in writing, software
33
- // distributed under the License is distributed on an "AS IS" BASIS,
34
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35
- // See the License for the specific language governing permissions and
36
- // limitations under the License.
37
-
38
-
39
- var name = 'Facebook',
40
- moduleId = 45,
41
- MessageType = {
42
- SessionStart: 1,
43
- SessionEnd: 2,
44
- PageView: 3,
45
- PageEvent: 4,
46
- CrashReport: 5,
47
- OptOut: 6,
48
- Commerce: 16,
49
- },
50
- IdentityType = {
51
- Other: 0,
52
- CustomerId: 1,
53
- Facebook: 2,
54
- Twitter: 3,
55
- Google: 4,
56
- Microsoft: 5,
57
- Yahoo: 6,
58
- Email: 7,
59
- FacebookCustomAudienceId: 9,
60
- Other2: 10,
61
- Other3: 11,
62
- Other4: 12,
63
- Other5: 13,
64
- Other6: 14,
65
- Other7: 15,
66
- Other8: 16,
67
- Other9: 17,
68
- Other10: 18,
69
- MobileNumber: 19,
70
- PhoneNumber2: 20,
71
- PhoneNumber3: 21,
72
- },
73
- SupportedCommerceTypes = [],
74
- // Standard FB Event Names from https://developers.facebook.com/docs/facebook-pixel/reference#standard-events
75
- ADD_TO_CART_EVENT_NAME = 'AddToCart',
76
- ADD_TO_WISHLIST_EVENT_NAME = 'AddToWishlist',
77
- CHECKOUT_EVENT_NAME = 'InitiateCheckout',
78
- PAGE_VIEW_EVENT_NAME = 'PageView',
79
- PURCHASE_EVENT_NAME = 'Purchase',
80
- REMOVE_FROM_CART_EVENT_NAME = 'RemoveFromCart',
81
- VIEW_CONTENT_EVENT_NAME = 'ViewContent',
82
- constructor = function () {
83
- var self = this,
84
- isInitialized = false,
85
- reportingService = null,
86
- settings,
87
- productAttributeMapping;
88
-
89
- self.name = name;
90
-
91
- function initForwarder(forwarderSettings, service, testMode, trackerId, userAttributes, userIdentities) {
92
- settings = forwarderSettings;
93
- reportingService = service;
94
-
95
- SupportedCommerceTypes = [
96
- mParticle.ProductActionType.Checkout,
97
- mParticle.ProductActionType.Purchase,
98
- mParticle.ProductActionType.AddToCart,
99
- mParticle.ProductActionType.RemoveFromCart,
100
- mParticle.ProductActionType.AddToWishlist,
101
- mParticle.ProductActionType.ViewDetail
102
- ];
103
-
104
- try {
105
- if (!testMode) {
106
- !function (f, b, e, v, n, t, s) {
107
- if (f.fbq) return; n = f.fbq = function () { n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments); }; if (!f._fbq) f._fbq = n;
108
- n.push = n; n.loaded = !0; n.version = '2.0'; n.queue = []; t = b.createElement(e); t.async = !0; t.src = v; s = b.getElementsByTagName(e)[0];
109
- s.parentNode.insertBefore(t, s);
110
- } (window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
111
-
112
- var visitorData = {};
113
-
114
- if(settings.externalUserIdentityType && userIdentities && userIdentities.length > 0) {
115
- var selectedType = IdentityType[settings.externalUserIdentityType];
116
- var selectedIdentity = userIdentities.filter(function (identityElement) {
117
- if (identityElement.Type === selectedType) {
118
- return identityElement.Identity;
119
- }
120
- });
121
-
122
- if (selectedIdentity.length > 0) {
123
- visitorData['external_id'] = selectedIdentity[0].Identity;
124
- }
125
- }
126
- }
127
-
128
- if (settings.disablePushState === 'True') {
129
- // Facebook will automatically track page views whenever a new state is pushed to the HTML 5 History State API
130
- // this option can be disabled to prevent duplicate page views
131
- // https://developers.facebook.com/docs/facebook-pixel/implementation/tag_spa/#tagging-single-page-applications
132
- fbq.disablePushState = true;
133
- }
134
- fbq('init', settings.pixelId, visitorData);
135
-
136
- loadMappings();
137
-
138
- isInitialized = true;
139
-
140
- return 'Successfully initialized: ' + name;
141
-
142
- }
143
- catch (e) {
144
- return 'Can\'t initialize forwarder: ' + name + ':' + e;
145
- }
146
- }
147
-
148
- function loadMappings() {
149
- productAttributeMapping = settings.productAttributeMapping
150
- ? JSON.parse(settings.productAttributeMapping.replace(/"/g, '"'))
151
- : [];
152
- }
153
-
154
- function processEvent(event) {
155
- var reportEvent = false;
156
-
157
- if (!isInitialized) {
158
- return 'Can\'t send forwarder ' + name + ', not initialized';
159
- }
160
-
161
- try {
162
- if (event.EventDataType == MessageType.PageView) {
163
- reportEvent = true;
164
- logPageView(event);
165
- }
166
- else if (event.EventDataType == MessageType.PageEvent) {
167
- reportEvent = true;
168
- logPageEvent(event);
169
- }
170
- else if (event.EventDataType == MessageType.Commerce) {
171
- reportEvent = logCommerceEvent(event);
172
- }
173
-
174
- if (reportEvent && reportingService) {
175
- reportingService(self, event);
176
- }
177
-
178
- return 'Successfully sent to forwarder ' + name;
179
- }
180
- catch (error) {
181
- return 'Can\'t send to forwarder: ' + name + ' ' + error;
182
- }
183
- }
184
-
185
- function logCommerceEvent(event) {
186
- if (event.ProductAction &&
187
- event.ProductAction.ProductList &&
188
- event.ProductAction.ProductActionType &&
189
- SupportedCommerceTypes.indexOf(event.ProductAction.ProductActionType) > -1) {
190
- var eventName,
191
- totalValue,
192
- params = cloneEventAttributes(event),
193
- eventID = createEventId(event),
194
- sendProductNamesAsContents = settings.sendProductNamesasContents || false;
195
-
196
- params['currency'] = event.CurrencyCode || 'USD';
197
-
198
- if (event.EventName) {
199
- params['content_name'] = event.EventName;
200
- }
201
-
202
- var productSkus = event.ProductAction.ProductList.reduce(function (arr, curr) {
203
- if (curr.Sku) {
204
- arr.push(curr.Sku);
205
- }
206
- return arr;
207
- }, []);
208
-
209
- if (productSkus && productSkus.length > 0) {
210
- params['content_ids'] = productSkus;
211
- }
212
-
213
- // Override content_name with product names array if setting enabled
214
- if (sendProductNamesAsContents) {
215
- var productNames = buildProductNames(event.ProductAction.ProductList);
216
- if (productNames && productNames.length > 0) {
217
- params['content_name'] = productNames;
218
- }
219
- }
220
-
221
- // Set order_id if TransactionId exists
222
- if (event.ProductAction.TransactionId) {
223
- params['order_id'] = event.ProductAction.TransactionId;
224
- }
225
-
226
- // Build contents array
227
- var contents = buildProductContents(event.ProductAction.ProductList);
228
- if (contents && contents.length > 0) {
229
- params['contents'] = contents;
230
- }
231
-
232
- if (event.ProductAction.ProductActionType == mParticle.ProductActionType.AddToWishlist ||
233
- event.ProductAction.ProductActionType == mParticle.ProductActionType.Checkout) {
234
- var eventCategory = getEventCategoryString(event);
235
- if (eventCategory) {
236
- params['content_category'] = eventCategory;
237
- }
238
- if (event.ProductAction.ProductActionType == mParticle.ProductActionType.Checkout && event.ProductAction.CheckoutStep) {
239
- params['checkout_step'] = event.ProductAction.CheckoutStep;
240
- }
241
- }
242
-
243
- if (event.ProductAction.ProductActionType == mParticle.ProductActionType.AddToCart ||
244
- event.ProductAction.ProductActionType == mParticle.ProductActionType.AddToWishlist ||
245
- event.ProductAction.ProductActionType == mParticle.ProductActionType.ViewDetail) {
246
-
247
- totalValue = event.ProductAction.ProductList.reduce(function(sum, product){
248
- if (isNumeric(product.Price) && isNumeric(product.Quantity)) {
249
- sum += product.Price * product.Quantity;
250
- }
251
- return sum;
252
- }, 0);
253
-
254
- params['value'] = totalValue;
255
-
256
- if (event.ProductAction.ProductActionType == mParticle.ProductActionType.AddToWishlist){
257
- eventName = ADD_TO_WISHLIST_EVENT_NAME;
258
- }
259
- else if (event.ProductAction.ProductActionType == mParticle.ProductActionType.AddToCart){
260
- eventName = ADD_TO_CART_EVENT_NAME;
261
- }
262
- else {
263
- eventName = VIEW_CONTENT_EVENT_NAME;
264
- }
265
-
266
- }
267
- else if (event.ProductAction.ProductActionType == mParticle.ProductActionType.Checkout ||
268
- event.ProductAction.ProductActionType == mParticle.ProductActionType.Purchase) {
269
-
270
- eventName = event.ProductAction.ProductActionType == mParticle.ProductActionType.Checkout ? CHECKOUT_EVENT_NAME : PURCHASE_EVENT_NAME;
271
-
272
- if (event.ProductAction.TotalAmount) {
273
- params['value'] = event.ProductAction.TotalAmount;
274
- }
275
-
276
- var num_items = event.ProductAction.ProductList.reduce(function(sum, product){
277
- if (isNumeric(product.Quantity)) {
278
- sum += product.Quantity;
279
- }
280
- return sum;
281
- }, 0);
282
- params['num_items'] = num_items;
283
- }
284
- else if (event.ProductAction.ProductActionType == mParticle.ProductActionType.RemoveFromCart) {
285
- eventName = REMOVE_FROM_CART_EVENT_NAME;
286
-
287
- // remove from cart can be performed in 1 of 2 ways:
288
- // 1. mParticle.eCommerce.logProductEvent(), which contains event.ProductAction.TotalAmount
289
- // 2. mParticle.eCommerce.Cart.remove(), which does not contain event.ProductAction.TotalAmount
290
- // when there is no TotalAmount, a manual calculation must be done
291
- if (event.ProductAction.TotalAmount) {
292
- totalValue = event.ProductAction.TotalAmount;
293
- } else {
294
- totalValue = event.ProductAction.ProductList.reduce(function(sum, product) {
295
- if (isNumeric(product.TotalAmount)) {
296
- sum += product.TotalAmount;
297
- }
298
- return sum;
299
- }, 0);
300
- }
301
-
302
- params['value'] = totalValue;
303
-
304
- fbq('trackCustom', eventName || 'customEvent', params, eventID);
305
- return true;
306
- }
307
-
308
- if (eventName) {
309
- fbq('track', eventName, params, eventID);
310
- }
311
- else {
312
- return false;
313
- }
314
-
315
- return true;
316
- }
317
-
318
- return false;
319
- }
320
-
321
- function logPageView(event) {
322
- logPageEvent(event, PAGE_VIEW_EVENT_NAME);
323
- }
324
-
325
- function logPageEvent(event, eventName) {
326
- var params = cloneEventAttributes(event);
327
- var eventID = createEventId(event);
328
-
329
- eventName = eventName || event.EventName;
330
- if (event.EventName) {
331
- params['content_name'] = event.EventName;
332
- }
333
-
334
- fbq('trackCustom', eventName || 'customEvent', params, eventID);
335
- }
336
-
337
- function cloneEventAttributes(event) {
338
- var attr = {};
339
- if (event && event.EventAttributes) {
340
- try {
341
- attr = JSON.parse(JSON.stringify(event.EventAttributes));
342
- }
343
- catch (e) {
344
- //
345
- }
346
- }
347
- return attr;
348
- }
349
-
350
- function isNumeric(n) {
351
- return !isNaN(parseFloat(n)) && isFinite(n);
352
- }
353
-
354
- function getEventCategoryString(event) {
355
-
356
- var enumTypeValues;
357
- var enumValue;
358
- if (event.EventDataType == MessageType.Commerce) {
359
- enumTypeValues = event.EventCategory ? mParticle.CommerceEventType : mParticle.ProductActionType;
360
- enumValue = event.EventCategory || event.ProductAction.ProductActionType;
361
- }
362
- else {
363
- enumTypeValues = mParticle.EventType;
364
- enumValue = event.EventCategory;
365
- }
366
-
367
- if (enumTypeValues && enumValue) {
368
-
369
- for (var category in enumTypeValues) {
370
- if (enumValue == enumTypeValues[category]) {
371
- return category;
372
- }
373
- }
374
- }
375
-
376
- return null;
377
- }
378
-
379
- /**
380
- * Builds contents array for Facebook Pixel commerce events.
381
- * Creates a nested array of content items with product details.
382
- *
383
- * @param {Array} productList - Array of products from event.ProductAction.ProductList
384
- * @returns {Array} Array of content objects for Facebook Pixel
385
- */
386
- function buildProductContents(productList) {
387
- if (!productList || productList.length === 0) {
388
- return [];
389
- }
390
-
391
- return productList
392
- .filter(function(product) {
393
- return product && product.Sku;
394
- })
395
- .map(function(product) {
396
- var contentItem = {
397
- id: product.Sku,
398
- quantity: isNumeric(product.Quantity) ? product.Quantity : 1,
399
- name: product.Name,
400
- brand: product.Brand,
401
- category: product.Category,
402
- variant: product.Variant,
403
- item_price: isNumeric(product.Price) ? product.Price : null
404
- };
405
-
406
- // Apply configured mappings to custom attributes
407
- productAttributeMapping.forEach(function(productMapping) {
408
- if (!isobject$1(productMapping) || !productMapping.map || !productMapping.value) {
409
- return;
410
- }
411
-
412
- var sourceField = productMapping.map;
413
- var facebookFieldName = productMapping.value;
414
- var value = null;
415
-
416
- // Check for Product level field first
417
- if (product.hasOwnProperty(sourceField)) {
418
- value = product[sourceField];
419
- }
420
- // then check for Product.Attributes level field
421
- else if (product.Attributes && product.Attributes[sourceField]) {
422
- value = product.Attributes[sourceField];
423
- }
424
-
425
- if (value !== null && value !== undefined) {
426
- contentItem[facebookFieldName] = value;
427
- }
428
- });
429
- return contentItem;
430
- });
431
- }
432
-
433
- // https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events#event-deduplication-options
434
- function createEventId(event) {
435
- return {
436
- eventID: event.SourceMessageId || null
437
- }
438
- }
439
-
440
- /**
441
- * Builds array of product names from product list
442
- * @param {Array} productList - Array of products
443
- * @returns {Array} Array of product names
444
- */
445
- function buildProductNames(productList) {
446
- if (!productList || productList.length === 0) {
447
- return [];
448
- }
449
-
450
- return productList
451
- .filter(function(product) {
452
- return product && product.Name;
453
- })
454
- .map(function(product) {
455
- return product.Name;
456
- });
457
- }
458
-
459
- this.init = initForwarder;
460
- this.process = processEvent;
461
- };
462
-
463
- function getId() {
464
- return moduleId;
465
- }
466
-
467
- function register(config) {
468
- if (!config) {
469
- console.log('You must pass a config object to register the kit ' + name);
470
- return;
471
- }
472
-
473
- if (!isobject$1(config)) {
474
- console.log('\'config\' must be an object. You passed in a ' + typeof config);
475
- return;
476
- }
477
-
478
- if (isobject$1(config.kits)) {
479
- config.kits[name] = {
480
- constructor: constructor
481
- };
482
- } else {
483
- config.kits = {};
484
- config.kits[name] = {
485
- constructor: constructor
486
- };
487
- }
488
- console.log('Successfully registered ' + name + ' to your mParticle configuration');
489
- }
490
-
491
- if (typeof window !== 'undefined') {
492
- if (window && window.mParticle && window.mParticle.addForwarder) {
493
- window.mParticle.addForwarder({
494
- name: name,
495
- constructor: constructor,
496
- getId: getId
497
- });
498
- }
499
- }
500
-
501
- var FacebookEventForwarder = {
502
- register: register
23
+ /* eslint-disable no-undef */
24
+ // Copyright 2015 mParticle, Inc.
25
+ //
26
+ // Licensed under the Apache License, Version 2.0 (the "License");
27
+ // you may not use this file except in compliance with the License.
28
+ // You may obtain a copy of the License at
29
+ //
30
+ // http://www.apache.org/licenses/LICENSE-2.0
31
+ //
32
+ // Unless required by applicable law or agreed to in writing, software
33
+ // distributed under the License is distributed on an "AS IS" BASIS,
34
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35
+ // See the License for the specific language governing permissions and
36
+ // limitations under the License.
37
+
38
+
39
+ var name = 'Facebook',
40
+ moduleId = 45,
41
+ MessageType = {
42
+ SessionStart: 1,
43
+ SessionEnd: 2,
44
+ PageView: 3,
45
+ PageEvent: 4,
46
+ CrashReport: 5,
47
+ OptOut: 6,
48
+ Commerce: 16,
49
+ },
50
+ IdentityType = {
51
+ Other: 0,
52
+ CustomerId: 1,
53
+ Facebook: 2,
54
+ Twitter: 3,
55
+ Google: 4,
56
+ Microsoft: 5,
57
+ Yahoo: 6,
58
+ Email: 7,
59
+ FacebookCustomAudienceId: 9,
60
+ Other2: 10,
61
+ Other3: 11,
62
+ Other4: 12,
63
+ Other5: 13,
64
+ Other6: 14,
65
+ Other7: 15,
66
+ Other8: 16,
67
+ Other9: 17,
68
+ Other10: 18,
69
+ MobileNumber: 19,
70
+ PhoneNumber2: 20,
71
+ PhoneNumber3: 21,
72
+ },
73
+ SupportedCommerceTypes = [],
74
+ // Standard FB Event Names from https://developers.facebook.com/docs/facebook-pixel/reference#standard-events
75
+ ADD_TO_CART_EVENT_NAME = 'AddToCart',
76
+ ADD_TO_WISHLIST_EVENT_NAME = 'AddToWishlist',
77
+ CHECKOUT_EVENT_NAME = 'InitiateCheckout',
78
+ PAGE_VIEW_EVENT_NAME = 'PageView',
79
+ PURCHASE_EVENT_NAME = 'Purchase',
80
+ REMOVE_FROM_CART_EVENT_NAME = 'RemoveFromCart',
81
+ VIEW_CONTENT_EVENT_NAME = 'ViewContent',
82
+ constructor = function() {
83
+ var self = this,
84
+ isInitialized = false,
85
+ reportingService = null,
86
+ settings,
87
+ productAttributeMapping;
88
+
89
+ self.name = name;
90
+
91
+ function initForwarder(
92
+ forwarderSettings,
93
+ service,
94
+ testMode,
95
+ trackerId,
96
+ userAttributes,
97
+ userIdentities
98
+ ) {
99
+ settings = forwarderSettings;
100
+ reportingService = service;
101
+
102
+ SupportedCommerceTypes = [
103
+ mParticle.ProductActionType.Checkout,
104
+ mParticle.ProductActionType.Purchase,
105
+ mParticle.ProductActionType.AddToCart,
106
+ mParticle.ProductActionType.RemoveFromCart,
107
+ mParticle.ProductActionType.AddToWishlist,
108
+ mParticle.ProductActionType.ViewDetail,
109
+ ];
110
+
111
+ try {
112
+ if (!testMode) {
113
+ !(function(f, b, e, v, n, t, s) {
114
+ if (f.fbq) return;
115
+ n = f.fbq = function() {
116
+ n.callMethod
117
+ ? n.callMethod.apply(n, arguments)
118
+ : n.queue.push(arguments);
119
+ };
120
+ if (!f._fbq) f._fbq = n;
121
+ n.push = n;
122
+ n.loaded = !0;
123
+ n.version = '2.0';
124
+ n.queue = [];
125
+ t = b.createElement(e);
126
+ t.async = !0;
127
+ t.src = v;
128
+ s = b.getElementsByTagName(e)[0];
129
+ s.parentNode.insertBefore(t, s);
130
+ })(
131
+ window,
132
+ document,
133
+ 'script',
134
+ 'https://connect.facebook.net/en_US/fbevents.js'
135
+ );
136
+
137
+ var visitorData = {};
138
+
139
+ if (
140
+ settings.externalUserIdentityType &&
141
+ userIdentities &&
142
+ userIdentities.length > 0
143
+ ) {
144
+ var selectedType =
145
+ IdentityType[settings.externalUserIdentityType];
146
+ var selectedIdentity = userIdentities.filter(function(
147
+ identityElement
148
+ ) {
149
+ if (identityElement.Type === selectedType) {
150
+ return identityElement.Identity;
151
+ }
152
+ });
153
+
154
+ if (selectedIdentity.length > 0) {
155
+ visitorData['external_id'] =
156
+ selectedIdentity[0].Identity;
157
+ }
158
+ }
159
+ }
160
+
161
+ if (settings.disablePushState === 'True') {
162
+ // Facebook will automatically track page views whenever a new state is pushed to the HTML 5 History State API
163
+ // this option can be disabled to prevent duplicate page views
164
+ // https://developers.facebook.com/docs/facebook-pixel/implementation/tag_spa/#tagging-single-page-applications
165
+ fbq.disablePushState = true;
166
+ }
167
+ fbq('init', settings.pixelId, visitorData);
168
+
169
+ loadMappings();
170
+
171
+ isInitialized = true;
172
+
173
+ return 'Successfully initialized: ' + name;
174
+ } catch (e) {
175
+ return "Can't initialize forwarder: " + name + ':' + e;
176
+ }
177
+ }
178
+
179
+ function loadMappings() {
180
+ productAttributeMapping = settings.productAttributeMapping
181
+ ? JSON.parse(
182
+ settings.productAttributeMapping.replace(/"/g, '"')
183
+ )
184
+ : [];
185
+ }
186
+
187
+ function processEvent(event) {
188
+ var reportEvent = false;
189
+
190
+ if (!isInitialized) {
191
+ return "Can't send forwarder " + name + ', not initialized';
192
+ }
193
+
194
+ try {
195
+ if (event.EventDataType == MessageType.PageView) {
196
+ reportEvent = true;
197
+ logPageView(event);
198
+ } else if (event.EventDataType == MessageType.PageEvent) {
199
+ reportEvent = true;
200
+ logPageEvent(event);
201
+ } else if (event.EventDataType == MessageType.Commerce) {
202
+ reportEvent = logCommerceEvent(event);
203
+ }
204
+
205
+ if (reportEvent && reportingService) {
206
+ reportingService(self, event);
207
+ }
208
+
209
+ return 'Successfully sent to forwarder ' + name;
210
+ } catch (error) {
211
+ return "Can't send to forwarder: " + name + ' ' + error;
212
+ }
213
+ }
214
+
215
+ function logCommerceEvent(event) {
216
+ if (
217
+ event.ProductAction &&
218
+ event.ProductAction.ProductList &&
219
+ event.ProductAction.ProductActionType &&
220
+ SupportedCommerceTypes.indexOf(
221
+ event.ProductAction.ProductActionType
222
+ ) > -1
223
+ ) {
224
+ var eventName,
225
+ totalValue,
226
+ params = cloneEventAttributes(event),
227
+ eventID = createEventId(event),
228
+ sendProductNamesAsContents =
229
+ settings.sendProductNamesasContents || false;
230
+
231
+ params['currency'] = event.CurrencyCode || 'USD';
232
+
233
+ if (event.EventName) {
234
+ params['content_name'] = event.EventName;
235
+ }
236
+
237
+ var productSkus = event.ProductAction.ProductList.reduce(
238
+ function(arr, curr) {
239
+ if (curr.Sku) {
240
+ arr.push(curr.Sku);
241
+ }
242
+ return arr;
243
+ },
244
+ []
245
+ );
246
+
247
+ if (productSkus && productSkus.length > 0) {
248
+ params['content_ids'] = productSkus;
249
+ }
250
+
251
+ // Override content_name with product names array if setting enabled
252
+ if (sendProductNamesAsContents) {
253
+ var productNames = buildProductNames(
254
+ event.ProductAction.ProductList
255
+ );
256
+ if (productNames && productNames.length > 0) {
257
+ params['content_name'] = productNames;
258
+ }
259
+ }
260
+
261
+ // Set order_id if TransactionId exists
262
+ if (event.ProductAction.TransactionId) {
263
+ params['order_id'] = event.ProductAction.TransactionId;
264
+ }
265
+
266
+ // Build contents array
267
+ var contents = buildProductContents(
268
+ event.ProductAction.ProductList
269
+ );
270
+ if (contents && contents.length > 0) {
271
+ params['contents'] = contents;
272
+ }
273
+
274
+ if (
275
+ event.ProductAction.ProductActionType ==
276
+ mParticle.ProductActionType.AddToWishlist ||
277
+ event.ProductAction.ProductActionType ==
278
+ mParticle.ProductActionType.Checkout
279
+ ) {
280
+ var eventCategory = getEventCategoryString(event);
281
+ if (eventCategory) {
282
+ params['content_category'] = eventCategory;
283
+ }
284
+ if (
285
+ event.ProductAction.ProductActionType ==
286
+ mParticle.ProductActionType.Checkout &&
287
+ event.ProductAction.CheckoutStep
288
+ ) {
289
+ params['checkout_step'] =
290
+ event.ProductAction.CheckoutStep;
291
+ }
292
+ }
293
+
294
+ if (
295
+ event.ProductAction.ProductActionType ==
296
+ mParticle.ProductActionType.AddToCart ||
297
+ event.ProductAction.ProductActionType ==
298
+ mParticle.ProductActionType.AddToWishlist ||
299
+ event.ProductAction.ProductActionType ==
300
+ mParticle.ProductActionType.ViewDetail
301
+ ) {
302
+ totalValue = event.ProductAction.ProductList.reduce(
303
+ function(sum, product) {
304
+ if (
305
+ isNumeric(product.Price) &&
306
+ isNumeric(product.Quantity)
307
+ ) {
308
+ sum += product.Price * product.Quantity;
309
+ }
310
+ return sum;
311
+ },
312
+ 0
313
+ );
314
+
315
+ params['value'] = totalValue;
316
+
317
+ if (
318
+ event.ProductAction.ProductActionType ==
319
+ mParticle.ProductActionType.AddToWishlist
320
+ ) {
321
+ eventName = ADD_TO_WISHLIST_EVENT_NAME;
322
+ } else if (
323
+ event.ProductAction.ProductActionType ==
324
+ mParticle.ProductActionType.AddToCart
325
+ ) {
326
+ eventName = ADD_TO_CART_EVENT_NAME;
327
+ } else {
328
+ eventName = VIEW_CONTENT_EVENT_NAME;
329
+ }
330
+ } else if (
331
+ event.ProductAction.ProductActionType ==
332
+ mParticle.ProductActionType.Checkout ||
333
+ event.ProductAction.ProductActionType ==
334
+ mParticle.ProductActionType.Purchase
335
+ ) {
336
+ eventName =
337
+ event.ProductAction.ProductActionType ==
338
+ mParticle.ProductActionType.Checkout
339
+ ? CHECKOUT_EVENT_NAME
340
+ : PURCHASE_EVENT_NAME;
341
+
342
+ if (event.ProductAction.TotalAmount) {
343
+ params['value'] = event.ProductAction.TotalAmount;
344
+ }
345
+
346
+ var num_items = event.ProductAction.ProductList.reduce(
347
+ function(sum, product) {
348
+ if (isNumeric(product.Quantity)) {
349
+ sum += product.Quantity;
350
+ }
351
+ return sum;
352
+ },
353
+ 0
354
+ );
355
+ params['num_items'] = num_items;
356
+ } else if (
357
+ event.ProductAction.ProductActionType ==
358
+ mParticle.ProductActionType.RemoveFromCart
359
+ ) {
360
+ eventName = REMOVE_FROM_CART_EVENT_NAME;
361
+
362
+ // remove from cart can be performed in 1 of 2 ways:
363
+ // 1. mParticle.eCommerce.logProductEvent(), which contains event.ProductAction.TotalAmount
364
+ // 2. mParticle.eCommerce.Cart.remove(), which does not contain event.ProductAction.TotalAmount
365
+ // when there is no TotalAmount, a manual calculation must be done
366
+ if (event.ProductAction.TotalAmount) {
367
+ totalValue = event.ProductAction.TotalAmount;
368
+ } else {
369
+ totalValue = event.ProductAction.ProductList.reduce(
370
+ function(sum, product) {
371
+ if (isNumeric(product.TotalAmount)) {
372
+ sum += product.TotalAmount;
373
+ }
374
+ return sum;
375
+ },
376
+ 0
377
+ );
378
+ }
379
+
380
+ params['value'] = totalValue;
381
+
382
+ fbq(
383
+ 'trackCustom',
384
+ eventName || 'customEvent',
385
+ params,
386
+ eventID
387
+ );
388
+ return true;
389
+ }
390
+
391
+ if (eventName) {
392
+ fbq('track', eventName, params, eventID);
393
+ } else {
394
+ return false;
395
+ }
396
+
397
+ return true;
398
+ }
399
+
400
+ return false;
401
+ }
402
+
403
+ function logPageView(event) {
404
+ logPageEvent(event, PAGE_VIEW_EVENT_NAME);
405
+ }
406
+
407
+ function logPageEvent(event, eventName) {
408
+ var params = cloneEventAttributes(event);
409
+ var eventID = createEventId(event);
410
+
411
+ eventName = eventName || event.EventName;
412
+ if (event.EventName) {
413
+ params['content_name'] = event.EventName;
414
+ }
415
+
416
+ fbq('trackCustom', eventName || 'customEvent', params, eventID);
417
+ }
418
+
419
+ function cloneEventAttributes(event) {
420
+ var attr = {};
421
+ if (event && event.EventAttributes) {
422
+ try {
423
+ attr = JSON.parse(JSON.stringify(event.EventAttributes));
424
+ } catch (e) {
425
+ //
426
+ }
427
+ }
428
+ return attr;
429
+ }
430
+
431
+ function isNumeric(n) {
432
+ return !isNaN(parseFloat(n)) && isFinite(n);
433
+ }
434
+
435
+ function getEventCategoryString(event) {
436
+ var enumTypeValues;
437
+ var enumValue;
438
+ if (event.EventDataType == MessageType.Commerce) {
439
+ enumTypeValues = event.EventCategory
440
+ ? mParticle.CommerceEventType
441
+ : mParticle.ProductActionType;
442
+ enumValue =
443
+ event.EventCategory ||
444
+ event.ProductAction.ProductActionType;
445
+ } else {
446
+ enumTypeValues = mParticle.EventType;
447
+ enumValue = event.EventCategory;
448
+ }
449
+
450
+ if (enumTypeValues && enumValue) {
451
+ for (var category in enumTypeValues) {
452
+ if (enumValue == enumTypeValues[category]) {
453
+ return category;
454
+ }
455
+ }
456
+ }
457
+
458
+ return null;
459
+ }
460
+
461
+ /**
462
+ * Builds contents array for Facebook Pixel commerce events.
463
+ * Creates a nested array of content items with product details.
464
+ *
465
+ * @param {Array} productList - Array of products from event.ProductAction.ProductList
466
+ * @returns {Array} Array of content objects for Facebook Pixel
467
+ */
468
+ function buildProductContents(productList) {
469
+ if (!productList || productList.length === 0) {
470
+ return [];
471
+ }
472
+
473
+ return productList
474
+ .filter(function(product) {
475
+ return product && product.Sku;
476
+ })
477
+ .map(function(product) {
478
+ var contentItem = {
479
+ id: product.Sku,
480
+ quantity: isNumeric(product.Quantity)
481
+ ? product.Quantity
482
+ : 1,
483
+ name: product.Name,
484
+ brand: product.Brand,
485
+ category: product.Category,
486
+ variant: product.Variant,
487
+ item_price: isNumeric(product.Price)
488
+ ? product.Price
489
+ : null,
490
+ };
491
+
492
+ // Apply configured mappings to custom attributes
493
+ productAttributeMapping.forEach(function(productMapping) {
494
+ if (
495
+ !isobject$1(productMapping) ||
496
+ !productMapping.map ||
497
+ !productMapping.value
498
+ ) {
499
+ return;
500
+ }
501
+
502
+ var sourceField = productMapping.map;
503
+ var facebookFieldName = productMapping.value;
504
+ var value = null;
505
+
506
+ // Check for Product level field first
507
+ if (product.hasOwnProperty(sourceField)) {
508
+ value = product[sourceField];
509
+ }
510
+ // then check for Product.Attributes level field
511
+ else if (
512
+ product.Attributes &&
513
+ product.Attributes[sourceField]
514
+ ) {
515
+ value = product.Attributes[sourceField];
516
+ }
517
+
518
+ if (value !== null && value !== undefined) {
519
+ contentItem[facebookFieldName] = value;
520
+ }
521
+ });
522
+ return contentItem;
523
+ });
524
+ }
525
+
526
+ // https://developers.facebook.com/docs/marketing-api/conversions-api/deduplicate-pixel-and-server-events#event-deduplication-options
527
+ function createEventId(event) {
528
+ return {
529
+ eventID: event.SourceMessageId || null,
530
+ };
531
+ }
532
+
533
+ /**
534
+ * Builds array of product names from product list
535
+ * @param {Array} productList - Array of products
536
+ * @returns {Array} Array of product names
537
+ */
538
+ function buildProductNames(productList) {
539
+ if (!productList || productList.length === 0) {
540
+ return [];
541
+ }
542
+
543
+ return productList
544
+ .filter(function(product) {
545
+ return product && product.Name;
546
+ })
547
+ .map(function(product) {
548
+ return product.Name;
549
+ });
550
+ }
551
+
552
+ this.init = initForwarder;
553
+ this.process = processEvent;
554
+ };
555
+
556
+ function getId() {
557
+ return moduleId;
558
+ }
559
+
560
+ function register(config) {
561
+ if (!config) {
562
+ console.log(
563
+ 'You must pass a config object to register the kit ' + name
564
+ );
565
+ return;
566
+ }
567
+
568
+ if (!isobject$1(config)) {
569
+ console.log(
570
+ "'config' must be an object. You passed in a " + typeof config
571
+ );
572
+ return;
573
+ }
574
+
575
+ if (isobject$1(config.kits)) {
576
+ config.kits[name] = {
577
+ constructor: constructor,
578
+ };
579
+ } else {
580
+ config.kits = {};
581
+ config.kits[name] = {
582
+ constructor: constructor,
583
+ };
584
+ }
585
+ console.log(
586
+ 'Successfully registered ' + name + ' to your mParticle configuration'
587
+ );
588
+ }
589
+
590
+ if (typeof window !== 'undefined') {
591
+ if (window && window.mParticle && window.mParticle.addForwarder) {
592
+ window.mParticle.addForwarder({
593
+ name: name,
594
+ constructor: constructor,
595
+ getId: getId,
596
+ });
597
+ }
598
+ }
599
+
600
+ var FacebookEventForwarder = {
601
+ register: register,
503
602
  };
504
603
  var FacebookEventForwarder_1 = FacebookEventForwarder.register;
505
604