Skip to content

Commit

Permalink
feat: initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
shrouti1507 committed Feb 6, 2024
1 parent c7c3110 commit e35fb4e
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/v0/destinations/bluecore/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { getMappingConfig } = require('../../util');

const BASE_URL = 'https://api.bluecore.com/api/track/mobile/v1';

const CONFIG_CATEGORIES = {
IDENTIFY: {
name: 'bluecoreIdentifyConfig',
type: 'identify',
},
TRACK: {
name: 'bluecoreTrackConfig',
type: 'track',
},
};

// const EVENT_NAME_MAPPING = {
// 'Product Viewed': 'viewed_product',
// 'Products Searched': 'search',
// 'Product Added': 'add_to_cart',
// 'Product Removed': 'remove_from_cart',
// 'Product Added to Wishlist': 'wishlist',
// 'Order Completed': 'purchase',
// 'Identify': 'identify',
// };

const EVENT_NAME_MAPPING = [
{
src: ['Product Viewed'],
dest: 'viewed_product',
},
{
src: ['Products Searched'],
dest: 'search',
},
{
src: ['Product Added'],
dest: 'add_to_cart',
},
{
src: ['Product Removed'],
dest: 'remove_from_cart',
},
{
src: ['Product Added to Wishlist'],
dest: 'wishlist',
},
{
src: ['Order Completed'],
dest: 'purchase',
},
];

const MAPPING_CONFIG = getMappingConfig(CONFIG_CATEGORIES, __dirname);
module.exports = {
CONFIG_CATEGORIES,
MAPPING_CONFIG,
EVENT_NAME_MAPPING,
BASE_URL,
};
63 changes: 63 additions & 0 deletions src/v0/destinations/bluecore/data/bluecoreIdentifyConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[
{
"destKey": "properties.distinct_id",
"sourceKeys": ["userId", "anonymousId", "email"],
"required": true
},
{
"destKey": "properties.customer.name",
"sourceKeys": "name",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.first_name",
"sourceKeys": "firstName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.last_name",
"sourceKeys": "lastName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.age",
"sourceKeys": ["context.traits.age","traits.age"],
"required": false
},
{
"destKey": "event",
"sourceKeys": "event",
"required": false
},
{
"destKey": "properties.customer.sex",
"sourceKeys": ["traits.gender", "context.traits.gender","traits.sex", "context.traits.sex"],
"required": false
},
{
"destKey": "properties.customer.address",
"sourceKeys": "address",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.email",
"sourceKeys": "email",
"required": true,
"sourceFromGenericMap": true
},
{
"destKey": "properties.client",
"sourceKeys": "context.app.version",
"required": false
},
{
"destKey": "properties.device",
"sourceKeys": "context.device.model",
"required": false
}
]

73 changes: 73 additions & 0 deletions src/v0/destinations/bluecore/data/bluecoreTrackConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[
{
"destKey": "properties.distinct_id",
"sourceKeys": ["userId", "anonymousId", "email"],
"required": false
},
{
"destKey": "properties.customer.name",
"sourceKeys": "name",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.first_name",
"sourceKeys": "firstName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.last_name",
"sourceKeys": "lastName",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.age",
"sourceKeys": ["context.traits.age","traits.age"],
"required": false
},
{
"destKey": "properties.customer.sex",
"sourceKeys": ["traits.gender", "context.traits.gender","traits.sex", "context.traits.sex"],
"required": false
},
{
"destKey": "properties.customer.address",
"sourceKeys": "address",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.customer.email",
"sourceKeys": "email",
"required": false,
"sourceFromGenericMap": true
},
{
"destKey": "properties.search_term",
"sourceKeys": "properties.query",
"required": false
},
{
"destKey": "properties.order_id",
"sourceKeys": "properties.order_id",
"required": false
},
{
"destKey": "properties.total",
"sourceKeys": "properties.total",
"required": false
},
{
"destKey": "properties.client",
"sourceKeys": "context.app.version",
"required": false
},
{
"destKey": "properties.device",
"sourceKeys": "context.device.model",
"required": false
}
]

148 changes: 148 additions & 0 deletions src/v0/destinations/bluecore/transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
const { getHashFromArrayWithDuplicate, isDefinedAndNotNull, ConfigurationError, TransformationError,
InstrumentationError, } = require('@rudderstack/integrations-lib');
const { EventType } = require('../../../constants');
const {
constructPayload,
ErrorMessage,
defaultPostRequestConfig,
getValueFromMessage,
// isDefinedAndNotNull,
simpleProcessRouterDest,
validateEventName,
} = require('../../util');

const {
MAPPING_CONFIG,
CONFIG_CATEGORIES,
BASE_URL,
EVENT_NAME_MAPPING,
} = require('./config');

const verifyTrackPayload = (payload) => {
switch (payload.event) {
case 'search':
if (!payload.search_term) {
throw new InstrumentationError('[Bluecore] property:: search_query is required for search event');
}
break;
case 'purchase':
if (!payload.order_id) {
throw new InstrumentationError('[Bluecore] property:: order_id is required for purchase event');
}
if (!payload.total) {
throw new InstrumentationError('[Bluecore] property:: total is required for purchase event');
}
break;
default:
break;
}
};

const deduceTrackEventName = (trackEventName, Config) => {
let eventName;
const { eventsMapping } = Config;
validateEventName(trackEventName);
/*
Step 1: If the event is not amongst the above list of ecommerce events, will look for
the event mapping in the UI. In case it is similar, will map to that.
*/
if (eventsMapping.length > 0) {
const keyMap = getHashFromArrayWithDuplicate(eventsMapping, 'from', 'to', false);
eventName = keyMap[trackEventName];
}
/*
Step 2: To find if the particular event is amongst the list of standard
Rudderstack ecommerce events, used specifically for Pinterest Conversion API
mappings.
*/
if (!eventName) {
const eventMapInfo = EVENT_NAME_MAPPING.find((eventMap) => {
if (eventMap.src.includes(trackEventName.toLowerCase())) {
return eventMap;
}
return false;
});
if (!isDefinedAndNotNull(eventMapInfo)) {
throw new ConfigurationError(`[Bluecore] Event name ${trackEventName} is not mapped`);
} else {
return [eventMapInfo.dest];
}
}
// Step 3 : check if one single event is mapped then
// if(typeof eventName === 'string') {
// return [eventName];
// }
return eventName;
};
const trackResponseBuilder = async (message, category, { Config }, eventName) => {
const event = getValueFromMessage(message, 'event');

if (!event) {
throw new InstrumentationError('[Bluecore] property:: event is required for track call');
}

const payload = constructPayload(message, MAPPING_CONFIG[category.name]);
payload.event = eventName;
verifyTrackPayload(payload);
payload.token = Config.bluecoreNamespace;
if (!payload) {
// fail-safety for developer error
throw new TransformationError(ErrorMessage.FailedToConstructPayload);
}
return payload;
};

// const identifyResponseBuilder = async (message, category, { Config }) => {

// }

const responseBuilderSimple = (response, destination) => {
const resp = defaultPostRequestConfig();
resp.endpoint = BASE_URL;
resp.body.JSON = response;
resp.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${destination.Config.bluecoreNamespace}`,
};
return resp;
}

const process = async (event) => {
const deducedEventNameArray = [];
const toSendEvents = [];
const respList = [];
const { message, destination } = event;
if (!message.type) {
throw new InstrumentationError('Message Type is not present. Aborting message.');
}

if (!destination.Config.bluecoreNamespace) {
throw new ConfigurationError('[BLUECORE] bluecore account namespace required for Authentication.');
}
const messageType = message.type.toLowerCase();
const category = CONFIG_CATEGORIES[message.type.toUpperCase()];
switch (messageType) {
case EventType.TRACK:
deducedEventNameArray.push(...deduceTrackEventName(message.event, destination.Config));
deducedEventNameArray.forEach((eventName) => {
toSendEvents.push(trackResponseBuilder(message, category, destination, eventName));
});
break;
case EventType.IDENTIFY:
// response = await identifyResponseBuilder(message, category, destination);
break;
default:
throw new InstrumentationError(`Message type ${messageType} not supported`);
}
toSendEvents.forEach((sendEvent) => {
respList.push(responseBuilderSimple(sendEvent, destination));
});
return respList;
};

const processRouterDest = async (inputs, reqMetadata) => {
const respList = await simpleProcessRouterDest(inputs, process, reqMetadata);
return respList;
};

module.exports = { process, processRouterDest };
Empty file.

0 comments on commit e35fb4e

Please sign in to comment.