From 7e25a0f10390c9d81873663568c2bf0fb8c8262b Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Thu, 29 Sep 2022 06:36:10 +0530 Subject: [PATCH 1/7] feat(new integration): Iterable - onboard integration --- integrations/Iterable/browser.js | 192 +++++++++++++++++++++++++++++ integrations/Iterable/constants.js | 8 ++ integrations/Iterable/index.js | 3 + integrations/Iterable/utils.js | 46 +++++++ integrations/client_server_name.js | 1 + integrations/index.js | 2 + integrations/integration_cname.js | 2 + 7 files changed, 254 insertions(+) create mode 100644 integrations/Iterable/browser.js create mode 100644 integrations/Iterable/constants.js create mode 100644 integrations/Iterable/index.js create mode 100644 integrations/Iterable/utils.js diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js new file mode 100644 index 0000000000..ce0a27f48d --- /dev/null +++ b/integrations/Iterable/browser.js @@ -0,0 +1,192 @@ +/* eslint-disable class-methods-use-this */ +import get from "get-value"; +import logger from "../../utils/logUtil"; +import { myAsyncJWTGenerator, formPurchaseEventPayload } from "./utils"; + +import { + getEventMappingFromConfig, + removeUndefinedAndNullValues, + getHashFromArrayWithDuplicate, +} from "../utils/commonUtils"; +import { NAME } from "./constants"; +import ScriptLoader from "../ScriptLoader"; + +class Iterable { + constructor(config) { + this.apiKey = config.apiKey; + this.apiSecret = config.apiSecret; + this.useUserId = config.useUserId; + this.fetchAppEvents = undefined; + this.name = NAME; + this.eventMappingFromConfig = config.eventMappingFromConfig; + + this.animationDuration = config.animationDuration; + this.displayInterval = config.displayInterval; + this.onOpenScreenReaderMessage = config.onOpenScreenReaderMessage; + this.onOpenNodeToTakeFocus = config.onOpenNodeToTakeFocus; + this.packageName = config.packageName; + this.rightOffset = config.rightOffset; + this.topOffset = config.topOffset; + this.bottomOffset = config.bottomOffset; + this.handleLinks = config.handleLinks; + + this.closeButtonColor = config.closeButtonColor; + this.closeButtonSize = config.closeButtonSize; + this.closeButtonColorTopOffset = config.closeButtonColorTopOffset; + this.closeButtonColorSideOffset = config.closeButtonColorSideOffset; + this.iconPath = config.iconPath; + this.isRequiredToDismissMessage = config.isRequiredToDismissMessage; + this.closeButtonPosition = config.closeButtonPosition; + } + + init() { + logger.debug("===In init Iterable==="); + ScriptLoader("iterable-web","https://unpkg.com/@iterable/web-sdk/index.js") + } + + isLoaded() { + logger.debug("===In isLoaded Iterable==="); + return !!window['@iterable/web-sdk']; + } + + isReady() { + logger.debug("===In isReady Iterable==="); + return !!window['@iterable/web-sdk']; + } + + identify(rudderElement) { + logger.debug("===In identify Iterable"); + + const { message } = rudderElement; + const userEmail = get(message, "context.traits.email"); + const userId = get(message, "userId"); + + let wd; + /* + TODO: update initialization using myAsyncJWTGenerator() + to use email/userId and api-secret from config to build JWT + */ + if(this.useUserId) { + wd = window['@iterable/web-sdk'].initialize( + this.apiKey, + myAsyncJWTGenerator + ); + wd.setUserID(userId).then(() => { + logger.debug("userId set"); + }); + } else { + wd = window['@iterable/web-sdk'].initialize( + this.apiKey, + myAsyncJWTGenerator + ); + wd.setEmail(userEmail).then(() => { + logger.debug("userEmail set"); + }); + } + /* Available pop-up push notification settings configurable from UI + this.animationDuration, + this.displayInterval, + this.onOpenScreenReaderMessage, + this.onOpenNodeToTakeFocus, + this.packageName, + this.rightOffset, + this.topOffset, + this.bottomOffset, + this.handleLinks, + this.closeButtonColor, + this.closeButtonSize, + this.closeButtonColorTopOffset, + this.closeButtonColorSideOffset, + this.iconPath, + this.isRequiredToDismissMessage, + this.closeButtonPosition, + */ + // Reference : https://github.com/iterable/iterable-web-sdk + let getInAppMessagesPayload = { + count: 20, + animationDuration: Number(this.animationDuration) || 400, + displayInterval: Number(this.displayInterval) || 30000, + onOpenScreenReaderMessage: this.onOpenScreenReaderMessage || undefined, + onOpenNodeToTakeFocus: this.onOpenNodeToTakeFocus || undefined, + packageName: this.packageName || undefined, + rightOffset: this.rightOffset || undefined, + topOffset: this.topOffset || undefined, + bottomOffset: this.bottomOffset || undefined, + handleLinks: this.handleLinks || undefined, + closeButton: { + color: this.closeButtonColor || 'red', + size: this.closeButtonSize || '16px', + topOffset: this.closeButtonColorTopOffset || '4%', + sideOffset: this.closeButtonColorSideOffset || '4%', + iconPath: this.iconPath || undefined, + isRequiredToDismissMessage: this.isRequiredToDismissMessage || undefined, + position: this.closeButtonPosition || 'top-right' + } + } + getInAppMessagesPayload = removeUndefinedAndNullValues(getInAppMessagesPayload); + + const { request } = window['@iterable/web-sdk'].getInAppMessages( + getInAppMessagesPayload, + { display: 'immediate' } + ); + // fetchAppEvents is a class function now available throughout + // we will trigger getInAppMessages when event name matches from the ui mapping in config. + this.fetchAppEvents = request; + } + + track(rudderElement) { + logger.debug("===In track Iterable==="); + + const { message } = rudderElement; + const { event } = message; + const eventPayload = removeUndefinedAndNullValues(message.properties); + const userEmail = get(message, "context.traits.email"); + const userId = get(message, "userId"); + const eventsHashmap = getHashFromArrayWithDuplicate( + this.eventMappingFromConfig, + "from", + "to", + false + ); + const mappedEventTypes = getEventMappingFromConfig(event, eventsHashmap); + if (!event) { + logger.error("Event name not present"); + return; + } + if(mappedEventTypes) { + mappedEventTypes.forEach((evType) => { + if(evType === "trackPurchase") { + // purchase events + const purchaseEventPayload = formPurchaseEventPayload(message) + window['@iterable/web-sdk'].trackPurchase( + purchaseEventPayload, + ) + } + else if (evType === "getInAppMessages") { + this.fetchAppEvents(); + } + }); + } else { + // custom events if event is not mapped + /* fields available for custom track event + { + "email": "string", + "userId": "string", + "eventName": "string", + "id": "string", + "createdAt": 0, + "dataFields": {}, + "campaignId": 0, + "templateId": 0 + } + */ + // Either email or userId must be passed in to identify the user. + // If both are passed in, email takes precedence. + logger.debug(`The event ${event} is not mapped in the dashboard, firing a custom event`); + window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: event, dataFields: eventPayload }) + .then(logger.debug("Track a custom event.")); + } + } +} + +export default Iterable; diff --git a/integrations/Iterable/constants.js b/integrations/Iterable/constants.js new file mode 100644 index 0000000000..8ffddbb3ae --- /dev/null +++ b/integrations/Iterable/constants.js @@ -0,0 +1,8 @@ +const NAME = "ITERABLE"; +const CNameMapping = { + [NAME]: NAME, + Iterable: NAME, + iterable: NAME, +}; + +export { NAME, CNameMapping }; \ No newline at end of file diff --git a/integrations/Iterable/index.js b/integrations/Iterable/index.js new file mode 100644 index 0000000000..7b7a279f0e --- /dev/null +++ b/integrations/Iterable/index.js @@ -0,0 +1,3 @@ +import Iterable from "./browser"; + +export default Iterable; \ No newline at end of file diff --git a/integrations/Iterable/utils.js b/integrations/Iterable/utils.js new file mode 100644 index 0000000000..4f982b05f7 --- /dev/null +++ b/integrations/Iterable/utils.js @@ -0,0 +1,46 @@ +import { getDataFromSource } from "../../utils/utils"; + +async function myAsyncJWTGenerator (email) { + return "PLACEHOLDER FOR JWT TOKEN"; + /* + TODO: update JWT function. + */ +} + +const ITEMS_MAPPING = [ + { src: "product_id", dest: "id" }, + { src: "sku", dest: "sku" }, + { src: "name", dest: "name" }, + { src: "price", dest: "price" }, + { src: "quantity", dest: "quantity" }, + { src: "image_url", dest: "imageUrl" }, + { src: "url", dest: "url" } +] + +function getMappingObject (properties, mappings) { + let itemsObject = {}; + mappings.forEach((mapping) => { + itemsObject = { + ...getDataFromSource(mapping.src, mapping.dest, properties), + ...itemsObject, + }; + }); + return itemsObject; +} + +function formPurchaseEventPayload(message) { + let purchaseEventPayload = {}; + const { products } = message.properties; + purchaseEventPayload.id = message.properties.order_id || message.properties.checkout_id; + purchaseEventPayload.total = message.properties.total; + purchaseEventPayload.items = []; + const lineItems = []; + products.forEach((p) => { + const product = getMappingObject(p, ITEMS_MAPPING); + lineItems.push(product); + }); + purchaseEventPayload.items = lineItems; + return purchaseEventPayload; +} + +export { myAsyncJWTGenerator, formPurchaseEventPayload }; \ No newline at end of file diff --git a/integrations/client_server_name.js b/integrations/client_server_name.js index a1153457a5..8445399c68 100644 --- a/integrations/client_server_name.js +++ b/integrations/client_server_name.js @@ -58,6 +58,7 @@ const clientToServerNames = { WOOPRA: "Woopra", ROLLBAR: "RollBar", QUORA_PIXEL: "Quora Pixel", + ITERABLE: "Iterable" }; export { clientToServerNames }; diff --git a/integrations/index.js b/integrations/index.js index 39ca3812f5..d9b42f8527 100644 --- a/integrations/index.js +++ b/integrations/index.js @@ -57,6 +57,7 @@ import * as Shynet from "./Shynet"; import * as Woopra from "./Woopra"; import * as RollBar from "./RollBar"; import * as QuoraPixel from "./QuoraPixel"; +import * as Iterable from "./Iterable"; // the key names should match the destination.name value to keep partity everywhere @@ -122,6 +123,7 @@ const integrations = { WOOPRA: Woopra.default, ROLLBAR: RollBar.default, QUORA_PIXEL: QuoraPixel.default, + ITERABLE: Iterable.default, }; diff --git a/integrations/integration_cname.js b/integrations/integration_cname.js index 95727eff4d..f667a8e1b4 100644 --- a/integrations/integration_cname.js +++ b/integrations/integration_cname.js @@ -57,6 +57,7 @@ import { CNameMapping as Shynet } from "./Shynet/constants"; import { CNameMapping as Woopra } from "./Woopra/constants"; import { CNameMapping as RollBar } from "./RollBar/constants"; import { CNameMapping as QuoraPixel } from "./QuoraPixel/constants"; +import { CNameMapping as Iterable } from "./Iterable/constants"; // for sdk side native integration identification @@ -122,6 +123,7 @@ const commonNames = { ...Woopra, ...RollBar, ...QuoraPixel, + ...Iterable, }; From 63ee6937ebd86d4a8c995f131ca23c0179ccdc83 Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Fri, 7 Oct 2022 14:57:44 +0530 Subject: [PATCH 2/7] feat(new integration): get jwt_token from integrations object, add getinapp track support --- integrations/Iterable/browser.js | 22 ++++++++++++++++++---- integrations/Iterable/utils.js | 6 ------ integrations/client_server_name.js | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index ce0a27f48d..1324973c30 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -4,6 +4,7 @@ import logger from "../../utils/logUtil"; import { myAsyncJWTGenerator, formPurchaseEventPayload } from "./utils"; import { + isDefinedAndNotNull, getEventMappingFromConfig, removeUndefinedAndNullValues, getHashFromArrayWithDuplicate, @@ -20,6 +21,7 @@ class Iterable { this.name = NAME; this.eventMappingFromConfig = config.eventMappingFromConfig; + this.sendTrackForInapp = config.sendTrackForInapp; this.animationDuration = config.animationDuration; this.displayInterval = config.displayInterval; this.onOpenScreenReaderMessage = config.onOpenScreenReaderMessage; @@ -58,14 +60,21 @@ class Iterable { logger.debug("===In identify Iterable"); const { message } = rudderElement; + const { integrations } = message; const userEmail = get(message, "context.traits.email"); const userId = get(message, "userId"); + async function myAsyncJWTGenerator (message) { + if (integrations && integrations.ITERABLE) { + const { jwt_token } = integrations.ITERABLE; + if (isDefinedAndNotNull(jwt_token)) + return jwt_token; + } else { + logger.info("The JWT token was not passed, The SDK could not be initialised.") + } + } + let wd; - /* - TODO: update initialization using myAsyncJWTGenerator() - to use email/userId and api-secret from config to build JWT - */ if(this.useUserId) { wd = window['@iterable/web-sdk'].initialize( this.apiKey, @@ -163,6 +172,11 @@ class Iterable { ) } else if (evType === "getInAppMessages") { + // send a track call for getinappMessages if option enabled in config + if (this.sendTrackForInapp) { + window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: "Track getInAppMessages", dataFields: eventPayload }) + .then(logger.debug("Track a getinappMessages event.")); + } this.fetchAppEvents(); } }); diff --git a/integrations/Iterable/utils.js b/integrations/Iterable/utils.js index 4f982b05f7..5ffc3c3e86 100644 --- a/integrations/Iterable/utils.js +++ b/integrations/Iterable/utils.js @@ -1,11 +1,5 @@ import { getDataFromSource } from "../../utils/utils"; -async function myAsyncJWTGenerator (email) { - return "PLACEHOLDER FOR JWT TOKEN"; - /* - TODO: update JWT function. - */ -} const ITEMS_MAPPING = [ { src: "product_id", dest: "id" }, diff --git a/integrations/client_server_name.js b/integrations/client_server_name.js index ab125864b2..4d079457be 100644 --- a/integrations/client_server_name.js +++ b/integrations/client_server_name.js @@ -58,7 +58,7 @@ const clientToServerNames = { WOOPRA: "Woopra", ROLLBAR: "RollBar", QUORA_PIXEL: "Quora Pixel", - ITERABLE: "Iterable" + ITERABLE: "Iterable", JUNE: "June", }; From 86a4d8c41408f1efb85de8826f83b216de9d83d1 Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Mon, 10 Oct 2022 08:02:45 +0530 Subject: [PATCH 3/7] feat(new integration): seperate mapping support for inapp and purchase calls, refactor --- integrations/Iterable/browser.js | 83 +++++++++++++++++--------------- integrations/Iterable/utils.js | 2 +- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index 1324973c30..c6394aaf69 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -1,13 +1,12 @@ /* eslint-disable class-methods-use-this */ import get from "get-value"; import logger from "../../utils/logUtil"; -import { myAsyncJWTGenerator, formPurchaseEventPayload } from "./utils"; +import { formPurchaseEventPayload } from "./utils"; import { isDefinedAndNotNull, - getEventMappingFromConfig, removeUndefinedAndNullValues, - getHashFromArrayWithDuplicate, + isNotEmpty, } from "../utils/commonUtils"; import { NAME } from "./constants"; import ScriptLoader from "../ScriptLoader"; @@ -19,7 +18,8 @@ class Iterable { this.useUserId = config.useUserId; this.fetchAppEvents = undefined; this.name = NAME; - this.eventMappingFromConfig = config.eventMappingFromConfig; + this.getInAppEventMapping = config.getInAppEventMapping; + this.purchaseEventMapping = config.purchaseEventMapping; this.sendTrackForInapp = config.sendTrackForInapp; this.animationDuration = config.animationDuration; @@ -151,54 +151,59 @@ class Iterable { const eventPayload = removeUndefinedAndNullValues(message.properties); const userEmail = get(message, "context.traits.email"); const userId = get(message, "userId"); - const eventsHashmap = getHashFromArrayWithDuplicate( - this.eventMappingFromConfig, - "from", - "to", - false - ); - const mappedEventTypes = getEventMappingFromConfig(event, eventsHashmap); + if (!event) { logger.error("Event name not present"); return; - } - if(mappedEventTypes) { - mappedEventTypes.forEach((evType) => { - if(evType === "trackPurchase") { - // purchase events - const purchaseEventPayload = formPurchaseEventPayload(message) - window['@iterable/web-sdk'].trackPurchase( - purchaseEventPayload, - ) - } - else if (evType === "getInAppMessages") { + } + let isCustom = true; + if (isNotEmpty(this.getInAppEventMapping)) { + const mappedEvents = this.getInAppEventMapping; + mappedEvents.forEach((e) => { + if(e.eventName === event) { // send a track call for getinappMessages if option enabled in config if (this.sendTrackForInapp) { window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: "Track getInAppMessages", dataFields: eventPayload }) .then(logger.debug("Track a getinappMessages event.")); } this.fetchAppEvents(); + isCustom = false; } - }); - } else { + }) + } + if (isNotEmpty(this.purchaseEventMapping)) { + // purchase events + const mappedEvents = this.purchaseEventMapping; + mappedEvents.forEach((e) => { + if(e.eventName === event) { + const purchaseEventPayload = formPurchaseEventPayload(message) + window['@iterable/web-sdk'].trackPurchase( + purchaseEventPayload, + ) + isCustom = false; + } + }) + } + if (isCustom) { // custom events if event is not mapped - /* fields available for custom track event - { - "email": "string", - "userId": "string", - "eventName": "string", - "id": "string", - "createdAt": 0, - "dataFields": {}, - "campaignId": 0, - "templateId": 0 - } - */ - // Either email or userId must be passed in to identify the user. - // If both are passed in, email takes precedence. + /* fields available for custom track event + { + "email": "string", + "userId": "string", + "eventName": "string", + "id": "string", + "createdAt": 0, + "dataFields": {}, + "campaignId": 0, + "templateId": 0 + } + */ + // Either email or userId must be passed in to identify the user. + // If both are passed in, email takes precedence. logger.debug(`The event ${event} is not mapped in the dashboard, firing a custom event`); window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: event, dataFields: eventPayload }) - .then(logger.debug("Track a custom event.")); + .then(logger.debug("Track a custom event.")); + } } } diff --git a/integrations/Iterable/utils.js b/integrations/Iterable/utils.js index 5ffc3c3e86..b3ef1853f2 100644 --- a/integrations/Iterable/utils.js +++ b/integrations/Iterable/utils.js @@ -37,4 +37,4 @@ function formPurchaseEventPayload(message) { return purchaseEventPayload; } -export { myAsyncJWTGenerator, formPurchaseEventPayload }; \ No newline at end of file +export { formPurchaseEventPayload }; \ No newline at end of file From 4b53ae093a10e39a523e1918d09fe11428447c9e Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Mon, 10 Oct 2022 13:12:46 +0530 Subject: [PATCH 4/7] feat(new integration): address comments, refactor, fix references, loggers --- integrations/Iterable/browser.js | 17 +++++++++-------- integrations/Iterable/utils.js | 19 ++++++++++++++++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index c6394aaf69..23aa83b0f7 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -61,16 +61,17 @@ class Iterable { const { message } = rudderElement; const { integrations } = message; - const userEmail = get(message, "context.traits.email"); - const userId = get(message, "userId"); + const userEmail = message.traits?.email || message.context?.traits?.email; + const userId = message.userId; - async function myAsyncJWTGenerator (message) { + async function extractJWT (message) { if (integrations && integrations.ITERABLE) { const { jwt_token } = integrations.ITERABLE; if (isDefinedAndNotNull(jwt_token)) return jwt_token; } else { - logger.info("The JWT token was not passed, The SDK could not be initialised.") + logger.error("The JWT token was not passed, The SDK could not be initialised.") + return; } } @@ -78,7 +79,7 @@ class Iterable { if(this.useUserId) { wd = window['@iterable/web-sdk'].initialize( this.apiKey, - myAsyncJWTGenerator + extractJWT ); wd.setUserID(userId).then(() => { logger.debug("userId set"); @@ -86,7 +87,7 @@ class Iterable { } else { wd = window['@iterable/web-sdk'].initialize( this.apiKey, - myAsyncJWTGenerator + extractJWT ); wd.setEmail(userEmail).then(() => { logger.debug("userEmail set"); @@ -161,12 +162,12 @@ class Iterable { const mappedEvents = this.getInAppEventMapping; mappedEvents.forEach((e) => { if(e.eventName === event) { + this.fetchAppEvents(); // send a track call for getinappMessages if option enabled in config if (this.sendTrackForInapp) { window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: "Track getInAppMessages", dataFields: eventPayload }) - .then(logger.debug("Track a getinappMessages event.")); + .then(logger.debug("Web in-app push triggered")); } - this.fetchAppEvents(); isCustom = false; } }) diff --git a/integrations/Iterable/utils.js b/integrations/Iterable/utils.js index b3ef1853f2..1f491c8186 100644 --- a/integrations/Iterable/utils.js +++ b/integrations/Iterable/utils.js @@ -29,10 +29,23 @@ function formPurchaseEventPayload(message) { purchaseEventPayload.total = message.properties.total; purchaseEventPayload.items = []; const lineItems = []; - products.forEach((p) => { - const product = getMappingObject(p, ITEMS_MAPPING); + if (products) { + products.forEach((p) => { + const product = getMappingObject(p, ITEMS_MAPPING); + lineItems.push(product); + }); + } else { + // if product related info is on properties root + let product = {}; + product.id = message.properties.product_id; + product.sku = message.properties.sku; + product.name = message.properties.name; + product.price = message.properties.price; + product.quantity = message.properties.quantity; + product.imageUrl = message.properties.image_url; + product.url = message.properties.url; lineItems.push(product); - }); + } purchaseEventPayload.items = lineItems; return purchaseEventPayload; } From b6f183743de005c90ca2ed251bd7a5766fda1344 Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Mon, 10 Oct 2022 16:04:31 +0530 Subject: [PATCH 5/7] feat(new integration): address comment, remove flag --- integrations/Iterable/browser.js | 44 ++++++++++---------------------- integrations/Iterable/utils.js | 11 +++++++- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index 23aa83b0f7..be439036a9 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ import get from "get-value"; import logger from "../../utils/logUtil"; -import { formPurchaseEventPayload } from "./utils"; +import { formPurchaseEventPayload, existsInMapping } from "./utils"; import { isDefinedAndNotNull, @@ -14,7 +14,6 @@ import ScriptLoader from "../ScriptLoader"; class Iterable { constructor(config) { this.apiKey = config.apiKey; - this.apiSecret = config.apiSecret; this.useUserId = config.useUserId; this.fetchAppEvents = undefined; this.name = NAME; @@ -152,40 +151,25 @@ class Iterable { const eventPayload = removeUndefinedAndNullValues(message.properties); const userEmail = get(message, "context.traits.email"); const userId = get(message, "userId"); - if (!event) { logger.error("Event name not present"); return; } - let isCustom = true; - if (isNotEmpty(this.getInAppEventMapping)) { - const mappedEvents = this.getInAppEventMapping; - mappedEvents.forEach((e) => { - if(e.eventName === event) { - this.fetchAppEvents(); - // send a track call for getinappMessages if option enabled in config - if (this.sendTrackForInapp) { - window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: "Track getInAppMessages", dataFields: eventPayload }) - .then(logger.debug("Web in-app push triggered")); - } - isCustom = false; - } - }) + if (isNotEmpty(this.getInAppEventMapping) && existsInMapping(this.getInAppEventMapping, event)) { + this.fetchAppEvents(); + // send a track call for getinappMessages if option enabled in config + if (this.sendTrackForInapp) { + window['@iterable/web-sdk'].track({ email: userEmail, userId, eventName: "Track getInAppMessages", dataFields: eventPayload }) + .then(logger.debug("Web in-app push triggered")); + } } - if (isNotEmpty(this.purchaseEventMapping)) { + else if (isNotEmpty(this.purchaseEventMapping) && existsInMapping(this.purchaseEventMapping, event)) { // purchase events - const mappedEvents = this.purchaseEventMapping; - mappedEvents.forEach((e) => { - if(e.eventName === event) { - const purchaseEventPayload = formPurchaseEventPayload(message) - window['@iterable/web-sdk'].trackPurchase( - purchaseEventPayload, - ) - isCustom = false; - } - }) - } - if (isCustom) { + const purchaseEventPayload = formPurchaseEventPayload(message) + window['@iterable/web-sdk'].trackPurchase( + purchaseEventPayload, + ) + } else { // custom events if event is not mapped /* fields available for custom track event { diff --git a/integrations/Iterable/utils.js b/integrations/Iterable/utils.js index 1f491c8186..ddc8cde1b7 100644 --- a/integrations/Iterable/utils.js +++ b/integrations/Iterable/utils.js @@ -50,4 +50,13 @@ function formPurchaseEventPayload(message) { return purchaseEventPayload; } -export { formPurchaseEventPayload }; \ No newline at end of file +function existsInMapping(mappedEvents, event) { + let mapped = false; + mappedEvents.forEach((e) => { + if (e.eventName == event) + mapped = true; + }) + return mapped; +} + +export { formPurchaseEventPayload, existsInMapping }; \ No newline at end of file From 137c32bad5e3b3f2f40cc120d103e6438f3cc4cb Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Mon, 10 Oct 2022 21:27:20 +0530 Subject: [PATCH 6/7] addressed comments, some more refactors --- integrations/Iterable/browser.js | 43 +++++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index be439036a9..92eb92e181 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -14,7 +14,7 @@ import ScriptLoader from "../ScriptLoader"; class Iterable { constructor(config) { this.apiKey = config.apiKey; - this.useUserId = config.useUserId; + this.initialisationIdentifier = config.initialisationIdentifier; this.fetchAppEvents = undefined; this.name = NAME; this.getInAppEventMapping = config.getInAppEventMapping; @@ -73,24 +73,31 @@ class Iterable { return; } } + + // Initialize the iterable SDK with the proper apiKey and the passed JWT + function initializeSDK(initialisationIdentifier, apiKey) { + let wd = window['@iterable/web-sdk'].initialize(apiKey, extractJWT) + if (initialisationIdentifier === "email") { + wd.setEmail(userEmail).then(() => { + logger.debug("userEmail set"); + }); + } else { + wd.setUserID(userId).then(() => { + logger.debug("userId set"); + }); + } + } - let wd; - if(this.useUserId) { - wd = window['@iterable/web-sdk'].initialize( - this.apiKey, - extractJWT - ); - wd.setUserID(userId).then(() => { - logger.debug("userId set"); - }); - } else { - wd = window['@iterable/web-sdk'].initialize( - this.apiKey, - extractJWT - ); - wd.setEmail(userEmail).then(() => { - logger.debug("userEmail set"); - }); + switch (this.initialisationIdentifier) { + case "email": + initializeSDK(this.initialisationIdentifier, this.apiKey) + break; + case "userId": + initializeSDK(this.initialisationIdentifier, this.apiKey) + break; + default: + initializeSDK("email") + break; } /* Available pop-up push notification settings configurable from UI this.animationDuration, From 7e99d75507808ac6e5b1059f4d4d3769dd559d39 Mon Sep 17 00:00:00 2001 From: yashasvibajpai Date: Mon, 10 Oct 2022 22:23:39 +0530 Subject: [PATCH 7/7] feat(new integration): remove redundant function, utilize switch --- integrations/Iterable/browser.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/integrations/Iterable/browser.js b/integrations/Iterable/browser.js index 92eb92e181..e9de324725 100644 --- a/integrations/Iterable/browser.js +++ b/integrations/Iterable/browser.js @@ -1,6 +1,6 @@ /* eslint-disable class-methods-use-this */ import get from "get-value"; -import logger from "../../utils/logUtil"; +import Logger from "../../utils/logger"; import { formPurchaseEventPayload, existsInMapping } from "./utils"; import { @@ -11,12 +11,16 @@ import { import { NAME } from "./constants"; import ScriptLoader from "../ScriptLoader"; +const logger = new Logger(NAME); + class Iterable { - constructor(config) { + constructor(config, analytics) { this.apiKey = config.apiKey; this.initialisationIdentifier = config.initialisationIdentifier; this.fetchAppEvents = undefined; this.name = NAME; + this.analytics = analytics; + if (analytics.logLevel) logger.setLogLevel(analytics.logLevel); this.getInAppEventMapping = config.getInAppEventMapping; this.purchaseEventMapping = config.purchaseEventMapping; @@ -75,28 +79,22 @@ class Iterable { } // Initialize the iterable SDK with the proper apiKey and the passed JWT - function initializeSDK(initialisationIdentifier, apiKey) { - let wd = window['@iterable/web-sdk'].initialize(apiKey, extractJWT) - if (initialisationIdentifier === "email") { + let wd = window['@iterable/web-sdk'].initialize(this.apiKey, extractJWT) + switch (this.initialisationIdentifier) { + case "email": wd.setEmail(userEmail).then(() => { logger.debug("userEmail set"); - }); - } else { + }); + break; + case "userId": wd.setUserID(userId).then(() => { logger.debug("userId set"); }); - } - } - - switch (this.initialisationIdentifier) { - case "email": - initializeSDK(this.initialisationIdentifier, this.apiKey) - break; - case "userId": - initializeSDK(this.initialisationIdentifier, this.apiKey) break; default: - initializeSDK("email") + wd.setEmail(userEmail).then(() => { + logger.debug("userEmail set"); + }); break; } /* Available pop-up push notification settings configurable from UI