diff --git a/snippet.js b/snippet.js index 8fb19f2b5..b31ca3fe8 100644 --- a/snippet.js +++ b/snippet.js @@ -43,7 +43,7 @@ 'startTrackingLocation', 'stopTrackingLocation', ]; - var ecommerceMethods = ['setCurrencyCode', 'logCheckout']; + var ecommerceMethods = ['setCurrencyCode']; var identityMethods = ['identify', 'login', 'logout', 'modify']; var roktMethods = [ 'selectPlacements', diff --git a/snippet.rokt.js b/snippet.rokt.js index d2bc84407..a3d536fdc 100644 --- a/snippet.rokt.js +++ b/snippet.rokt.js @@ -43,7 +43,7 @@ 'startTrackingLocation', 'stopTrackingLocation', ]; - var ecommerceMethods = ['setCurrencyCode', 'logCheckout']; + var ecommerceMethods = ['setCurrencyCode']; var identityMethods = ['identify', 'login', 'logout', 'modify']; var roktMethods = [ 'selectPlacements', diff --git a/src/constants.ts b/src/constants.ts index 3072e9bee..38c85d00d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,8 +25,6 @@ const Constants = { PromotionIdRequired: 'Promotion ID is required', BadAttribute: 'Attribute value cannot be object or array', BadKey: 'Key value cannot be object or array', - BadLogPurchase: - 'Transaction attributes and a product are both required to log a purchase, https://docs.mparticle.com/?javascript#measuring-transactions', AudienceAPINotEnabled: 'Your workspace is not enabled to retrieve user audiences.', }, diff --git a/src/ecommerce.interfaces.ts b/src/ecommerce.interfaces.ts index 053f848c0..89cb34e70 100644 --- a/src/ecommerce.interfaces.ts +++ b/src/ecommerce.interfaces.ts @@ -64,12 +64,6 @@ export interface SDKCart { // Used for the public `eCommerce` namespace export interface SDKECommerceAPI extends IECommerceShared { - logCheckout( - step: number, - option?: string, - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; logImpression( impression: SDKProductImpression, attrs?: SDKEventAttrs, @@ -98,27 +92,6 @@ export interface SDKECommerceAPI extends IECommerceShared { */ Cart: SDKCart; - /* - * @deprecated - */ - logPurchase( - transactionAttributes: TransactionAttributes, - product: SDKProduct | SDKProduct[], - clearCart?: boolean, - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; - - /* - * @deprecated - */ - logRefund( - transactionAttributes: TransactionAttributes, - product: SDKProduct | SDKProduct[], - clearCart?: boolean, - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; } interface ExtractedActionAttributes { diff --git a/src/events.interfaces.ts b/src/events.interfaces.ts index 0674e47a8..5c36fca67 100644 --- a/src/events.interfaces.ts +++ b/src/events.interfaces.ts @@ -27,17 +27,6 @@ export interface IEvents { eventType: valueof ): void; logAST(): void; - logCheckoutEvent( - step: number, - - // User options specified during the checkout process - // e.g., FedEx, DHL, UPS for delivery options; - // Visa, MasterCard, AmEx for payment options. - option?: string, - - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; logCommerceEvent( commerceEvent: SDKEvent, attrs?: SDKEventAttrs, @@ -66,18 +55,6 @@ export interface IEvents { customFlags?: SDKEventCustomFlags, eventOptions?: SDKEventOptions ): void; - logPurchaseEvent( - transactionAttributes: TransactionAttributes, - product: SDKProduct | SDKProduct[], - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; - logRefundEvent( - transactionAttributes: TransactionAttributes, - product: SDKProduct | SDKProduct[], - attrs?: SDKEventAttrs, - customFlags?: SDKEventCustomFlags - ): void; startTracking(callback: Callback): void; stopTracking(): void; } diff --git a/src/events.js b/src/events.js index 73969b5df..fb916c90e 100644 --- a/src/events.js +++ b/src/events.js @@ -99,27 +99,6 @@ export default function Events(mpInstance) { self.logEvent({ messageType: Types.MessageType.AppStateTransition }); }; - this.logCheckoutEvent = function(step, option, attrs, customFlags) { - var event = mpInstance._Ecommerce.createCommerceEventObject( - customFlags - ); - - if (event) { - event.EventName += mpInstance._Ecommerce.getProductActionEventName( - Types.ProductActionType.Checkout - ); - event.EventCategory = Types.CommerceEventType.ProductCheckout; - event.ProductAction = { - ProductActionType: Types.ProductActionType.Checkout, - CheckoutStep: step, - CheckoutOptions: option, - ProductList: [], - }; - - self.logCommerceEvent(event, attrs); - } - }; - this.logProductActionEvent = function( productActionType, product, @@ -185,75 +164,6 @@ export default function Events(mpInstance) { } }; - this.logPurchaseEvent = function( - transactionAttributes, - product, - attrs, - customFlags - ) { - var event = mpInstance._Ecommerce.createCommerceEventObject( - customFlags - ); - - if (event) { - event.EventName += mpInstance._Ecommerce.getProductActionEventName( - Types.ProductActionType.Purchase - ); - event.EventCategory = Types.CommerceEventType.ProductPurchase; - event.ProductAction = { - ProductActionType: Types.ProductActionType.Purchase, - }; - event.ProductAction.ProductList = mpInstance._Ecommerce.buildProductList( - event, - product - ); - - mpInstance._Ecommerce.convertTransactionAttributesToProductAction( - transactionAttributes, - event.ProductAction - ); - - self.logCommerceEvent(event, attrs); - } - }; - - this.logRefundEvent = function( - transactionAttributes, - product, - attrs, - customFlags - ) { - if (!transactionAttributes) { - mpInstance.Logger.error(Messages.ErrorMessages.TransactionRequired); - return; - } - - var event = mpInstance._Ecommerce.createCommerceEventObject( - customFlags - ); - - if (event) { - event.EventName += mpInstance._Ecommerce.getProductActionEventName( - Types.ProductActionType.Refund - ); - event.EventCategory = Types.CommerceEventType.ProductRefund; - event.ProductAction = { - ProductActionType: Types.ProductActionType.Refund, - }; - event.ProductAction.ProductList = mpInstance._Ecommerce.buildProductList( - event, - product - ); - - mpInstance._Ecommerce.convertTransactionAttributesToProductAction( - transactionAttributes, - event.ProductAction - ); - - self.logCommerceEvent(event, attrs); - } - }; - this.logPromotionEvent = function( promotionType, promotion, diff --git a/src/mp-instance.ts b/src/mp-instance.ts index 6322b28af..ee07942ef 100644 --- a/src/mp-instance.ts +++ b/src/mp-instance.ts @@ -921,37 +921,6 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan tax ); }, - /** - * Logs a checkout action - * @for mParticle.eCommerce - * @method logCheckout - * @param {Number} step checkout step number - * @param {String} checkout option string - * @param {Object} attrs - * @param {Object} [customFlags] Custom flags for the event - * @deprecated - */ - logCheckout: function(step, option, attrs, customFlags) { - self.Logger.warning( - 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead' - ); - - if (!self._Store.isInitialized) { - self.ready(function() { - self.eCommerce.logCheckout( - step, - option, - attrs, - customFlags - ); - }); - - return; - } - - self._SessionManager.resetSessionTimer(); - self._Events.logCheckoutEvent(step, option, attrs, customFlags); - }, /** * Logs a product action * @for mParticle.eCommerce @@ -994,51 +963,6 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan eventOptions ); }, - /** - * Logs a product purchase - * @for mParticle.eCommerce - * @method logPurchase - * @param {Object} transactionAttributes transactionAttributes object - * @param {Object} product the product being purchased - * @param {Boolean} [clearCart] boolean to clear the cart after logging or not. Defaults to false - * @param {Object} [attrs] other attributes related to the product purchase - * @param {Object} [customFlags] Custom flags for the event - * @deprecated - */ - logPurchase: function( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ) { - self.Logger.warning( - 'mParticle.logPurchase is deprecated, please use mParticle.logProductAction instead' - ); - if (!self._Store.isInitialized) { - self.ready(function() { - self.eCommerce.logPurchase( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ); - }); - return; - } - if (!transactionAttributes || !product) { - self.Logger.error(Messages.ErrorMessages.BadLogPurchase); - return; - } - self._SessionManager.resetSessionTimer(); - self._Events.logPurchaseEvent( - transactionAttributes, - product, - attrs, - customFlags - ); - }, /** * Logs a product promotion * @for mParticle.eCommerce @@ -1106,47 +1030,6 @@ export default function mParticleInstance(this: IMParticleWebSDKInstance, instan eventOptions ); }, - /** - * Logs a refund - * @for mParticle.eCommerce - * @method logRefund - * @param {Object} transactionAttributes transaction attributes related to the refund - * @param {Object} product product being refunded - * @param {Boolean} [clearCart] boolean to clear the cart after refund is logged. Defaults to false. - * @param {Object} [attrs] attributes related to the refund - * @param {Object} [customFlags] Custom flags for the event - * @deprecated - */ - logRefund: function( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ) { - self.Logger.warning( - 'mParticle.logRefund is deprecated, please use mParticle.logProductAction instead' - ); - if (!self._Store.isInitialized) { - self.ready(function() { - self.eCommerce.logRefund( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ); - }); - return; - } - self._SessionManager.resetSessionTimer(); - self._Events.logRefundEvent( - transactionAttributes, - product, - attrs, - customFlags - ); - }, expandCommerceEvent: function(event) { return self._Ecommerce.expandCommerceEvent(event); }, diff --git a/src/mparticle-instance-manager.ts b/src/mparticle-instance-manager.ts index 82cd9b0cf..9c189f507 100644 --- a/src/mparticle-instance-manager.ts +++ b/src/mparticle-instance-manager.ts @@ -268,14 +268,6 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) { tax ); }, - logCheckout: function(step, options, attrs, customFlags) { - self.getInstance().eCommerce.logCheckout( - step, - options, - attrs, - customFlags - ); - }, logProductAction: function( productActionType, product, @@ -293,21 +285,6 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) { eventOptions ); }, - logPurchase: function( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ) { - self.getInstance().eCommerce.logPurchase( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ); - }, logPromotion: function( type, promotion, @@ -331,21 +308,6 @@ function mParticleInstanceManager(this: IMParticleInstanceManager) { eventOptions ); }, - logRefund: function( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ) { - self.getInstance().eCommerce.logRefund( - transactionAttributes, - product, - clearCart, - attrs, - customFlags - ); - }, expandCommerceEvent: function(event) { return self.getInstance().eCommerce.expandCommerceEvent(event); }, diff --git a/src/stub/mparticle.stub.js b/src/stub/mparticle.stub.js index 237e4ac23..7a73bb2e2 100644 --- a/src/stub/mparticle.stub.js +++ b/src/stub/mparticle.stub.js @@ -33,12 +33,9 @@ let mParticle = { createProduct: returnProduct, createPromotion: returnPromotion, createTransactionAttributes: returnTransactionAttributes, - logCheckout: voidFunction, logImpression: voidFunction, logProductAction: voidFunction, logPromotion: voidFunction, - logPurchase: voidFunction, - logRefund: voidFunction, setCurrencyCode: voidFunction, Cart: new Cart(), }, diff --git a/test/snippet/tests-snippet.js b/test/snippet/tests-snippet.js index de678fffe..d06b62ff5 100644 --- a/test/snippet/tests-snippet.js +++ b/test/snippet/tests-snippet.js @@ -103,19 +103,8 @@ describe('snippet', function() { it('mParticle object should proxy eCommerce methods', function(done) { mParticle.eCommerce.setCurrencyCode('usd'); - mParticle.eCommerce.logCheckout( - 1, - { optionFoo: 'optionBar' }, - { attrFoo: 'attrBar' }, - { customFoo: 'customBar' } - ); mParticle.config.rq[0][0].should.equal('eCommerce.setCurrencyCode'); mParticle.config.rq[0][1].should.equal('usd'); - mParticle.config.rq[1][0].should.equal('eCommerce.logCheckout'); - mParticle.config.rq[1][1].should.equal(1); - mParticle.config.rq[1][2].optionFoo.should.equal('optionBar'); - mParticle.config.rq[1][3].attrFoo.should.equal('attrBar'); - mParticle.config.rq[1][4].customFoo.should.equal('customBar'); done(); }); diff --git a/test/src/tests-core-sdk.js b/test/src/tests-core-sdk.js index 43515cfc8..6eb263fb4 100644 --- a/test/src/tests-core-sdk.js +++ b/test/src/tests-core-sdk.js @@ -278,40 +278,12 @@ describe('core SDK', function() { product.Attributes.should.not.have.property('invalid'); product.Attributes.should.have.property('valid'); - fetchMock.resetHistory(); - mParticle.eCommerce.logCheckout(1, 'visa', attrs); - const checkoutEvent = findEventFromRequest(fetchMock.calls(), 'checkout'); - - checkoutEvent.data.custom_attributes.should.not.have.property('invalid'); - checkoutEvent.data.custom_attributes.should.have.property('valid'); - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, product, attrs); const addToCartEvent = findEventFromRequest(fetchMock.calls(), 'add_to_cart'); addToCartEvent.data.custom_attributes.should.not.have.property('invalid'); addToCartEvent.data.custom_attributes.should.have.property('valid'); - const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( - '12345', - 'test-affiliation', - 'coupon-code', - 44334, - 600, - 200 - ); - - fetchMock.resetHistory(); - - mParticle.eCommerce.logPurchase( - transactionAttributes, - product, - false, - attrs - ); - const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); - purchaseEvent.data.custom_attributes.should.not.have.property('invalid'); - purchaseEvent.data.custom_attributes.should.have.property('valid'); - const promotion = mParticle.eCommerce.createPromotion( 'id', 'creative', @@ -326,18 +298,6 @@ describe('core SDK', function() { promotionViewEvent.data.custom_attributes.should.not.have.property('invalid'); promotionViewEvent.data.custom_attributes.should.have.property('valid'); - fetchMock.resetHistory(); - - mParticle.eCommerce.logRefund( - transactionAttributes, - product, - false, - attrs - ); - const refundEvent = findEventFromRequest(fetchMock.calls(), 'refund'); - - refundEvent.data.custom_attributes.should.not.have.property('invalid'); - refundEvent.data.custom_attributes.should.have.property('valid'); }); it('should not generate a new device ID if a deviceId exists in localStorage', async () => { diff --git a/test/src/tests-eCommerce.js b/test/src/tests-eCommerce.js index 78d951b83..726e02515 100644 --- a/test/src/tests-eCommerce.js +++ b/test/src/tests-eCommerce.js @@ -60,7 +60,7 @@ describe('eCommerce', function() { transactionAttributes.should.have.property('Tax', 200); }); - it('should log ecommerce event', async () => { + it('should log ecommerce purchase event', async () => { await waitForCondition(hasIdentifyReturned); const product = mParticle.eCommerce.createProduct( 'iPhone', @@ -83,7 +83,13 @@ describe('eCommerce', function() { 200 ); - mParticle.eCommerce.logPurchase(transactionAttributes, product); + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + product, + {}, + {}, + transactionAttributes + ); const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); @@ -127,7 +133,7 @@ describe('eCommerce', function() { fetchMock.calls().length.should.equal(0); }); - it('should log badly formed ecommerce event', async () => { + it('should log badly formed ecommerce purchase event', async () => { const product = mParticle.eCommerce.createProduct( 'iPhone', '12345', @@ -150,7 +156,13 @@ describe('eCommerce', function() { ); await waitForCondition(hasIdentifyReturned); - mParticle.eCommerce.logPurchase(transactionAttributes, product); + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + product, + {}, + {}, + transactionAttributes + ); const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); @@ -179,64 +191,59 @@ describe('eCommerce', function() { purchaseEvent.data.product_action.products[0].custom_attributes.should.have.property('customkey', 'customvalue'); }); - it('should log identical events for logPurchase and logProductAction with product action type of `purchase`', async () => { + it('should log ecommerce refund event', async () => { + await waitForCondition(hasIdentifyReturned); const product = mParticle.eCommerce.createProduct( - 'iPhone', - '12345', - '400', - 2, - 'Plus', - 'Phones', - 'Apple', - 1, - 'my-coupon-code', - { customkey: 'customvalue' } - ), - transactionAttributes = mParticle.eCommerce.createTransactionAttributes( - '12345', - 'test-affiliation', - 'coupon-code', - 44334, - 600, - 200 - ); + 'iPhone', + '12345', + 400, + 2, + 'Apple', + 'Plus', + 'Phones' + ), + transactionAttributes = mParticle.eCommerce.createTransactionAttributes( + '12345', + 'test-affiliation', + 'coupon-code', + 44334, + 600, + 200 + ); - await waitForCondition(hasIdentifyReturned); - mParticle.eCommerce.logPurchase(transactionAttributes, product); - const purchaseEvent1 = findEventFromRequest(fetchMock.calls(), 'purchase'); - - fetchMock.resetHistory(); - - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Purchase, product, null, null, transactionAttributes) - const purchaseEvent2 = findEventFromRequest(fetchMock.calls(), 'purchase'); - - const { product_action: productAction1 } = purchaseEvent1.data; - const { product_action: productAction2 } = purchaseEvent2.data - - productAction1.action.should.equal(productAction2.action); - productAction1.transaction_id.should.equal(productAction2.transaction_id); - productAction1.affiliation.should.equal(productAction2.affiliation); - productAction1.coupon_code.should.equal(productAction2.coupon_code); - productAction1.total_amount.should.equal(productAction2.total_amount); - productAction1.shipping_amount.should.equal(productAction2.shipping_amount); - productAction1.tax_amount.should.equal(productAction2.tax_amount); - productAction1.products.length.should.equal(productAction2.products.length); - - productAction1.products[0].name.should.equal(productAction2.products[0].name); - productAction1.products[0].id.should.equal(productAction2.products[0].id); - productAction1.products[0].price.should.equal(productAction2.products[0].price); - productAction1.products[0].quantity.should.equal(productAction2.products[0].quantity); - productAction1.products[0].brand.should.equal(productAction2.products[0].brand); - productAction1.products[0].variant.should.equal(productAction2.products[0].variant); - productAction1.products[0].category.should.equal(productAction2.products[0].category); - productAction1.products[0].position.should.equal(productAction2.products[0].position); - - productAction1.products[0].coupon_code.should.equal(productAction2.products[0].coupon_code); - productAction1.products[0].total_product_amount.should.equal(productAction2.products[0].total_product_amount); - productAction1.products[0].custom_attributes.customkey.should.equal(productAction2.products[0].custom_attributes.customkey); + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Refund, + product, + {}, + {}, + transactionAttributes + ); + + const refundEvent = findEventFromRequest(fetchMock.calls(), 'refund'); + + Should(refundEvent).be.ok(); + + refundEvent.data.should.have.property('product_action'); + + refundEvent.data.product_action.should.have.property('action', 'refund'); + refundEvent.data.product_action.should.have.property('transaction_id', '12345'); + refundEvent.data.product_action.should.have.property('affiliation', 'test-affiliation'); + refundEvent.data.product_action.should.have.property('coupon_code', 'coupon-code'); + refundEvent.data.product_action.should.have.property('total_amount', 44334); + refundEvent.data.product_action.should.have.property('shipping_amount', 600); + refundEvent.data.product_action.should.have.property('tax_amount', 200); + refundEvent.data.product_action.products.should.have.length(1); + refundEvent.data.product_action.products[0].should.have.property('id', '12345'); + refundEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); + refundEvent.data.product_action.products[0].should.have.property('price', 400); + refundEvent.data.product_action.products[0].should.have.property('quantity', 2); + refundEvent.data.product_action.products[0].should.have.property('brand', 'Phones'); + refundEvent.data.product_action.products[0].should.have.property('variant', 'Apple'); + refundEvent.data.product_action.products[0].should.have.property('category', 'Plus'); + refundEvent.data.product_action.products[0].should.have.property('total_product_amount', 800); }); - it('logPurchase should support array of products', async () => { + it('logProductAction should support array of products for purchase', async () => { const product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1), transactionAttributes = mParticle.eCommerce.createTransactionAttributes( @@ -244,10 +251,13 @@ describe('eCommerce', function() { ); await waitForCondition(hasIdentifyReturned); - mParticle.eCommerce.logPurchase(transactionAttributes, [ - product1, - product2, - ]); + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + [product1, product2], + {}, + {}, + transactionAttributes + ); const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); @@ -257,21 +267,21 @@ describe('eCommerce', function() { purchaseEvent.data.product_action.products[1].should.have.property('name', 'Android'); }); - it('logRefund should support array of products', async () => { + it('logProductAction should support array of products for refund', async () => { const product1 = mParticle.eCommerce.createProduct('iPhone', 'SKU1', 1), product2 = mParticle.eCommerce.createProduct('Android', 'SKU2', 1), transactionAttributes = mParticle.eCommerce.createTransactionAttributes( '12345' ); - await waitForCondition(hasIdentifyReturned); - mParticle.eCommerce.logRefund(transactionAttributes, [ - product1, - product2, - ]); - + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Refund, + [product1, product2], + {}, + {}, + transactionAttributes + ); const refundEvent = findEventFromRequest(fetchMock.calls(), 'refund'); - refundEvent.data.should.have.property('product_action'); refundEvent.data.product_action.should.have.property('products').with.lengthOf(2); refundEvent.data.product_action.products[0].should.have.property('name', 'iPhone'); @@ -458,107 +468,6 @@ describe('eCommerce', function() { impressionEvent.data.product_impressions[1].products[0].should.have.property('id', '23456'); }); - it('should log ecommerce refund', async () => { - await waitForCondition(hasIdentifyReturned); - const product = mParticle.eCommerce.createProduct( - 'iPhone', - '12345', - 400, - 2, - 'Apple', - 'Plus', - 'Phones' - ), - transactionAttributes = mParticle.eCommerce.createTransactionAttributes( - '12345', - 'test-affiliation', - 'coupon-code', - 44334, - 600, - 200 - ); - - mParticle.eCommerce.logRefund(transactionAttributes, product); - - - const refundEvent = findEventFromRequest(fetchMock.calls(), 'refund'); - - Should(refundEvent).be.ok(); - - refundEvent.data.should.have.property('product_action'); - - refundEvent.data.product_action.should.have.property('action', 'refund'); - refundEvent.data.product_action.should.have.property('transaction_id', '12345'); - refundEvent.data.product_action.should.have.property('affiliation', 'test-affiliation'); - refundEvent.data.product_action.should.have.property('coupon_code', 'coupon-code'); - refundEvent.data.product_action.should.have.property('total_amount', 44334); - refundEvent.data.product_action.should.have.property('shipping_amount', 600); - refundEvent.data.product_action.should.have.property('tax_amount', 200); - refundEvent.data.product_action.products.should.have.length(1); - refundEvent.data.product_action.products[0].should.have.property('id', '12345') - refundEvent.data.product_action.products[0].should.have.property('name', 'iPhone') - refundEvent.data.product_action.products[0].should.have.property('price', 400) - refundEvent.data.product_action.products[0].should.have.property('quantity', 2) - refundEvent.data.product_action.products[0].should.have.property('brand', 'Phones') - refundEvent.data.product_action.products[0].should.have.property('variant', 'Apple') - refundEvent.data.product_action.products[0].should.have.property('category', 'Plus') - refundEvent.data.product_action.products[0].should.have.property('total_product_amount', 800) - }); - - it('should log identical events for logRefund and logProductAction with a product action of `refund`', async () => { - await waitForCondition(hasIdentifyReturned); - const product = mParticle.eCommerce.createProduct( - 'iPhone', - '12345', - '400', - 2, - 'Plus', - 'Phones', - 'Apple', - 1, - 'my-coupon-code', - { customkey: 'customvalue' } - ), - transactionAttributes = mParticle.eCommerce.createTransactionAttributes( - '12345', - 'test-affiliation', - 'coupon-code', - 44334, - 600, - 200 - ); - - mParticle.eCommerce.logRefund(transactionAttributes, product); - - const refundEvent1 = findEventFromRequest(fetchMock.calls(), 'refund'); - - fetchMock.resetHistory(); - - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Refund, product, null, null, transactionAttributes) - - const refundEvent2 = findEventFromRequest(fetchMock.calls(), 'refund'); - - Should(refundEvent1).be.ok(); - Should(refundEvent2).be.ok(); - - refundEvent1.data.product_action.action.should.equal(refundEvent2.data.product_action.action); - refundEvent1.data.product_action.transaction_id.should.equal(refundEvent2.data.product_action.transaction_id); - refundEvent1.data.product_action.affiliation.should.equal(refundEvent2.data.product_action.affiliation); - refundEvent1.data.product_action.coupon_code.should.equal(refundEvent2.data.product_action.coupon_code); - refundEvent1.data.product_action.total_amount.should.equal(refundEvent2.data.product_action.total_amount); - refundEvent1.data.product_action.shipping_amount.should.equal(refundEvent2.data.product_action.shipping_amount); - refundEvent1.data.product_action.tax_amount.should.equal(refundEvent2.data.product_action.tax_amount); - refundEvent1.data.product_action.products.length.should.equal(refundEvent2.data.product_action.products.length) - - refundEvent1.data.product_action.products[0].id.should.equal(refundEvent2.data.product_action.products[0].id) - refundEvent1.data.product_action.products[0].price.should.equal(refundEvent2.data.product_action.products[0].price) - refundEvent1.data.product_action.products[0].quantity.should.equal(refundEvent2.data.product_action.products[0].quantity) - refundEvent1.data.product_action.products[0].brand.should.equal(refundEvent2.data.product_action.products[0].brand) - refundEvent1.data.product_action.products[0].variant.should.equal(refundEvent2.data.product_action.products[0].variant) - refundEvent1.data.product_action.products[0].category.should.equal(refundEvent2.data.product_action.products[0].category) - refundEvent1.data.product_action.products[0].position.should.equal(refundEvent2.data.product_action.products[0].position) - }); - it('should allow a product action to bypass server upload', async () => { await waitForCondition(hasIdentifyReturned); const product = mParticle.eCommerce.createProduct( @@ -596,28 +505,6 @@ describe('eCommerce', function() { Should(event).not.be.ok(); }); - it('should log checkout via deprecated logCheckout method', async () => { - await waitForCondition(hasIdentifyReturned); - const bond = sinon.spy(mParticle.getInstance().Logger, 'warning'); - - mParticle.eCommerce.logCheckout(1, 'Visa'); - - const checkoutEvent = findEventFromRequest(fetchMock.calls(), 'checkout'); - - Should(checkoutEvent).be.ok(); - - bond.called.should.eql(true); - bond.getCalls()[0].args[0].should.eql( - 'mParticle.logCheckout is deprecated, please use mParticle.logProductAction instead' - ); - - checkoutEvent.should.have.property('event_type', 'commerce_event'); - checkoutEvent.data.should.have.property('product_action'); - - checkoutEvent.data.product_action.should.have.property('action', 'checkout'); - checkoutEvent.data.product_action.should.have.property('checkout_step', 1); - checkoutEvent.data.product_action.should.have.property('checkout_options', 'Visa'); - }); it('should log checkout via mParticle.logProductAction method', async () => { await waitForCondition(hasIdentifyReturned); @@ -756,20 +643,25 @@ describe('eCommerce', function() { 200 ); - mParticle.eCommerce.logPurchase(transactionAttributes, product); + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, + product, + {}, + {}, + transactionAttributes + ); const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); - purchaseEvent.data.product_action.products[0].should.not.have.property('position'); }); - it('expand product purchase commerce event', async () => { + // Purchase actions generate a plus-one "Total" summary event plus per-product "Item" events + it('expand commerce event with summary total (purchase action)', async () => { await waitForCondition(hasIdentifyReturned); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); window.mParticle.config.kitConfigs.push(config1); - - + mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { return ( @@ -805,11 +697,12 @@ describe('eCommerce', function() { 10, 8 ); - mParticle.eCommerce.logPurchase( - transactionAttributes, + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, product, - false, - eventAttributes + eventAttributes, + {}, + transactionAttributes ); window.MockForwarder1.instance.receivedEvent.should.have.property( 'ProductAction' @@ -870,8 +763,9 @@ describe('eCommerce', function() { 'foo-product-attribute-value' ); }); - - it('expand product refund commerce event', async () => { + + // Refund actions also generate a plus-one "Total" summary event plus per-product "Item" events + it('expand commerce event with summary total (refund action)', async () => { await waitForCondition(hasIdentifyReturned); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -913,11 +807,13 @@ describe('eCommerce', function() { 10, 8 ); - mParticle.eCommerce.logRefund( - transactionAttributes, + + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Refund, product, - false, - eventAttributes + eventAttributes, + {}, + transactionAttributes ); window.MockForwarder1.instance.receivedEvent.should.have.property( 'ProductAction' @@ -932,73 +828,38 @@ describe('eCommerce', function() { 'EventName', 'eCommerce - refund - Total' ); - const attributes = plusOneEvent.EventAttributes; + plusOneEvent.should.have.property( + 'EventCategory', + mParticle.EventType.Transaction + ); + let attributes = plusOneEvent.EventAttributes; + attributes.should.have.property('Transaction Id', 'foo-transaction-id'); + attributes.should.have.property('Affiliation', 'foo-affiliation'); + attributes.should.have.property('Coupon Code', 'foo-couponcode'); + attributes.should.have.property('Total Amount', 400); + attributes.should.have.property('Shipping Amount', 10); attributes.should.have.property('Product Count', 1); + attributes.should.have.property('Tax Amount', 8); + attributes.should.have.property( + 'foo-event-attribute-key', + 'foo-event-attribute-value' + ); const productEvent = expandedEvents[1]; productEvent.should.have.property( 'EventName', 'eCommerce - refund - Item' ); - }); - - it('expand non-plus-one-product commerce event', async () => { - await waitForCondition(hasIdentifyReturned); - const mockForwarder = new MockForwarder(); - mockForwarder.register(window.mParticle.config); - const config1 = forwarderDefaultConfiguration('MockForwarder', 1); - window.mParticle.config.kitConfigs.push(config1); - - mParticle.init(apiKey, window.mParticle.config); - await waitForCondition(() => { - return ( - mParticle.getInstance()._Store.identityCallInFlight === false - ); - }); - const productAttributes = {}; - productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; - - const eventAttributes = {}; - eventAttributes['foo-event-attribute-key'] = - 'foo-event-attribute-value'; - - const product = mParticle.eCommerce.createProduct( - 'Foo name', - 'Foo sku', - 100.0, - 4, - 'foo-variant', - 'foo-category', - 'foo-brand', - 5, - 'foo-productcouponcode', - productAttributes - ); - - mParticle.eCommerce.logProductAction( - mParticle.ProductActionType.RemoveFromWishlist, - product, - eventAttributes - ); - window.MockForwarder1.instance.receivedEvent.should.have.property( - 'ProductAction' - ); - const expandedEvents = mParticle.eCommerce.expandCommerceEvent( - window.MockForwarder1.instance.receivedEvent - ); - expandedEvents.should.be.instanceof(Array).and.have.lengthOf(1); - - const productEvent = expandedEvents[0]; - productEvent.should.have.property( - 'EventName', - 'eCommerce - remove_from_wishlist - Item' - ); productEvent.should.have.property( 'EventCategory', mParticle.EventType.Transaction ); - const attributes = productEvent.EventAttributes; - + attributes = productEvent.EventAttributes; + attributes.should.not.have.property('Affiliation'); + attributes.should.not.have.property('Total Amount'); + attributes.should.not.have.property('Shipping Amount'); + attributes.should.not.have.property('Tax Amount'); + attributes.should.have.property('foo-event-attribute-key'); attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); attributes.should.have.property('Brand', 'foo-brand'); attributes.should.have.property('Category', 'foo-category'); @@ -1013,7 +874,15 @@ describe('eCommerce', function() { ); }); - it('expand checkout commerce event', async () => { + + + + + // "Plus one" (aka "Total") events are summary events generated only for Purchase and Refund + // product actions. They include aggregate attributes like Product Count, Total Amount, etc. + // All other product action types (e.g. AddToCart, RemoveFromWishlist, Checkout) only + // generate per-product "Item" events without a summary "Total" event. + it('expand commerce event without summary total (non-purchase/refund action)', async () => { await waitForCondition(hasIdentifyReturned); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); @@ -1026,15 +895,12 @@ describe('eCommerce', function() { mParticle.getInstance()._Store.identityCallInFlight === false ); }); + const productAttributes = {}; + productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; const eventAttributes = {}; eventAttributes['foo-event-attribute-key'] = 'foo-event-attribute-value'; - eventAttributes['Checkout Step'] = 'foo-step'; - eventAttributes['Checkout Options'] = 'foo-options'; - - const productAttributes = {}; - productAttributes['foo-attribute-key'] = 'foo-product-attribute-value'; const product = mParticle.eCommerce.createProduct( 'Foo name', @@ -1049,14 +915,14 @@ describe('eCommerce', function() { productAttributes ); - mParticle.eCommerce.Cart.add(product, true); - - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.Checkout, [product], eventAttributes); - + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Checkout, + product, + eventAttributes + ); window.MockForwarder1.instance.receivedEvent.should.have.property( 'ProductAction' ); - const expandedEvents = mParticle.eCommerce.expandCommerceEvent( window.MockForwarder1.instance.receivedEvent ); @@ -1073,8 +939,6 @@ describe('eCommerce', function() { ); const attributes = productEvent.EventAttributes; - attributes.should.have.property('Checkout Step', 'foo-step'); - attributes.should.have.property('Checkout Options', 'foo-options'); attributes.should.have.property('Coupon Code', 'foo-productcouponcode'); attributes.should.have.property('Brand', 'foo-brand'); attributes.should.have.property('Category', 'foo-category'); @@ -1089,13 +953,14 @@ describe('eCommerce', function() { ); }); + it('expand promotion commerce event', async () => { await waitForCondition(hasIdentifyReturned); const mockForwarder = new MockForwarder(); mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); window.mParticle.config.kitConfigs.push(config1); - + mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { return ( @@ -1160,7 +1025,7 @@ describe('eCommerce', function() { mockForwarder.register(window.mParticle.config); const config1 = forwarderDefaultConfiguration('MockForwarder', 1); window.mParticle.config.kitConfigs.push(config1); - + mParticle.init(apiKey, window.mParticle.config); await waitForCondition(() => { return ( @@ -1236,13 +1101,6 @@ describe('eCommerce', function() { ); }); - it('should add customFlags to logCheckout events', async () => { - await waitForCondition(hasIdentifyReturned); - mParticle.eCommerce.logCheckout(1, {}, {}, { interactionEvent: true }); - - const checkoutEvent = findEventFromRequest(fetchMock.calls(), 'checkout'); - checkoutEvent.data.custom_flags.interactionEvent.should.equal(true); - }); it('should add customFlags to logProductAction events', async () => { await waitForCondition(hasIdentifyReturned); @@ -1258,7 +1116,8 @@ describe('eCommerce', function() { unknownEvent.data.custom_flags.interactionEvent.should.equal(true); }); - it('should add customFlags to logPurchase events', async () => { + + it('should add customFlags to purchase events', async () => { await waitForCondition(hasIdentifyReturned); const product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( @@ -1266,19 +1125,19 @@ describe('eCommerce', function() { 'affil1', 'couponCode1' ); - mParticle.eCommerce.logPurchase( - transactionAttributes, + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, product, - true, { shipping: 5 }, - { interactionEvent: true } + { interactionEvent: true }, + transactionAttributes ); const purchaseEvent = findEventFromRequest(fetchMock.calls(), 'purchase'); - purchaseEvent.data.custom_flags.interactionEvent.should.equal(true); }); + it('should add customFlags to logPromotion events', async () => { await waitForCondition(hasIdentifyReturned); const promotion = mParticle.eCommerce.createPromotion( @@ -1317,25 +1176,6 @@ describe('eCommerce', function() { impressionEvent.data.custom_flags.interactionEvent.should.equal(true); }); - it('should add customFlags to logRefund events', async () => { - await waitForCondition(hasIdentifyReturned); - const product = mParticle.eCommerce.createProduct('iPhone', 'sku1', 499); - const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( - 'id1', - 'affil1', - 'couponCode1' - ); - mParticle.eCommerce.logRefund( - transactionAttributes, - product, - true, - { shipping: 5 }, - { interactionEvent: true } - ); - const refundEvent = findEventFromRequest(fetchMock.calls(), 'refund'); - - refundEvent.data.custom_flags.interactionEvent.should.equal(true); - }); describe('Cart', function() { afterEach(function() { sinon.restore(); diff --git a/test/src/tests-mparticle-instance-manager.ts b/test/src/tests-mparticle-instance-manager.ts index abddf2322..dd9cf728a 100644 --- a/test/src/tests-mparticle-instance-manager.ts +++ b/test/src/tests-mparticle-instance-manager.ts @@ -141,12 +141,9 @@ describe('mParticle instance manager', () => { 'createPromotion', 'createImpression', 'createTransactionAttributes', - 'logCheckout', 'logProductAction', - 'logPurchase', 'logPromotion', 'logImpression', - 'logRefund', 'expandCommerceEvent', ]); expect(mParticle.Consent, 'Consent').to.have.keys([ @@ -419,7 +416,7 @@ describe('mParticle instance manager', () => { mParticle .getInstance() - .eCommerce.logPurchase(ta, [product1, product2]); + .eCommerce.logProductAction(mParticle.ProductActionType.Purchase, [product1, product2], {}, {}, ta); let instance1Event, instance2Event, instance3Event; @@ -437,7 +434,7 @@ describe('mParticle instance manager', () => { mParticle .getInstance('instance2') - .eCommerce.logPurchase(ta, [product1, product2]); + .eCommerce.logProductAction(mParticle.ProductActionType.Purchase, [product1, product2], {}, {}, ta); await waitForCondition(() => { instance2Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey2', 'purchase'); @@ -450,7 +447,7 @@ describe('mParticle instance manager', () => { mParticle .getInstance('instance3') - .eCommerce.logPurchase(ta, [product1, product2]); + .eCommerce.logProductAction(mParticle.ProductActionType.Purchase, [product1, product2], {}, {}, ta); await waitForCondition(() => { instance3Event = returnEventForMPInstance(fetchMock.calls(), 'apiKey3', 'purchase'); diff --git a/test/src/tests-native-sdk.js b/test/src/tests-native-sdk.js index 5cc8d703d..28e3e10df 100644 --- a/test/src/tests-native-sdk.js +++ b/test/src/tests-native-sdk.js @@ -726,7 +726,7 @@ describe('native-sdk methods', function() { ).EventName.should.equal('test'); }); - it('should send an event with a product list when calling logPurchase', () => { + it('should send an event with a product list when calling logProductAction with Purchase', () => { const product = mParticle.eCommerce.createProduct( 'product1', 'sku', @@ -740,8 +740,6 @@ describe('native-sdk methods', function() { 1 ); - mParticle.eCommerce.Cart.add([product, product2]); - const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( 'TAid1', 'aff1', @@ -750,16 +748,15 @@ describe('native-sdk methods', function() { 10, 5 ); - const clearCartBoolean = true; const customAttributes = { value: 10 }; const customFlags = { foo: 'bar' }; mParticleAndroidV2Bridge.data = []; - mParticle.eCommerce.logPurchase( - transactionAttributes, + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, [product, product2], - clearCartBoolean, customAttributes, - customFlags + customFlags, + transactionAttributes ); JSON.parse( @@ -1071,7 +1068,7 @@ describe('native-sdk methods', function() { }); - it('should send an event with a product list when calling logPurchase', () => { + it('should send an event with a product list when calling logProductAction with Purchase', () => { const product = mParticle.eCommerce.createProduct( 'product1', 'sku', @@ -1084,7 +1081,6 @@ describe('native-sdk methods', function() { 10, 1 ); - mParticle.eCommerce.logProductAction(mParticle.ProductActionType.AddToCart, [product, product2]); const transactionAttributes = mParticle.eCommerce.createTransactionAttributes( 'TAid1', @@ -1094,16 +1090,15 @@ describe('native-sdk methods', function() { 10, 5 ); - const clearCartBoolean = true; const customAttributes = { value: 10 }; const customFlags = { foo: 'bar' }; mParticleIOSV2Bridge.data = []; - mParticle.eCommerce.logPurchase( - transactionAttributes, + mParticle.eCommerce.logProductAction( + mParticle.ProductActionType.Purchase, [product, product2], - clearCartBoolean, customAttributes, - customFlags + customFlags, + transactionAttributes ); JSON.parse(mParticleIOSV2Bridge.data[0]).path.should.equal( diff --git a/test/stub/tests-mParticle-stub.js b/test/stub/tests-mParticle-stub.js index ee85da019..516b22f5f 100644 --- a/test/stub/tests-mParticle-stub.js +++ b/test/stub/tests-mParticle-stub.js @@ -53,12 +53,9 @@ describe('mParticle stubs', function() { transactionAttributes.Shipping.should.equal('shipping'); transactionAttributes.Tax.should.equal(0); - mParticle.eCommerce.logCheckout(); mParticle.eCommerce.logImpression(); mParticle.eCommerce.logProductAction(); mParticle.eCommerce.logPromotion(); - mParticle.eCommerce.logPurchase(); - mParticle.eCommerce.logRefund(); mParticle.eCommerce.setCurrencyCode(); var product1 = mParticle.eCommerce.createProduct(