From c045f8bcaf5d3e212b0bacf37019c4effc92bf56 Mon Sep 17 00:00:00 2001 From: Caleb Cox Date: Wed, 20 Dec 2023 09:16:23 -0500 Subject: [PATCH 1/3] Migrate add_to_cart, remove_from_cart, and view_item to GA4 --- src/app/analytics/analytics.factory.js | 28 ++++---- src/app/analytics/analytics.factory.spec.js | 75 ++++++++++----------- 2 files changed, 50 insertions(+), 53 deletions(-) diff --git a/src/app/analytics/analytics.factory.js b/src/app/analytics/analytics.factory.js index a53c7ce1b..3c14d54df 100644 --- a/src/app/analytics/analytics.factory.js +++ b/src/app/analytics/analytics.factory.js @@ -216,15 +216,14 @@ const analyticsFactory = /* @ngInject */ function ($window, $timeout, envService // Send GTM Advance Ecommerce event $window.dataLayer = $window.dataLayer || [] $window.dataLayer.push({ - event: 'add-to-cart', + event: 'add_to_cart', ecommerce: { currencyCode: 'USD', - add: { - products: [generateProduct(productData, { - price: itemConfig.AMOUNT, - recurringDate - })] - } + value: itemConfig.AMOUNT.toFixed(2), + items: [generateProduct(productData, { + price: itemConfig.AMOUNT, + recurringDate + })] } }) }), @@ -251,12 +250,11 @@ const analyticsFactory = /* @ngInject */ function ($window, $timeout, envService // Send GTM Advance Ecommerce event $window.dataLayer = $window.dataLayer || [] $window.dataLayer.push({ - event: 'remove-from-cart', + event: 'remove_from_cart', ecommerce: { currencyCode: 'USD', - remove: { - products: [generateProduct(item)] - } + value: item.amount.toFixed(2), + items: [generateProduct(item)] } }) }), @@ -448,12 +446,12 @@ const analyticsFactory = /* @ngInject */ function ($window, $timeout, envService $window.digitalData.product = product $window.dataLayer = $window.dataLayer || [] $window.dataLayer.push({ - event: 'give-gift-modal', + event: 'view_item', ecommerce: { currencyCode: 'USD', - detail: { - products: [generateProduct(modifiedProductData)] - } + // value is unavailable until the user selects a gift amount + value: undefined, + items: [generateProduct(modifiedProductData)] } }) this.setEvent('give gift modal') diff --git a/src/app/analytics/analytics.factory.spec.js b/src/app/analytics/analytics.factory.spec.js index d4e033e0c..1c4fd6102 100644 --- a/src/app/analytics/analytics.factory.spec.js +++ b/src/app/analytics/analytics.factory.spec.js @@ -113,8 +113,9 @@ describe('analytics factory', () => { self.analyticsFactory.cartAdd(itemConfig, productData) expect(self.$window.dataLayer.length).toEqual(1) - expect(self.$window.dataLayer[0].event).toEqual('add-to-cart') - expect(self.$window.dataLayer[0].ecommerce.add.products[0]).toEqual({ + expect(self.$window.dataLayer[0].event).toEqual('add_to_cart') + expect(self.$window.dataLayer[0].ecommerce.value).toEqual(itemConfig.AMOUNT.toFixed(2)) + expect(self.$window.dataLayer[0].ecommerce.items[0]).toEqual({ item_id: productData.code, item_name: productData.displayName, item_brand: productData.orgId, @@ -134,8 +135,9 @@ describe('analytics factory', () => { self.analyticsFactory.cartAdd(itemConfig, productData) expect(self.$window.dataLayer.length).toEqual(1) - expect(self.$window.dataLayer[0].event).toEqual('add-to-cart') - expect(self.$window.dataLayer[0].ecommerce.add.products[0]).toEqual({ + expect(self.$window.dataLayer[0].event).toEqual('add_to_cart') + expect(self.$window.dataLayer[0].ecommerce.value).toEqual(itemConfig.AMOUNT.toFixed(2)) + expect(self.$window.dataLayer[0].ecommerce.items[0]).toEqual({ item_id: productData.code, item_name: productData.displayName, item_brand: productData.orgId, @@ -260,22 +262,21 @@ describe('analytics factory', () => { }) expect(self.$window.digitalData.cart.item.length).toEqual(1) - expect(self.$window.dataLayer[0].event).toEqual('remove-from-cart') + expect(self.$window.dataLayer[0].event).toEqual('remove_from_cart') expect(self.$window.dataLayer[0].ecommerce).toEqual({ currencyCode: 'USD', - remove: { - products: [{ - item_id: item.designationNumber, - item_name: item.displayName, - item_brand: item.orgId, - item_category: item.designationType.toLowerCase(), - item_variant: 'monthly', - currency: 'USD', - price: item.amount.toString(), - quantity: '1', - recurring_date: 'September 15, 2024' - }] - } + value: item.amount.toFixed(2), + items: [{ + item_id: item.designationNumber, + item_name: item.displayName, + item_brand: item.orgId, + item_category: item.designationType.toLowerCase(), + item_variant: 'monthly', + currency: 'USD', + price: item.amount.toString(), + quantity: '1', + recurring_date: 'September 15, 2024' + }] }) }); }); @@ -364,7 +365,7 @@ describe('analytics factory', () => { it('should create payment info and checkout step DataLayer events', () => { self.analyticsFactory.checkoutStepEvent('payment', cart) - + expect(self.$window.dataLayer.length).toEqual(2) expect(self.$window.dataLayer[0]).toEqual({ event: 'add_payment_info' @@ -386,7 +387,7 @@ describe('analytics factory', () => { it('should create review order and checkout step DataLayer events', () => { self.analyticsFactory.checkoutStepEvent('review', cart) - + expect(self.$window.dataLayer.length).toEqual(2) expect(self.$window.dataLayer[0]).toEqual({ event: 'review_order', @@ -407,7 +408,7 @@ describe('analytics factory', () => { }) }); - describe('checkoutStepOptionEvent', () => { + describe('checkoutStepOptionEvent', () => { it('should add contact checkout option event to DataLayer', () => { self.analyticsFactory.checkoutStepOptionEvent('Household', 'contact') expect(self.$window.dataLayer.length).toEqual(1) @@ -487,25 +488,23 @@ describe('analytics factory', () => { "orgId": "STAFF" } - it('should push give-gift-modal event to the DataLayer', () => { + it('should push view_item event to the DataLayer', () => { self.analyticsFactory.giveGiftModal(productData) expect(self.$window.dataLayer.length).toEqual(1) - expect(self.$window.dataLayer[0].event).toEqual('give-gift-modal') + expect(self.$window.dataLayer[0].event).toEqual('view_item') expect(self.$window.dataLayer[0].ecommerce).toEqual({ currencyCode: 'USD', - detail: { - products: [{ - item_id: '0643021', - item_name: 'International Staff', - item_brand: 'STAFF', - item_category: 'staff', - item_variant: undefined, - price: undefined, - currency: 'USD', - quantity: '1', - recurring_date: undefined, - }] - } + items: [{ + item_id: '0643021', + item_name: 'International Staff', + item_brand: 'STAFF', + item_category: 'staff', + item_variant: undefined, + price: undefined, + currency: 'USD', + quantity: '1', + recurring_date: undefined, + }] }) }); }); @@ -621,7 +620,7 @@ describe('analytics factory', () => { self.analyticsFactory.transactionEvent(purchaseData) expect(self.$window.sessionStorage.getItem('transactionId')).toEqual(purchaseData.rawData['purchase-number']) - + expect(self.$window.dataLayer.length).toEqual(1) expect(self.$window.dataLayer[0].event).toEqual('purchase') expect(self.$window.dataLayer[0].paymentType).toEqual('credit card') @@ -678,7 +677,7 @@ describe('analytics factory', () => { const totalWithFees = 51.2 * 3 const totalWithoutFees = 50 * 3 - + expect(self.$window.dataLayer[0].ecommerce.processing_fee).toEqual((totalWithFees - totalWithoutFees).toFixed(2)) expect(self.$window.dataLayer[0].ecommerce.value).toEqual((totalWithFees).toFixed(2)) expect(self.$window.dataLayer[0].ecommerce.pays_processing).toEqual('yes') From db46df50a626d43f572123cf2ab1fccbaa45fe86 Mon Sep 17 00:00:00 2001 From: Caleb Cox Date: Wed, 20 Dec 2023 09:45:55 -0500 Subject: [PATCH 2/3] Fix tests sharing state Previously, focusing on cartRemove would cause those tests to fail because it was relying on cartAdd or buildProductVar to initialize digitalData --- src/app/analytics/analytics.factory.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/analytics/analytics.factory.spec.js b/src/app/analytics/analytics.factory.spec.js index 1c4fd6102..c4d70b42f 100644 --- a/src/app/analytics/analytics.factory.spec.js +++ b/src/app/analytics/analytics.factory.spec.js @@ -11,6 +11,7 @@ describe('analytics factory', () => { self.analyticsFactory = analyticsFactory self.envService = envService self.$window = $window + self.$window.digitalData = { cart: {} } self.$window.dataLayer = [] self.$window.sessionStorage.clear() From 562258c8e0703cbbe6ada975d60a02de100ed441 Mon Sep 17 00:00:00 2001 From: Caleb Cox Date: Wed, 20 Dec 2023 14:42:11 -0500 Subject: [PATCH 3/3] Make testing_transaction "false" instead of undefined --- src/app/analytics/analytics.factory.js | 5 +-- src/app/analytics/analytics.factory.spec.js | 41 ++++++++++++--------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/app/analytics/analytics.factory.js b/src/app/analytics/analytics.factory.js index 3c14d54df..312973bdb 100644 --- a/src/app/analytics/analytics.factory.js +++ b/src/app/analytics/analytics.factory.js @@ -30,9 +30,8 @@ function testingTransactionName (item) { // Generate a datalayer product object const generateProduct = suppressErrors(function (item, additionalData = {}) { const sessionStorageTestName = testingTransactionName(item) - const testingTransaction = sessionStorageTestName - ? window.sessionStorage.getItem(sessionStorageTestName) || undefined - : undefined + const testingTransaction = Boolean(sessionStorageTestName && + window.sessionStorage.getItem(sessionStorageTestName) === 'true').toString() const price = additionalData?.price || item.amount const category = additionalData?.category || item.designationType const name = additionalData?.name || item.displayName || undefined diff --git a/src/app/analytics/analytics.factory.spec.js b/src/app/analytics/analytics.factory.spec.js index c4d70b42f..cd0179df5 100644 --- a/src/app/analytics/analytics.factory.spec.js +++ b/src/app/analytics/analytics.factory.spec.js @@ -125,7 +125,8 @@ describe('analytics factory', () => { currency: 'USD', price: itemConfig.AMOUNT.toString(), quantity: '1', - recurring_date: 'September 13, 2023' + recurring_date: 'September 13, 2023', + testing_transaction: 'false', }) }); @@ -147,7 +148,8 @@ describe('analytics factory', () => { currency: 'USD', price: itemConfig.AMOUNT.toString(), quantity: '1', - recurring_date: undefined + recurring_date: undefined, + testing_transaction: 'false', }) }) }); @@ -276,7 +278,8 @@ describe('analytics factory', () => { currency: 'USD', price: item.amount.toString(), quantity: '1', - recurring_date: 'September 15, 2024' + recurring_date: 'September 15, 2024', + testing_transaction: 'false', }] }) }); @@ -336,7 +339,8 @@ describe('analytics factory', () => { currency: 'USD', price: item.amount.toString(), quantity: '1', - recurring_date: undefined + recurring_date: undefined, + testing_transaction: 'false', } it('should create begining checkout and checkout step DataLayer events', () => { @@ -495,17 +499,19 @@ describe('analytics factory', () => { expect(self.$window.dataLayer[0].event).toEqual('view_item') expect(self.$window.dataLayer[0].ecommerce).toEqual({ currencyCode: 'USD', - items: [{ - item_id: '0643021', - item_name: 'International Staff', - item_brand: 'STAFF', - item_category: 'staff', - item_variant: undefined, - price: undefined, - currency: 'USD', - quantity: '1', - recurring_date: undefined, - }] + value: undefined, + items: [{ + item_id: '0643021', + item_name: 'International Staff', + item_brand: 'STAFF', + item_category: 'staff', + item_variant: undefined, + price: undefined, + currency: 'USD', + quantity: '1', + recurring_date: undefined, + testing_transaction: 'false', + }] }) }); }); @@ -546,7 +552,8 @@ describe('analytics factory', () => { currency: 'USD', quantity: '1', recurring_date: undefined, - } + testing_transaction: 'false', + } ] } }) @@ -652,7 +659,7 @@ describe('analytics factory', () => { designation: 'designation', item_brand: 'STAFF', processingFee: undefined, - + testing_transaction: 'false', } ] })