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: for reddit adding currency and value for addToCart, viewConent event as well #3239

Merged
merged 5 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 4 additions & 3 deletions src/cdk/v2/destinations/reddit/procWorkflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bindings:
path: ../../../../v0/util/index
- name: OAuthSecretError
path: '@rudderstack/integrations-lib'
- path: ./utils

steps:
- name: validateInput
Expand Down Expand Up @@ -56,14 +57,14 @@ steps:
const event_type = (eventNames.length === 0 || eventNames[0]==="") ? ({"tracking_type": "Custom", "custom_event_name": event}): ({tracking_type: eventNames[0]});

- name: customFields
condition: $.outputs.prepareTrackPayload.eventType.tracking_type === "Purchase"
condition: $.outputs.prepareTrackPayload.eventType.tracking_type in ['Purchase', 'AddToCart', 'ViewContent']
reference: 'https://ads-api.reddit.com/docs/v2/#tag/Conversions/paths/~1api~1v2.0~1conversions~1events~1%7Baccount_id%7D/post'
template: |
const revenue_in_cents = .message.properties.revenue ? Math.round(Number(.message.properties.revenue)*100)
const revenue_in_cents = $.calculateRevenueField($.outputs.prepareTrackPayload.eventType.tracking_type,^.message.properties)
const customFields = .message.().({
"currency": .properties.currency,
"value_decimal": revenue_in_cents ? revenue_in_cents / 100,
"item_count": (Array.isArray(.properties.products) && .properties.products.length) || (.properties.itemCount && Number(.properties.itemCount)),
"item_count": $.outputs.prepareTrackPayload.eventType.tracking_type === 'Purchase' ? (Array.isArray(.properties.products) && .properties.products.length) || (.properties.itemCount && Number(.properties.itemCount)) : null,
"value": revenue_in_cents,
"conversion_id": .properties.conversionId || .messageId,
});
Expand Down
53 changes: 53 additions & 0 deletions src/cdk/v2/destinations/reddit/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,59 @@
const batchedEvents = batchEventChunks(eventChunks);
return batchedEvents;
};

const calculateRevenue = (properties) => {
// Check if working with products array
if (properties?.products && properties.products.length > 0) {
// Check if all product prices are undefined
if (properties.products.every((product) => product.price === undefined)) {
return null; // Return null if all product prices are undefined
}
// Proceed with calculation if not all prices are undefined
return properties.products.reduce(
(acc, product) => acc + (product.price || 0) * (product.quantity || 1),
0,
);
}
// For single product scenario, check if price is undefined
if (properties.price === undefined) {
return null; // Return null if price is undefined

Check warning on line 47 in src/cdk/v2/destinations/reddit/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/reddit/utils.js#L47

Added line #L47 was not covered by tests
}
// Proceed with calculation if price is defined
return properties.price * (properties.quantity ?? 1);
};

const calculateRevenueField = (eventType, properties) => {
let revenueInCents;
switch (eventType) {
case 'Purchase':
revenueInCents =
properties.revenue && !Number.isNaN(properties.revenue)
? Math.round(Number(properties?.revenue) * 100)
: null;

Check warning on line 60 in src/cdk/v2/destinations/reddit/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/reddit/utils.js#L60

Added line #L60 was not covered by tests
break;
case 'AddToCart':
revenueInCents =
properties.price && !Number.isNaN(properties.price)
? Math.round(Number(properties?.price) * Number(properties?.quantity || 1) * 100)
: null;

Check warning on line 66 in src/cdk/v2/destinations/reddit/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/reddit/utils.js#L66

Added line #L66 was not covered by tests
break;
default:
// for viewContent
// eslint-disable-next-line no-case-declarations
const revenue = calculateRevenue(properties);
revenueInCents = revenue ? revenue * 100 : null;
break;
}

if (lodash.isNaN(revenueInCents)) {
return null;
}
// Return the value as it is if it's not NaN
return revenueInCents;
};
module.exports = {
batchEvents,
calculateRevenueField,
calculateRevenue,
};
121 changes: 121 additions & 0 deletions src/cdk/v2/destinations/reddit/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
const { calculateRevenue, calculateRevenueField } = require('./utils');

describe('calculateRevenue', () => {
// Calculates revenue for a single product with defined price and quantity
it('should calculate revenue for a single product with defined price and quantity', () => {
const properties = {
price: 10,
quantity: 2,
};

const result = calculateRevenue(properties);

expect(result).toBe(20);
});

// Returns null for properties parameter being undefined
it('should return null for price parameter being undefined', () => {
const properties = { products: [{ quantity: 1 }] };

const result = calculateRevenue(properties);

expect(result).toBeNull();
});

// Calculates revenue for a single product with defined price and default quantity
it('should calculate revenue for a single product with defined price and default quantity', () => {
const properties = {
price: 10,
};

const result = calculateRevenue(properties);

expect(result).toBe(10);
});

// Calculates revenue for multiple products with defined prices and quantities
it('should calculate revenue for multiple products with defined prices and quantities', () => {
const properties = {
products: [{ price: 10, quantity: 2 }, { quantity: 3 }],
};

const result = calculateRevenue(properties);

expect(result).toBe(20);
shrouti1507 marked this conversation as resolved.
Show resolved Hide resolved
});

// Calculates revenue for multiple products with defined prices and default quantities
it('should calculate revenue for multiple products with defined prices and default quantities', () => {
const properties = {
products: [{ price: 10 }, { price: 5 }],
};

const result = calculateRevenue(properties);

expect(result).toBe(15);
});
});

describe('calculateRevenueField', () => {
// Returns revenue in cents for Purchase event type with valid revenue property
it('should return revenue in cents when Purchase event type has valid revenue property', () => {
const eventType = 'Purchase';
const properties = {
revenue: '10.50',
};
const expected = 1050;

const result = calculateRevenueField(eventType, properties);

expect(result).toBe(expected);
});

// Returns null for Purchase event type with revenue property as non-numeric string
it('should return null when Purchase event type has revenue property as non-numeric string', () => {
const eventType = 'Purchase';
const properties = {
revenue: 'invalid',
};
const expected = null;

const result = calculateRevenueField(eventType, properties);

expect(result).toBe(expected);
});

// Returns revenue in cents for AddToCart event type with valid price and quantity properties
it('should return revenue in cents when AddToCart event type has valid price and quantity properties', () => {
const eventType = 'AddToCart';
const properties = {
price: '10.50',
quantity: 2,
};
const expected = 2100;

const result = calculateRevenueField(eventType, properties);

expect(result).toBe(expected);
});

// Returns revenue in cents for ViewContent event type with valid properties
it('should return revenue in cents when ViewContent event type has valid properties', () => {
const eventType = 'ViewContent';
const properties = {
products: [
{
price: '10.50',
quantity: 2,
},
{
price: '5.25',
quantity: 3,
},
],
};
const expected = 3675;

const result = calculateRevenueField(eventType, properties);

expect(result).toBe(expected);
});
});
6 changes: 6 additions & 0 deletions test/integrations/destinations/reddit/processor/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ export const data = [
},
event_metadata: {
item_count: 0,
value: 2600,
value_decimal: 26,
products: [
{
id: '017c6f5d5cf86a4b22432066',
Expand Down Expand Up @@ -581,6 +583,8 @@ export const data = [
},
event_metadata: {
item_count: 5,
value: 24995,
value_decimal: 249.95,
products: [
{
id: '622c6f5d5cf86a4c77358033',
Expand Down Expand Up @@ -847,6 +851,8 @@ export const data = [
},
event_metadata: {
item_count: 5,
value: 24995,
value_decimal: 249.95,
products: [
{
id: '622c6f5d5cf86a4c77358033',
Expand Down
8 changes: 8 additions & 0 deletions test/integrations/destinations/reddit/router/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ export const data = [
properties: {
list_id: 'list1',
category: "What's New",
value: 2600,
value_decimal: 26,
products: [
{
product_id: '017c6f5d5cf86a4b22432066',
Expand Down Expand Up @@ -230,6 +232,8 @@ export const data = [
},
event_metadata: {
item_count: 0,
value: 2600,
value_decimal: 26,
products: [
{
id: '017c6f5d5cf86a4b22432066',
Expand Down Expand Up @@ -259,6 +263,8 @@ export const data = [
},
event_metadata: {
item_count: 5,
value: 24995,
value_decimal: 249.95,
products: [
{
id: '622c6f5d5cf86a4c77358033',
Expand Down Expand Up @@ -349,6 +355,8 @@ export const data = [
properties: {
list_id: 'list1',
category: "What's New",
value: 2600,
value_decimal: 26,
products: [
{
product_id: '017c6f5d5cf86a4b22432066',
Expand Down
Loading