Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/new integration: Convertflow onboarding #611

Merged
merged 10 commits into from
Aug 18, 2022
51 changes: 51 additions & 0 deletions integrations/ConvertFlow/browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* eslint-disable no-underscore-dangle */
/* eslint-disable class-methods-use-this */
import { NAME } from "./constants";
import logger from "../../utils/logUtil";
import ScriptLoader from "../ScriptLoader";
import { trigger } from "./utils";

class ConvertFlow {
constructor(config) {
this.websiteId = config.websiteId;
this.toggleToSendData = config.toggleToSendData;
this.eventsList = config.eventsList;
this.eventsMappping = config.eventsMappping;
this.name = NAME;
}

init() {
logger.debug("===In init convertflow===");
ScriptLoader(
"convertflow-integration",
`https://js.convertflow.co/production/websites/${this.websiteId}.js`
);
}

isLoaded() {
logger.debug("===In isLoaded convertflow===");
if (this.toggleToSendData) {
trigger(this.eventsMappping, this.eventsList);
}
return !!window.convertflow && typeof window.convertflow === "object";
}

isReady() {
logger.debug("===In isReady convertflow===");
return !!window.convertflow;
}

// identify call to Convertflow
identify(rudderElement) {
logger.debug("===In convertflow Identify===");
const { message } = rudderElement;
const email = message.context.traits?.email || message.traits?.email;
if (!email) {
logger.error("email is rquired for identify call");
}
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
const payload = { email, override: true };
window.convertflow.identify(payload);
}
}

export default ConvertFlow;
10 changes: 10 additions & 0 deletions integrations/ConvertFlow/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const NAME = "CONVERTFLOW";
const CNameMapping = {
[NAME]: NAME,
Convertflow: NAME,
convertflow: NAME,
convertFlow: NAME,
ConvertFlow: NAME,
};

export { NAME, CNameMapping };
3 changes: 3 additions & 0 deletions integrations/ConvertFlow/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ConvertFlow from "./browser";

export default ConvertFlow;
108 changes: 108 additions & 0 deletions integrations/ConvertFlow/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import {
getHashFromArray,
isDefinedAndNotNullAndNotEmpty,
} from "../utils/commonUtils";

// default mapping for the events
const standardEventsListMapping = {
cfReady: "CTA Ready",
cfView: "CTA Viewed",
cfConversion: "CTA Converted",
cfCompletion: "CTA Completed",
cfSubmit: "CTA Form Submitted",
cfAddToCart: "Product Added to Cart",
cfClosed: "CTA Closed",
};

const swapKeyValuePairs = (standardEventsMap) => {
const swappedEventsMap = {};
Object.keys(standardEventsMap).forEach((key) => {
swappedEventsMap[standardEventsMap[key]] = key;
});
return swappedEventsMap;
};

/**
* This function is used to populate properties to be sent in track call using the event data
* @param {*} data - data here, contains all the details about the event.
* eg. For event CTA Viewed
* data: {
* cta_name: {cta.name}
* cta_type: {cta.cta_type}
* }
*/
const populatingProperties = (data) => {
const rudderProperties = {};
if (data.cta) {
const { cta } = data;
rudderProperties.cta_name = cta.name;
rudderProperties.cta_type = cta.cta_type;
rudderProperties.cta_id = cta.id;
}
if (data.variant) {
rudderProperties.cta_variant = data.variant;
}
if (data.step) {
rudderProperties.cta_step = data.step;
}
return rudderProperties;
};

/**
* This function is used to trigger a callback.
utsabc marked this conversation as resolved.
Show resolved Hide resolved
* @param {*} standardEventsMap - mapping of events done by the user
* @param {*} eventName - standard event name
* @param {*} data - data here, contains all the details about the event.
* eg. For event CTA Viewed
* data: {
* cta_name: {cta.name}
* cta_type: {cta.cta_type}
* }
*/
const makeACall = (standardEventsMap, eventName, data) => {
// Updating the event name with any mapping from the webapp if available else
// storing default event name in the updatedEvent
const updatedEvent = standardEventsMap[eventName]
? standardEventsMap[eventName]
: standardEventsListMapping[eventName];

// Populating Properties
let properties = {};
if (data) {
properties = populatingProperties(data);
}
if (isDefinedAndNotNullAndNotEmpty(properties)) {
window.rudderanalytics.track(updatedEvent, properties);
} else {
window.rudderanalytics.track(updatedEvent);
}
};

/**
* This function has event listners for the occuring events and to make a call for the event after
* collecting the data.
* @param {*} userDefinedEventsMappping - Mapping of events in the webapp by the user
* @param {*} userDefinedEventsList - List of requested events by the user.
*/
const trigger = (userDefinedEventsMappping, userDefinedEventsList) => {
let standardEventsMap = getHashFromArray(userDefinedEventsMappping);
standardEventsMap = swapKeyValuePairs(standardEventsMap);
const standardEventsList = [
"cfReady",
"cfView",
"cfConversion",
"cfCompletion",
"cfSubmit",
"cfAddToCart",
"cfClosed",
];
standardEventsList.forEach((events) => {
window.addEventListener(events, function (event) {
if (userDefinedEventsList.includes(event.type)) {
makeACall(standardEventsMap, event.type, event.detail);
}
});
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
});
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
};

export { makeACall, trigger };
1 change: 1 addition & 0 deletions integrations/client_server_name.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const clientToServerNames = {
MATOMO: "Matomo",
ROCKERBOX: "Rockerbox",
MOUSEFLOW: "Mouseflow",
CONVERTFLOW: "ConvertFlow",
};

export { clientToServerNames };
2 changes: 2 additions & 0 deletions integrations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import * as Vero from "./Vero";
import * as Matomo from "./Matomo";
import * as Rockerbox from "./Rockerbox";
import * as Mouseflow from "./Mouseflow";
import * as ConvertFlow from "./ConvertFlow";

// 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))
Expand Down Expand Up @@ -107,6 +108,7 @@ const integrations = {
MATOMO: Matomo.default,
ROCKERBOX: Rockerbox.default,
MOUSEFLOW: Mouseflow.default,
CONVERTFLOW: ConvertFlow.default,
};

export { integrations };
2 changes: 2 additions & 0 deletions integrations/integration_cname.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { CNameMapping as Vero } from "./Vero/constants";
import { CNameMapping as Matomo } from "./Matomo/constants";
import { CNameMapping as Rockerbox } from "./Rockerbox/constants";
import { CNameMapping as Mouseflow } from "./Mouseflow/constants";
import { CNameMapping as ConvertFlow } from "./ConvertFlow/constants";

// for sdk side native integration identification
// add a mapping from common names to index.js exported key names as identified by Rudder
Expand All @@ -65,6 +66,7 @@ const commonNames = {
...Chartbeat,
...Clevertap,
...Comscore,
...ConvertFlow,
...Criteo,
...CustomerIO,
...DCMFloodlight,
Expand Down