From 720b4acd03c526b29852c48d66cf322df9c2a761 Mon Sep 17 00:00:00 2001 From: "Shivam@RS" Date: Fri, 18 Dec 2020 12:05:37 +0530 Subject: [PATCH] review commits fixes 2 --- __tests__/data/GA4_input.js | 70 ++++++++ __tests__/data/GA4_output.js | 28 +++ integrations/GA4/ECommerceEventConfig.js | 1 - integrations/GA4/browser.js | 32 +--- integrations/GA4/utility.js | 209 ++++++++++++----------- integrations/index.js | 10 -- 6 files changed, 221 insertions(+), 129 deletions(-) create mode 100644 __tests__/data/GA4_input.js create mode 100644 __tests__/data/GA4_output.js diff --git a/__tests__/data/GA4_input.js b/__tests__/data/GA4_input.js new file mode 100644 index 0000000000..eedc3d2cf2 --- /dev/null +++ b/__tests__/data/GA4_input.js @@ -0,0 +1,70 @@ +const rudderanalytics = []; + +rudderanalytics.track("Products Searched", { + query: "HDMI cable", +}); + +rudderanalytics.track("Product List Viewed", { + list_id: "list1", + category: "What's New", + products: [ + { + product_id: "223344ffdds3ff3", + sku: "12345", + name: "Just Another Game", + price: 22, + position: 2, + category: "Games and Entertainment", + url: "https://www.myecommercewebsite.com/product", + image_url: "https://www.myecommercewebsite.com/product/path.jpg", + }, + { + product_id: "343344ff5567ff3", + sku: "12346", + name: "Wrestling Trump Cards", + price: 4, + position: 21, + category: "Card Games", + }, + ], +}); + +rudderanalytics.track("Product List Filtered", { + list_id: "dealoftheday", + filters: [ + { + type: "department", + value: "health", + }, + { + type: "price", + value: "under-$75", + }, + ], + sorts: [ + { + type: "price", + value: "asc", + }, + ], + products: [ + { + product_id: "5034221345ffcd672315011", + sku: "12345", + name: "Whey Protein", + price: 55.45, + position: 1, + category: "health", + url: "https://www.myecommercewebsite.com/product/product1123", + image_url: "https://www.example.com/product/1123.jpg", + }, + { + product_id: "121244455323232326677232", + sku: "345667", + name: "Boost", + price: 47.85, + position: 12, + category: "health", + }, + ], +}); diff --git a/__tests__/data/GA4_output.js b/__tests__/data/GA4_output.js new file mode 100644 index 0000000000..ea663e0a0a --- /dev/null +++ b/__tests__/data/GA4_output.js @@ -0,0 +1,28 @@ +const gtag = []; + +gtag("event", "search", { search_term: "HDMI cable" }); + +gtag("event", "view_item_list", { + item_list_id: "list1", + items: [ + { + item_id: "223344ffdds3ff3", + item_name: "Just Another Game", + price: 22, + index: 2, + item_category: "Games and Entertainment", + item_list_id: "list1", + item_list_name: "What's New", + }, + { + item_id: "343344ff5567ff3", + item_name: "Wrestling Trump Cards", + price: 4, + index: 21, + item_category: "Card Games", + item_list_id: "list1", + item_list_name: "What's New", + }, + ], + item_list_name: "What's New", +}); diff --git a/integrations/GA4/ECommerceEventConfig.js b/integrations/GA4/ECommerceEventConfig.js index f04fb83140..a42a16b297 100644 --- a/integrations/GA4/ECommerceEventConfig.js +++ b/integrations/GA4/ECommerceEventConfig.js @@ -62,7 +62,6 @@ const eventParametersConfigArray = [ { src: "affiliation", dest: ["affiliation"] }, { src: "shipping", dest: ["shipping"] }, { src: "tax", dest: ["tax"] }, - { src: "affiliation", dest: ["affiliation"] }, { src: "total", dest: ["value"] }, { src: "checkout_id", dest: ["transaction_id"] }, ]; diff --git a/integrations/GA4/browser.js b/integrations/GA4/browser.js index 16eec66967..fb1e2a225d 100644 --- a/integrations/GA4/browser.js +++ b/integrations/GA4/browser.js @@ -71,19 +71,6 @@ export default class GA4 { } /* utility functions --- Ends here --- */ - getDestinationItemProperties(products, item) { - const items = []; - let obj = {}; - products.forEach((p) => { - obj = { - ...getDestinationEventProperties(p, itemParametersConfigArray), - ...(item && item[0]), - }; - items.push(obj); - }); - return items; - } - track(rudderElement) { let { event } = rudderElement.message; const { properties } = rudderElement.message; @@ -93,10 +80,10 @@ export default class GA4 { throw Error("Cannot call un-named/reserved named track event"); } - const obj = getDestinationEventName(event); - if (obj) { + const eventMappingObj = getDestinationEventName(event); + if (eventMappingObj) { if (products && Array.isArray(products)) { - event = obj.dest; + event = eventMappingObj.dest; // eslint-disable-next-line no-const-assign destinationProperties = getDestinationEventProperties( properties, @@ -107,8 +94,8 @@ export default class GA4 { destinationProperties.items ); } else { - event = obj.dest; - if (!obj.hasItem) { + event = eventMappingObj.dest; + if (!eventMappingObj.hasItem) { // eslint-disable-next-line no-const-assign destinationProperties = getDestinationEventProperties( properties, @@ -139,13 +126,12 @@ export default class GA4 { } page(rudderElement) { - const page = - rudderElement.message.context && rudderElement.message.context.page; - if (!page) return; + const pageProps = rudderElement.message.properties; + if (!pageProps) return; if (this.extendPageViewParams) { - window.gtag("event", "page_view", page); + window.gtag("event", "page_view", pageProps); } else { - window.gtag("event", "page_view", getPageViewProperty(page)); + window.gtag("event", "page_view", getPageViewProperty(pageProps)); } } } diff --git a/integrations/GA4/utility.js b/integrations/GA4/utility.js index 2c7f760606..09db0e91dc 100644 --- a/integrations/GA4/utility.js +++ b/integrations/GA4/utility.js @@ -1,99 +1,118 @@ import { - eventNamesConfigArray, - itemParametersConfigArray, - } from "./ECommerceEventConfig"; - - import { pageEventParametersConfigArray } from "./PageEventConfig"; - - function isReservedName(name) { - const reservedEventNames = [ - "ad_activeview", - "ad_click", - "ad_exposure", - "ad_impression", - "ad_query", - "adunit_exposure", - "app_clear_data", - "app_install", - "app_update", - "app_remove", - "error", - "first_open", - "first_visit", - "in_app_purchase", - "notification_dismiss", - "notification_foreground", - "notification_open", - "notification_receive", - "os_update", - "screen_view", - "session_start", - "user_engagement", - ]; - - return reservedEventNames.includes(name); - } - - function getDestinationEventName(events) { - return eventNamesConfigArray.find((p) => - p.src.includes(events.toLowerCase()) - ); - } - - function getDestinationEventProperties(props, destParameter) { - const destinationProperties = {}; - const item = {}; - Object.keys(props).forEach((key) => { - destParameter.forEach((param) => { - if (key === param.src) { - if (Array.isArray(param.dest)) { - param.dest.forEach((d) => { - const result = d.split("."); - // Here we only support mapping single level object mapping. - // To Do Future Scope :: implement using recursion to handle multi level prop mapping - if (result.length > 1) { - const levelOne = result[0]; - const levelTwo = result[1]; - item[levelTwo] = props[key]; - if (!destinationProperties[levelOne]) { - destinationProperties[levelOne] = []; - destinationProperties[levelOne].push(item); - } - } else { - destinationProperties[result] = props[key]; + eventNamesConfigArray, + itemParametersConfigArray, +} from "./ECommerceEventConfig"; + +import { pageEventParametersConfigArray } from "./PageEventConfig"; + +function isReservedName(name) { + const reservedEventNames = [ + "ad_activeview", + "ad_click", + "ad_exposure", + "ad_impression", + "ad_query", + "adunit_exposure", + "app_clear_data", + "app_install", + "app_update", + "app_remove", + "error", + "first_open", + "first_visit", + "in_app_purchase", + "notification_dismiss", + "notification_foreground", + "notification_open", + "notification_receive", + "os_update", + "screen_view", + "session_start", + "user_engagement", + ]; + + return reservedEventNames.includes(name); +} + +function getDestinationEventName(event) { + return eventNamesConfigArray.find((p) => + p.src.includes(event.toLowerCase()) + ); +} + +/* +props: {key: val, key2:val2} +destParameter: [{ src: "s", dest: ["d"] }, { src: "sr", dest: ["de", "ef"] }] +output: { + "item_list_id": "list1", + "items": [ + { + "item_id": "223344ffdds3ff3", + "item_name": "Just Another Game", + }, + { + "item_id": "343344ff5567ff3", + "item_name": "Wrestling Trump Cards", + "price": 4, + "index": 21, + } + ], + "item_list_name": "What's New" +} +*/ +function getDestinationEventProperties(props, destParameterConfig) { + const destinationProperties = {}; + const item = {}; + Object.keys(props).forEach((key) => { + destParameterConfig.forEach((param) => { + if (key === param.src) { + if (Array.isArray(param.dest)) { + param.dest.forEach((d) => { + const result = d.split("."); + // Here we only support mapping single level object mapping. + // To Do Future Scope :: implement using recursion to handle multi level prop mapping + if (result.length > 1) { + const levelOne = result[0]; + const levelTwo = result[1]; + item[levelTwo] = props[key]; + if (!destinationProperties[levelOne]) { + destinationProperties[levelOne] = []; + destinationProperties[levelOne].push(item); } - }); - } else { - destinationProperties[param.dest] = props[key]; - } + } else { + destinationProperties[result] = props[key]; + } + }); + } else { + destinationProperties[param.dest] = props[key]; } - }); + } }); - return destinationProperties; - } - - function getDestinationItemProperties(products, item) { - const items = []; - let obj = {}; - products.forEach((p) => { - obj = { - ...getDestinationEventProperties(p, itemParametersConfigArray), - ...(item && item[0]), - }; - items.push(obj); - }); - return items; - } - - function getPageViewProperty(props) { - return getDestinationEventProperties(props, pageEventParametersConfigArray); - } - - export { - isReservedName, - getDestinationEventName, - getDestinationEventProperties, - getDestinationItemProperties, - getPageViewProperty, - }; - \ No newline at end of file + }); + return destinationProperties; +} + +function getDestinationItemProperties(products, item) { + const items = []; + let obj = {}; + products.forEach((p) => { + obj = { + ...getDestinationEventProperties(p, itemParametersConfigArray), + ...(item && item[0]), + }; + items.push(obj); + }); + return items; +} + +function getPageViewProperty(props) { + return getDestinationEventProperties(props, pageEventParametersConfigArray); +} + +export { + isReservedName, + getDestinationEventName, + getDestinationEventProperties, + getDestinationItemProperties, + getPageViewProperty, +}; diff --git a/integrations/index.js b/integrations/index.js index 47e8154ce0..cabe4ca69d 100644 --- a/integrations/index.js +++ b/integrations/index.js @@ -17,12 +17,7 @@ import * as Optimizely from "./Optimizely"; import * as Bugsnag from "./Bugsnag"; import * as Fullstory from "./Fullstory"; import * as TVSquared from "./TVSquared"; -<<<<<<< HEAD -import * as MoEngage from "./MoEngage"; -import * as Amplitude from "./Amplitude"; -======= import * as GA4 from "./GA4"; ->>>>>>> 23bdbcd... GA4 sdk implementation // the key names should match the destination.name value to keep partity everywhere // (config-plan name, native destination.name , exported integration name(this one below)) @@ -47,12 +42,7 @@ const integrations = { BUGSNAG: Bugsnag.default, FULLSTORY: Fullstory.default, TVSQUARED: TVSquared.default, -<<<<<<< HEAD - MOENGAGE: MoEngage.default, - AM: Amplitude.default, -======= GA4: GA4.default, ->>>>>>> 23bdbcd... GA4 sdk implementation }; export { integrations };