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

feat: add unity source support in Singular #3634

Merged
merged 3 commits into from
Sep 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/v0/destinations/singular/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const CONFIG_CATEGORIES = {
name: 'SINGULARIosSessionConfig',
type: 'track',
},
SESSION_UNITY: {
name: 'SINGULARUnitySessionConfig',
type: 'track',
},
EVENT_ANDROID: {
name: 'SINGULARAndroidEventConfig',
type: 'track',
Expand All @@ -21,6 +25,10 @@ const CONFIG_CATEGORIES = {
name: 'SINGULARIosEventConfig',
type: 'track',
},
EVENT_UNITY: {
name: 'SINGULARUnityEventConfig',
type: 'track',
},
PRODUCT_PROPERTY: {
name: 'SINGULAREventProductConfig',
},
Expand All @@ -29,8 +37,15 @@ const CONFIG_CATEGORIES = {
const SUPPORTED_PLATFORM = {
android: 'ANDROID',
ios: 'IOS',
pc: 'unity',
xbox: 'unity',
playstation: 'unity',
nintendo: 'unity',
metaquest: 'unity',
};

const SUPPORTED_UNTIY_SUBPLATFORMS = ['pc', 'xbox', 'playstation', 'nintendo', 'metaquest'];

const SINGULAR_SESSION_ANDROID_EXCLUSION = [
'referring_application',
'asid',
Expand Down Expand Up @@ -93,5 +108,6 @@ module.exports = {
SINGULAR_EVENT_ANDROID_EXCLUSION,
SINGULAR_EVENT_IOS_EXCLUSION,
SUPPORTED_PLATFORM,
SUPPORTED_UNTIY_SUBPLATFORMS,
BASE_URL,
};
112 changes: 112 additions & 0 deletions src/v0/destinations/singular/data/SINGULARUnityEventConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[
{
"destKey": "p",
"sourceKeys": "context.os.name",
"required": true
},
{
"destKey": "i",
"sourceKeys": "context.app.namespace",
"required": true
},
{
"destKey": "sdid",
"sourceKeys": "context.device.id",
"required": false
},
{
"destKey": "is_revenue_event",
"sourceKeys": "properties.is_revenue_event",
"required": false
},
{
"destKey": "n",
"sourceKeys": "event",
"required": true
},
{
"destKey": "av",
"sourceKeys": "context.app.version",
"required": false
},
{
"destKey": "ve",
"sourceKeys": "context.os.version",
"required": false
},
{
"destKey": "os",
"sourceKeys": "properties.os",
"required": true
},
{
"destKey": "ip",
"sourceKeys": ["context.ip", "request_ip"],
"required": true
},
{
"destKey": "use_ip",
"sourceKeys": "properties.use_ip",
"required": false
},
{
"destKey": "install_source",
"sourceKeys": "properties.install_source",
"required": true
},
{
"destKey": "data_sharing_options",
"sourceKeys": "properties.data_sharing_options",
"required": false
},
{
"destKey": "amt",
"sourceKeys": [
"properties.total",
"properties.value",
"properties.revenue",
{
"operation": "multiplication",
"args": [
{
"sourceKeys": "properties.price"
},
{
"sourceKeys": "properties.quantity",
"default": 1
}
]
}
],
"required": false
},
{
"destKey": "cur",
"sourceKeys": "properties.currency",
"required": false
},
{
"destKey": "ua",
"sourceKeys": "context.userAgent",
"required": false
},
{
"destKey": "utime",
"sourceKeys": "timestamp",
"sourceFromGenericMap": true,
"required": false,
"metadata": {
"type": "secondTimestamp"
}
},
{
"destKey": "custom_user_id",
"sourceKeys": "properties.custom_user_id",
"required": false
},
{
"destKey": "install",
"sourceKeys": "properties.install",
"required": false
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
[
{
"destKey": "p",
"sourceKeys": "context.os.name",
"required": true
},
{
"destKey": "i",
"sourceKeys": "context.app.namespace",
"required": true
},
{
"destKey": "sdid",
"sourceKeys": "context.device.id",
"required": false
},
{
"destKey": "av",
"sourceKeys": "context.app.version",
"required": false
},
{
"destKey": "ve",
"sourceKeys": "context.os.version",
"required": false
},
{
"destKey": "os",
"sourceKeys": "properties.os",
"required": true
},
{
"destKey": "ip",
"sourceKeys": ["context.ip", "request_ip"],
"required": true
},
{
"destKey": "use_ip",
"sourceKeys": "properties.use_ip",
"required": false
},
{
"destKey": "install_source",
"sourceKeys": "properties.install_source",
"required": true
},
{
"destKey": "ua",
"sourceKeys": "context.userAgent",
"required": false
},
{
"destKey": "utime",
"sourceKeys": "timestamp",
"sourceFromGenericMap": true,
"required": false,
"metadata": {
"type": "secondTimestamp"
}
},
{
"destKey": "data_sharing_options",
"sourceKeys": "properties.data_sharing_options",
"required": false
},
{
"destKey": "custom_user_id",
"sourceKeys": "properties.custom_user_id",
"required": false
},
{
"destKey": "install",
"sourceKeys": "properties.install",
"required": false
}
]
2 changes: 1 addition & 1 deletion src/v0/destinations/singular/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const responseBuilderSimple = (message, { Config }) => {
}

const sessionEvent = isSessionEvent(Config, eventName);
const { eventAttributes, payload } = platformWisePayloadGenerator(message, sessionEvent);
const { eventAttributes, payload } = platformWisePayloadGenerator(message, sessionEvent, Config);
const endpoint = sessionEvent ? `${BASE_URL}/launch` : `${BASE_URL}/evt`;

// If we have an event where we have an array of Products, example Order Completed
Expand Down
94 changes: 54 additions & 40 deletions src/v0/destinations/singular/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
SINGULAR_EVENT_IOS_EXCLUSION,
BASE_URL,
SUPPORTED_PLATFORM,
SUPPORTED_UNTIY_SUBPLATFORMS,
SESSIONEVENTS,
} = require('./config');
const {
Expand Down Expand Up @@ -85,7 +86,7 @@
* @param {*} sessionEvent
* @returns
*/
const platformWisePayloadGenerator = (message, sessionEvent) => {
const platformWisePayloadGenerator = (message, sessionEvent, Config) => {
let eventAttributes;
const clonedMessage = { ...message };
let platform = getValueFromMessage(clonedMessage, 'context.os.name');
Expand All @@ -99,55 +100,68 @@
platform = 'iOS';
}
platform = platform.toLowerCase();
if (!SUPPORTED_PLATFORM[platform]) {
if (!SUPPORTED_PLATFORM[platform] && !SUPPORTED_UNTIY_SUBPLATFORMS[platform]) {
throw new InstrumentationError(`Platform ${platform} is not supported`);
}

const payload = constructPayload(
clonedMessage,
MAPPING_CONFIG[CONFIG_CATEGORIES[`${typeOfEvent}_${SUPPORTED_PLATFORM[platform]}`].name],
);

if (!payload) {
throw new TransformationError(`Failed to Create ${platform} ${typeOfEvent} Payload`);
}
if (sessionEvent) {
// context.device.adTrackingEnabled = true implies Singular's do not track (dnt)
// to be 0 and vice-versa.
const adTrackingEnabled = getValueFromMessage(
let payload;
if (SUPPORTED_UNTIY_SUBPLATFORMS.includes(platform)) {
payload = constructPayload(
clonedMessage,
'context.device.adTrackingEnabled',
MAPPING_CONFIG[CONFIG_CATEGORIES[`${typeOfEvent}_UNITY`].name],
);
if (adTrackingEnabled === true) {
payload.dnt = 0;
} else {
payload.dnt = 1;
}
// by default, the value of openuri and install_source should be "", i.e empty string if nothing is passed
payload.openuri = clonedMessage.properties.url || '';
if (platform === 'android' || platform === 'Android') {
payload.install_source = clonedMessage.properties.referring_application || '';
}
} else {
// Custom Attribues is not supported by session events
eventAttributes = extractExtraFields(
payload = constructPayload(
clonedMessage,
exclusionList[`${SUPPORTED_PLATFORM[platform]}_${typeOfEvent}_EXCLUSION_LIST`],
MAPPING_CONFIG[CONFIG_CATEGORIES[`${typeOfEvent}_${SUPPORTED_PLATFORM[platform]}`].name],
);
eventAttributes = removeUndefinedAndNullValues(eventAttributes);
}

// If anyone out of value, revenue, total is set,we will have amt in payload
// and we will consider the event as revenue event.
if (!isDefinedAndNotNull(payload.is_revenue_event) && payload.amt) {
payload.is_revenue_event = true;
}
if (!payload) {
throw new TransformationError(`Failed to Create ${platform} ${typeOfEvent} Payload`);

Check warning on line 120 in src/v0/destinations/singular/util.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/singular/util.js#L120

Added line #L120 was not covered by tests
}
if (!SUPPORTED_UNTIY_SUBPLATFORMS.includes(platform)) {
if (sessionEvent) {
// context.device.adTrackingEnabled = true implies Singular's do not track (dnt)
// to be 0 and vice-versa.
const adTrackingEnabled = getValueFromMessage(
clonedMessage,
'context.device.adTrackingEnabled',
);
if (adTrackingEnabled === true) {
payload.dnt = 0;
} else {
payload.dnt = 1;
}
// by default, the value of openuri and install_source should be "", i.e empty string if nothing is passed
payload.openuri = clonedMessage.properties.url || '';
if (platform === 'android' || platform === 'Android') {
payload.install_source = clonedMessage.properties.referring_application || '';
}
} else {
// Custom Attribues is not supported by session events
eventAttributes = extractExtraFields(
clonedMessage,
exclusionList[`${SUPPORTED_PLATFORM[platform]}_${typeOfEvent}_EXCLUSION_LIST`],
);
eventAttributes = removeUndefinedAndNullValues(eventAttributes);

// Singular maps Connection Type to either wifi or carrier
if (clonedMessage.context?.network?.wifi) {
payload.c = 'wifi';
} else {
payload.c = 'carrier';
// If anyone out of value, revenue, total is set,we will have amt in payload
// and we will consider the event as revenue event.
if (!isDefinedAndNotNull(payload.is_revenue_event) && payload.amt) {
payload.is_revenue_event = true;
}
}

// Singular maps Connection Type to either wifi or carrier
if (clonedMessage.context?.network?.wifi) {
payload.c = 'wifi';
} else {
payload.c = 'carrier';
}
} else if (Config.match_id === 'advertisingId') {
payload.match_id = clonedMessage?.context?.device?.advertisingId;

Check warning on line 162 in src/v0/destinations/singular/util.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/singular/util.js#L162

Added line #L162 was not covered by tests
} else if (message.properties.match_id) {
payload.match_id = message.properties.match_id;

Check warning on line 164 in src/v0/destinations/singular/util.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/singular/util.js#L164

Added line #L164 was not covered by tests
}
return { payload, eventAttributes };
};
Expand Down
Loading
Loading