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

chore(release): pull hotfix-release/v1.82.2 into main #3816

Merged
merged 3 commits into from
Oct 18, 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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [1.82.2](https://github.com/rudderlabs/rudder-transformer/compare/v1.82.1...v1.82.2) (2024-10-18)


### Bug Fixes

* add missing fields to pinterest_tag mapping ([#3814](https://github.com/rudderlabs/rudder-transformer/issues/3814)) ([88c6175](https://github.com/rudderlabs/rudder-transformer/commit/88c6175391cf4575a57936aced898465ad78b55e))

### [1.82.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.82.0...v1.82.1) (2024-10-16)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rudder-transformer",
"version": "1.82.1",
"version": "1.82.2",
"description": "",
"homepage": "https://github.com/rudderlabs/rudder-transformer#readme",
"bugs": {
Expand Down
19 changes: 19 additions & 0 deletions src/cdk/v2/destinations/pinterest_tag/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const ENDPOINT = 'https://ct.pinterest.com/events/v3';
// ref: https://developers.pinterest.com/docs/api/v5/#tag/conversion_events
const getV5EventsEndpoint = (adAccountId) =>
`https://api.pinterest.com/v5/ad_accounts/${adAccountId}/events`;

const API_VERSION = {
v3: 'legacyApi',
v5: 'newApi',
};

// ref: https://s.pinimg.com/ct/docs/conversions_api/dist/v3.html
const MAX_BATCH_SIZE = 1000;

module.exports = {
ENDPOINT,
MAX_BATCH_SIZE,
getV5EventsEndpoint,
API_VERSION,
};
24 changes: 18 additions & 6 deletions src/cdk/v2/destinations/pinterest_tag/procWorkflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ bindings:
path: ../../../../constants
- path: ../../bindings/jsontemplate
exportAll: true
- path: ../../../../v0/destinations/pinterest_tag/utils
- path: ../../../../v0/destinations/pinterest_tag/config
- path: ./utils
- path: ./config
- name: removeUndefinedValues
path: ../../../../v0/util
- name: removeUndefinedAndNullAndEmptyValues
Expand Down Expand Up @@ -66,7 +66,10 @@ steps:
"opt_out": .context.device.adTrackingEnabled !== undefined ? !.context.device.adTrackingEnabled,
"event_id": $.getOneByPaths(., ^.destination.Config.deduplicationKey) ?? .messageId,
"app_id": ^.destination.Config.appId,
"advertiser_id": ^.destination.Config.advertiserId
"advertiser_id": ^.destination.Config.advertiserId,
"partner_name": .properties.partnerName,
"device_carrier": .context.network.carrier,
"wifi": .context.network.wifi
});
$.outputs.apiVersion === {{$.API_VERSION.v5}} ? commonFields = commonFields{~["advertiser_id"]};
$.removeUndefinedValues(commonFields)
Expand Down Expand Up @@ -103,7 +106,8 @@ steps:
"client_ip_address": .context.ip ?? .request_ip,
"client_user_agent": .context.userAgent,
"external_id": {{{{$.getGenericPaths("userId")}}}},
"click_id": .properties.clickId
"click_id": .properties.clickId,
"partner_id": .traits.partnerId ?? .context.traits.partnerId
});
!.destination.Config.sendExternalId ? userFields = userFields{~["external_id"]} : null;
userFields = $.removeUndefinedAndNullAndEmptyValues(userFields);
Expand All @@ -129,7 +133,11 @@ steps:
"num_items": .properties.numOfItems && Number(.properties.numOfItems),
"order_id": .properties.order_id,
"search_string": .properties.query,
"opt_out_type": .properties.optOutType
"opt_out_type": .properties.optOutType,
"content_name": .properties.contentName,
"content_category": .properties.contentCategory,
"content_brand": .properties.contentBrand,
"np": .properties.np
});
$.removeUndefinedValues(customFields)

Expand All @@ -143,7 +151,11 @@ steps:
"content_ids": products.(.product_id ?? .sku ?? .id)[],
"contents": [email protected].({
"quantity": Number(.quantity ?? prop.quantity ?? 1),
"item_price": String(.price ?? prop.price)
"item_price": String(.price ?? prop.price),
"item_name": String(.name),
"id": .product_id ?? .sku,
"item_category": .category,
"item_brand": .brand
})[]
}
else:
Expand Down
2 changes: 1 addition & 1 deletion src/cdk/v2/destinations/pinterest_tag/rtWorkflow.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
bindings:
- path: ../../../../v0/destinations/pinterest_tag/config
- path: ./config
- name: batchMultiplexedEvents
path: ../../../../v0/util/index
steps:
Expand Down
150 changes: 150 additions & 0 deletions src/cdk/v2/destinations/pinterest_tag/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/* eslint-disable no-param-reassign */
const sha256 = require('sha256');
const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib');

const { API_VERSION } = require('./config');

const VALID_ACTION_SOURCES = ['app_android', 'app_ios', 'web', 'offline'];

const ecomEventMaps = [
{
src: ['order completed'],
dest: 'checkout',
},
{
src: ['product added'],
dest: 'add_to_cart',
},
{
src: ['products searched', 'product list filtered'],
dest: 'search',
},
];

const USER_NON_ARRAY_PROPERTIES = ['client_user_agent', 'client_ip_address'];

const getHashedValue = (key, value) => {
switch (key) {
case 'em':
case 'ct':
case 'st':
case 'country':
case 'ln':
case 'fn':
case 'ge':
value = Array.isArray(value)
? value.map((val) => val.toString().trim().toLowerCase())
: value.toString().trim().toLowerCase();
break;
case 'ph':
// phone numbers should only contain digits & should not contain leading zeros
value = Array.isArray(value)
? value.map((val) => val.toString().replace(/\D/g, '').replace(/^0+/, ''))
: value.toString().replace(/\D/g, '').replace(/^0+/, '');
break;
case 'zp':
// zip fields should only contain digits
value = Array.isArray(value)
? value.map((val) => val.toString().trim().replace(/\D/g, ''))
: value.toString().replace(/\D/g, '');
break;
case 'hashed_maids':
case 'external_id':
case 'db':
// no action needed on value
break;
default:
return String(value);
}
return Array.isArray(value) ? value.map((val) => sha256(val)) : [sha256(value)];
};

/**
*
* @param {*} userPayload Payload mapped from user fields
* @returns
* Further Processing the user fields following the instructions of Pinterest Conversion API
* Ref: https://s.pinimg.com/ct/docs/conversions_api/dist/v3.html
*/
const processUserPayload = (userPayload) => {
Object.keys(userPayload).forEach((key) => {
userPayload[key] = getHashedValue(key, userPayload[key]);
});
return userPayload;
};

/**
*
* @param {*} eventName // ["WatchVideo", "ViewCategory", "Custom"]
* @returns // ["watch_video", "view_category", "custom""]
* This function will return the snake case name of the destination config mapped event
*/
const convertToSnakeCase = (eventName) =>
eventName.map((str) =>
str
.replace(/([a-z])([A-Z])/g, '$1_$2')
.replace(/\s+/g, '_')
.toLowerCase(),
);

/**
*
* @param {*} userPayload
* @param {*} message
* @returns converts every single hashed user data property to array, except for
* "client_user_agent", "client_ip_address"
*
*/
const processHashedUserPayload = (userPayload, message) => {
const processedHashedUserPayload = {};
Object.keys(userPayload).forEach((key) => {
if (!USER_NON_ARRAY_PROPERTIES.includes(key)) {
if (Array.isArray(userPayload[key])) {
processedHashedUserPayload[key] = [...userPayload[key]];
} else {
processedHashedUserPayload[key] = [userPayload[key]];
}
} else {
processedHashedUserPayload[key] = userPayload[key];
}
});
// multiKeyMap will works on only specific values like m, male, MALE, f, F, Female
// if hashed data is sent from the user, it is directly set over here
const gender = message.traits?.gender || message.context?.traits?.gender;
if (gender && Array.isArray(gender)) {
processedHashedUserPayload.ge = [...gender];
} else if (gender) {
processedHashedUserPayload.ge = [gender];
}
return processedHashedUserPayload;
};

const validateInput = (message, { Config }) => {
const { apiVersion = API_VERSION.v3, advertiserId, adAccountId, conversionToken } = Config;
if (apiVersion === API_VERSION.v3 && !advertiserId) {
throw new ConfigurationError('Advertiser Id not found. Aborting');

Check warning on line 125 in src/cdk/v2/destinations/pinterest_tag/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/pinterest_tag/utils.js#L125

Added line #L125 was not covered by tests
}

if (apiVersion === API_VERSION.v5) {
if (!adAccountId) {
throw new ConfigurationError('Ad Account ID not found. Aborting');

Check warning on line 130 in src/cdk/v2/destinations/pinterest_tag/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/pinterest_tag/utils.js#L130

Added line #L130 was not covered by tests
}

if (!conversionToken) {
throw new ConfigurationError('Conversion Token not found. Aborting');

Check warning on line 134 in src/cdk/v2/destinations/pinterest_tag/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/pinterest_tag/utils.js#L134

Added line #L134 was not covered by tests
}
}

if (!message.type) {
throw new InstrumentationError('Event type is required');

Check warning on line 139 in src/cdk/v2/destinations/pinterest_tag/utils.js

View check run for this annotation

Codecov / codecov/patch

src/cdk/v2/destinations/pinterest_tag/utils.js#L139

Added line #L139 was not covered by tests
}
};

module.exports = {
processUserPayload,
processHashedUserPayload,
VALID_ACTION_SOURCES,
ecomEventMaps,
convertToSnakeCase,
validateInput,
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { processUserPayload } = require('../../../../src/v0/destinations/pinterest_tag/utils');
const { processUserPayload } = require('./utils');

const userFields = [
{
Expand Down
31 changes: 0 additions & 31 deletions src/v0/destinations/pinterest_tag/config.js

This file was deleted.

This file was deleted.

Loading
Loading