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(intercom): upgrade intercom version from 1.4 to 2.10 #2976

Merged
merged 24 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
68fee5e
feat(intercom): upgrade intercom version from 1.4 to 2.10
mihir-4116 Jan 8, 2024
3f7b61e
chore: code review changes
mihir-4116 Jan 8, 2024
6c2c442
chore: code review changes
mihir-4116 Jan 11, 2024
bb2e49c
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 11, 2024
fcddc25
chore: code review changes
mihir-4116 Jan 11, 2024
25b6045
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 15, 2024
e3cd261
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 17, 2024
0037e63
chore: added backward compatibility for updateLastRequestAt field
mihir-4116 Jan 17, 2024
70ee9bd
chore: intercom backward compatibility support
mihir-4116 Jan 24, 2024
80c89a5
chore: pr conflicts resolved
mihir-4116 Jan 25, 2024
f2fa005
chore: pr conflicts resolved
mihir-4116 Jan 25, 2024
03ac000
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 25, 2024
95d114a
Merge branch 'feat.intercom' of github.com:rudderlabs/rudder-transfor…
mihir-4116 Jan 25, 2024
3522b58
chore: added step to check value of apiVersion
mihir-4116 Jan 25, 2024
e2133fa
chore: change default value of apiVersion to latest
mihir-4116 Jan 25, 2024
851e0e2
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 31, 2024
8ca8822
Merge branch 'develop' into feat.intercom
mihir-4116 Jan 31, 2024
ec6f602
fix: intercom router response
mihir-4116 Feb 1, 2024
4834210
chore: code review changes
mihir-4116 Feb 2, 2024
cccb813
chore: code review changes
mihir-4116 Feb 2, 2024
05472f0
Merge branch 'develop' into feat.intercom
mihir-4116 Feb 2, 2024
2d436b2
Merge branch 'feat.intercom' of github.com:rudderlabs/rudder-transfor…
mihir-4116 Feb 2, 2024
e904dbd
Merge branch 'develop' into feat.intercom
mihir-4116 Feb 2, 2024
702c477
Merge branch 'develop' into feat.intercom
mihir-4116 Feb 2, 2024
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
99 changes: 62 additions & 37 deletions src/cdk/v2/destinations/intercom/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,67 @@ const BASE_AU_ENDPOINT = 'https://api.au.intercom.io';
const SEARCH_CONTACT_ENDPOINT = 'contacts/search';
const CREATE_OR_UPDATE_COMPANY_ENDPOINT = 'companies';

const ReservedUserAttributes = [
'userId',
'role',
'email',
'phone',
'name',
'avatar',
'company',
'ownerId',
'lastName',
'lastname',
'firstName',
'firstname',
'createdAt',
'timestamp',
'lastSeenAt',
'originalTimestamp',
'unsubscribedFromEmails',
];
const ReservedAttributes = {
oldVersionUserAttributes: [
mihir-4116 marked this conversation as resolved.
Show resolved Hide resolved
'userId',
'email',
'phone',
'name',
'createdAt',
'firstName',
'lastName',
'firstname',
'lastname',
'company',
],
newVersionUserAttributes: [
'userId',
'role',
'email',
'phone',
'name',
'avatar',
'company',
'ownerId',
'lastName',
'lastname',
'firstName',
'firstname',
'createdAt',
'timestamp',
'lastSeenAt',
'originalTimestamp',
'unsubscribedFromEmails',
],
oldVersionCompanyAttributes: [
'remoteCreatedAt',
'monthlySpend',
'industry',
'website',
'size',
'plan',
'name',
'userId',
],
newVersionCompanyAttributes: [
'tags',
'size',
'plan',
'name',
'email',
'userId',
'website',
'industry',
'segments',
'userCount',
'createdAt',
'sessionCount',
'monthlySpend',
'remoteCreatedAt',
],
};

const ReservedCompanyAttributes = [
'tags',
'size',
'plan',
'name',
'email',
'userId',
'website',
'industry',
'segments',
'userCount',
'createdAt',
'sessionCount',
'monthlySpend',
'remoteCreatedAt',
];
const ReservedCompanyProperties = ['id', 'name', 'industry'];

const MetadataTypes = { richLink: ['url', 'value'], monetaryAmount: ['amount', 'currency'] };

Expand All @@ -49,8 +74,8 @@ module.exports = {
MetadataTypes,
BASE_EU_ENDPOINT,
BASE_AU_ENDPOINT,
ReservedUserAttributes,
ReservedAttributes,
SEARCH_CONTACT_ENDPOINT,
ReservedCompanyAttributes,
ReservedCompanyProperties,
CREATE_OR_UPDATE_COMPANY_ENDPOINT,
};
208 changes: 138 additions & 70 deletions src/cdk/v2/destinations/intercom/procWorkflow.yaml
koladilip marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ bindings:
path: ../../../../v0/util
- name: addExternalIdToTraits
path: ../../../../v0/util
- path: ../../bindings/jsontemplate

steps:
- name: checkIfProcessed
Expand All @@ -34,29 +35,28 @@ steps:
$.assert(messageType in {{$.EventType.([.IDENTIFY, .TRACK, .GROUP])}}, "message type " + messageType + " is not supported");
$.assertConfig(.destination.Config.apiKey, "Access Token is not present. Aborting");

- name: apiVersion
template: |
const version = $.isDefinedAndNotNull(.destination.Config.apiVersion) ? .destination.Config.apiVersion : "latest";
version;

- name: rEtlPayload
condition: .message.context.mappedToDestination === true
template: |
$.addExternalIdToTraits(.message);
const payload = $.getFieldValueFromMessage(.message, "traits");
$.context.payload = payload;
payload;

- name: searchContact
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} || $.outputs.messageType === {{$.EventType.GROUP}}
condition: ($.outputs.messageType === {{$.EventType.IDENTIFY}} || $.outputs.messageType === {{$.EventType.GROUP}}) && $.outputs.apiVersion !== "1.4"
template: |
const contactId = await $.searchContact(.message, .destination);
contactId;

- name: identifyPayload
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}}
steps:
- name: streaming
condition: "!.message.context.mappedToDestination"
template: |
const timestamp = .message.().(
{{{{$.getGenericPaths("timestamp")}}}};
);
const payload = .message.({
- name: identifyTransformationForLatestVersion
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} && $.outputs.apiVersion !== "1.4" && !.message.context.mappedToDestination
template: |
const payload = .message.({
external_id: {{{{$.getGenericPaths("userIdOnly")}}}},
email: {{{{$.getGenericPaths("email")}}}},
phone: {{{{$.getGenericPaths("phone")}}}},
Expand All @@ -67,59 +67,90 @@ steps:
owner_id: Number(.traits.ownerId || .context.traits.ownerId) || undefined,
unsubscribed_from_emails: .traits.unsubscribedFromEmails || .context.traits.unsubscribedFromEmails
});
payload.name = $.getName(.message);
payload.custom_attributes = .message.context.traits || {};
payload.custom_attributes = $.filterCustomAttributes(payload, "user");
payload.last_seen_at = payload.last_seen_at === undefined && .destination.Config.updateLastRequestAt ? $.toSeconds(timestamp) : payload.last_seen_at;
payload.external_id = !payload.external_id && .destination.Config.sendAnonymousId && .message.anonymousId ? .message.anonymousId : payload.external_id;
$.context.payload = payload
- name: validate
template: |
$.assert($.context.payload.external_id || $.context.payload.email, "Either email or userId is required for Identify call");
- name: prepareFinalPayload
template: |
const endpoint = $.getBaseEndpoint(.destination) + "/" + "contacts";
$.context.requestMethod = $.outputs.searchContact ? 'PUT' : 'POST';
$.context.endpoint = $.outputs.searchContact ? endpoint + "/" + $.outputs.searchContact : endpoint;
$.context.payload = $.removeUndefinedAndNullValues($.context.payload);
!(payload.external_id) && .destination.Config.sendAnonymousId ? payload.external_id = .message.anonymousId;
payload;

- name: trackEtlPayload
condition: $.outputs.messageType === {{$.EventType.TRACK}}
steps:
- name: streaming
condition: "!.message.context.mappedToDestination"
template: |
let payload = .message.({
- name: identifyPayloadForLatestVersion
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} && $.outputs.apiVersion !== "1.4"
template: |
const payload = .message.context.mappedToDestination ? $.outputs.rEtlPayload : $.outputs.identifyTransformationForLatestVersion;
payload.name = $.getName(.message);
payload.custom_attributes = .message.context.traits || {};
payload.custom_attributes = $.filterCustomAttributes(payload, "user", .destination);
payload.external_id = !payload.external_id && .destination.Config.sendAnonymousId && .message.anonymousId ? .message.anonymousId : payload.external_id;
$.context.payload = payload;
$.assert($.context.payload.external_id || $.context.payload.email, "Either email or userId is required for Identify call");
const endpoint = $.getBaseEndpoint(.destination) + "/" + "contacts";
$.context.requestMethod = $.outputs.searchContact ? 'PUT' : 'POST';
$.context.endpoint = $.outputs.searchContact ? endpoint + "/" + $.outputs.searchContact : endpoint;
$.context.payload = $.removeUndefinedAndNullValues($.context.payload);

- name: identifyTransformationForOlderVersion
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} && $.outputs.apiVersion === "1.4" && !.message.context.mappedToDestination
template: |
const payload = .message.({
user_id: {{{{$.getGenericPaths("userIdOnly")}}}},
email: {{{{$.getGenericPaths("email")}}}},
phone: {{{{$.getGenericPaths("phone")}}}},
signed_up_at: $.toSeconds(.traits.createdAt || .context.traits.createdAt),
last_seen_user_agent: .context.userAgent,
});
!(payload.user_id) && .destination.Config.sendAnonymousId ? payload.user_id = .message.anonymousId;
payload;

- name: identifyPayloadForOlderVersion
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} && $.outputs.apiVersion === "1.4"
template: |
let payload = .message.context.mappedToDestination ? $.outputs.rEtlPayload : $.outputs.identifyTransformationForOlderVersion;
payload = {
...payload,
name : $.getName(.message),
custom_attributes : .message.traits || .message.context.traits || {},
update_last_request_at: typeof .destination.Config.updateLastRequestAt === 'boolean' ? .destination.Config.updateLastRequestAt : true
}
payload.companies = $.getCompaniesList(payload);
payload.custom_attributes = !.message.context.mappedToDestination ? $.filterCustomAttributes(payload, "user", .destination);
payload.user_id = !payload.user_id && .destination.Config.sendAnonymousId && .message.anonymousId ? .message.anonymousId : payload.user_id;
$.context.payload = payload;
$.assert($.context.payload.user_id || $.context.payload.email, "Either of `email` or `userId` is required for Identify call");
$.context.requestMethod = 'POST';
$.context.endpoint = $.getBaseEndpoint(.destination) + "/" + "users";
$.context.payload = $.removeUndefinedAndNullValues($.context.payload);

- name: trackTransformation
condition: $.outputs.messageType === {{$.EventType.TRACK}} && !.message.context.mappedToDestination
template: |
const timestamp = .message.().(
{{{{$.getGenericPaths("timestamp")}}}};
);
const payload = .message.({
event_name: .event,
created_at: $.toSeconds({{{{$.getGenericPaths("timestamp")}}}}),
user_id: {{{{$.getGenericPaths("userIdOnly")}}}},
email: {{{{$.getGenericPaths("email")}}}},
id: .properties.id || .traits.id,
metadata: .properties
})
payload = $.addMetadataToPayload(payload);
payload.user_id = !(payload.user_id) && .destination.Config.sendAnonymousId && .message.anonymousId ? .message.anonymousId : payload.user_id;
$.context.payload = payload
- name: validate
template: |
$.assert($.context.payload.event_name, "Event name is required for track call");
$.assert($.context.payload.user_id || $.context.payload.email, "Either email or userId is required for Track call");
- name: prepareFinalPayload
template: |
$.context.requestMethod = 'POST';
$.context.endpoint = $.getBaseEndpoint(.destination) + "/" + "events";
$.context.payload = $.removeUndefinedAndNullValues($.context.payload);

- name: groupPayload
condition: $.outputs.messageType === {{$.EventType.GROUP}}
steps:
- name: validateMessage
template: |
$.assert(.message.groupId, "groupId is required for group call");
- name: streaming
condition: "!.message.context.mappedToDestination"
template: |
const payload = .message.({
});
$.outputs.apiVersion !== "1.4" ? payload.id = .message.properties.id || .message.traits.id;
$.outputs.apiVersion !== "1.4" ? payload.created_at = $.toSeconds(timestamp);
$.outputs.apiVersion === "1.4" ? payload.created = $.toSeconds(timestamp);
!(payload.user_id) && .destination.Config.sendAnonymousId ? payload.user_id = .message.anonymousId;
payload;

- name: trackPayload
condition: $.outputs.messageType === {{$.EventType.TRACK}}
template: |
let payload = .message.context.mappedToDestination ? $.outputs.rEtlPayload : $.outputs.trackTransformation;
payload = $.addMetadataToPayload(payload);
$.context.payload = payload;
$.assert($.context.payload.event_name, "Event name is required for track call");
$.assert($.context.payload.user_id || $.context.payload.email, "Either email or userId is required for Track call");
$.context.requestMethod = 'POST';
$.context.endpoint = $.getBaseEndpoint(.destination) + "/" + "events";
$.context.payload = $.removeUndefinedAndNullValues($.context.payload);

- name: groupTransformation
condition: $.outputs.messageType === {{$.EventType.GROUP}} && !.message.context.mappedToDestination
template: |
const payload = .message.({
company_id: {{{{$.getGenericPaths("groupId")}}}},
name: {{{{$.getGenericPaths("name")}}}},
website: {{{{$.getGenericPaths("website")}}}},
Expand All @@ -128,9 +159,18 @@ steps:
industry: .traits.industry || .context.traits.industry,
monthly_spend: .traits.monthlySpend || .context.traits.monthlySpend ? Number(.traits.monthlySpend || .context.traits.monthlySpend) : undefined,
remote_created_at: .traits.remoteCreatedAt || .context.traits.remoteCreatedAt ? Number(.traits.remoteCreatedAt || .context.traits.remoteCreatedAt) : undefined
})
});
payload;

- name: groupPayloadForLatestVersion
condition: $.outputs.messageType === {{$.EventType.GROUP}} && $.outputs.apiVersion !== "1.4"
steps:
- name: validateMessageAndPreparePayload
template: |
$.assert(.message.groupId, "groupId is required for group call");
const payload = .message.context.mappedToDestination ? $.outputs.rEtlPayload : $.outputs.groupTransformation;
payload.custom_attributes = .message.traits || {};
payload.custom_attributes = $.filterCustomAttributes(payload, "company");
payload.custom_attributes = $.filterCustomAttributes(payload, "company", .destination);
$.context.payload = payload;
- name: whenSearchContactFound
condition: $.isDefinedAndNotNull($.outputs.searchContact)
Expand All @@ -149,14 +189,42 @@ steps:
- name: prepareFinalPayload
template:
$.context.requestMethod = 'POST';
$.removeUndefinedAndNullValues($.context.payload)
$.removeUndefinedAndNullValues($.context.payload);

- name: buildResponseForProcessTransformation
description: build response
- name: groupPayloadForOlderVersion
condition: $.outputs.messageType === {{$.EventType.GROUP}} && $.outputs.apiVersion === "1.4"
template: |
$.context.response = [];
const response = $.defaultRequestConfig();
response.body.JSON = $.removeUndefinedAndNullValues($.context.payload);
response.endpoint = $.context.endpoint;
response.method = $.context.requestMethod;
response.headers = $.getHeaders(.destination);
response;
let payload = .message.context.mappedToDestination ? $.outputs.rEtlPayload : $.outputs.groupTransformation;
payload = {
...payload,
custom_attributes : $.getFieldValueFromMessage(.message, "traits") || {}
}
payload.custom_attributes = $.filterCustomAttributes(payload, "company", .destination);
response.body.JSON = $.removeUndefinedAndNullValues(payload);
response.endpoint = $.getBaseEndpoint(.destination) + "/" + "companies";
response.headers = $.getHeaders(.destination, $.outputs.apiVersion);
response.method = "POST";
response.userId = .message.anonymousId;
$.context.response.push(response);
const attachUserAndCompanyResponse = $.attachUserAndCompany(.message, .destination.Config);
attachUserAndCompanyResponse ? attachUserAndCompanyResponse.userId = .message.anonymousId;
attachUserAndCompanyResponse ? $.context.response.push(attachUserAndCompanyResponse);

- name: buildResponseForProcessTransformation
description: Build response for multiple transformed event
condition: $.context.response && $.context.response.length > 0
template: |
$.context.response;
else:
name: buildResponseForProcessTransformation
description: Build response for single transformed event
template: |
const response = $.defaultRequestConfig();
response.body.JSON = $.context.payload;
response.endpoint = $.context.endpoint;
response.method = $.context.requestMethod;
response.headers = $.getHeaders(.destination, $.outputs.apiVersion);
$.outputs.apiVersion === "1.4" && $.outputs.messageType !== {{$.EventType.GROUP}} ? response.userId = .message.anonymousId;
response;
Loading
Loading