-
Notifications
You must be signed in to change notification settings - Fork 113
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 #2867
Changes from 25 commits
a01a96e
fb11bca
33bdccd
10d7838
e3a269f
c619099
fe15ecc
071a395
1151d90
9c23c39
1edac22
a6ff85a
345853b
39e93ce
a4bdb14
3c3dd42
1fbdacc
ee6aab1
2759026
170e094
9b8ec30
c9465ac
fbdf23d
1b9900e
2b880d6
75e8dc5
e3325da
c47bf6d
c9684ec
561b4ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
const BASE_ENDPOINT = 'https://api.intercom.io'; | ||
const BASE_EU_ENDPOINT = 'https://api.eu.intercom.io'; | ||
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', | ||
'originalTimestamp', | ||
'unsubscribedFromEmails', | ||
]; | ||
|
||
const ReservedCompanyAttributes = [ | ||
'tags', | ||
'size', | ||
'plan', | ||
'name', | ||
'email', | ||
'userId', | ||
'website', | ||
'industry', | ||
'segments', | ||
'userCount', | ||
'createdAt', | ||
'sessionCount', | ||
'monthlySpend', | ||
'remoteCreatedAt', | ||
]; | ||
|
||
const MetadataTypes = { richLink: ['url', 'value'], monetaryAmount: ['amount', 'currency'] }; | ||
|
||
module.exports = { | ||
BASE_ENDPOINT, | ||
MetadataTypes, | ||
BASE_EU_ENDPOINT, | ||
BASE_AU_ENDPOINT, | ||
ReservedUserAttributes, | ||
SEARCH_CONTACT_ENDPOINT, | ||
ReservedCompanyAttributes, | ||
CREATE_OR_UPDATE_COMPANY_ENDPOINT, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
bindings: | ||
- name: EventType | ||
path: ../../../../constants | ||
- path: ./utils | ||
exportAll: true | ||
- path: ../../bindings/jsontemplate | ||
exportAll: true | ||
- name: defaultRequestConfig | ||
path: ../../../../v0/util | ||
- name: removeUndefinedAndNullValues | ||
path: ../../../../v0/util | ||
- name: getFieldValueFromMessage | ||
path: ../../../../v0/util | ||
- name: isDefinedAndNotNull | ||
path: ../../../../v0/util | ||
- name: addExternalIdToTraits | ||
path: ../../../../v0/util | ||
|
||
steps: | ||
- name: checkIfProcessed | ||
condition: .message.statusCode | ||
template: | | ||
$.batchMode ? .message.body.JSON : .message; | ||
onComplete: return | ||
|
||
- name: messageType | ||
template: | | ||
.message.type.toLowerCase(); | ||
|
||
- name: validateInput | ||
template: | | ||
let messageType = $.outputs.messageType; | ||
$.assert(messageType, "message Type is not present. Aborting"); | ||
$.assert(messageType in {{$.EventType.([.IDENTIFY, .TRACK, .GROUP])}}, "message type " + messageType + " is not supported"); | ||
$.assertConfig(.destination.Config.apiKey, "Access Token is not present. Aborting"); | ||
|
||
- name: rEtlPayload | ||
condition: .message.context.mappedToDestination === true | ||
template: | | ||
$.addExternalIdToTraits(.message); | ||
const payload = $.getFieldValueFromMessage(.message, "traits"); | ||
payload; | ||
|
||
- name: searchContact | ||
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} || $.outputs.messageType === {{$.EventType.GROUP}} | ||
template: | | ||
const contactId = await $.searchContact(.message, .destination); | ||
contactId; | ||
|
||
- name: identifyEtlPayload | ||
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} && !.message.context.mappedToDestination | ||
template: | | ||
const payload = .message.({ | ||
external_id: {{{{$.getGenericPaths("userIdOnly")}}}}, | ||
email: {{{{$.getGenericPaths("email")}}}}, | ||
phone: {{{{$.getGenericPaths("phone")}}}}, | ||
avatar: {{{{$.getGenericPaths("avatar")}}}}, | ||
last_seen_at: $.toSeconds({{{{$.getGenericPaths("timestamp")}}}}), | ||
role: .traits.role || .context.traits.role, | ||
signed_up_at: $.toSeconds(.traits.createdAt || .context.traits.createdAt), | ||
owner_id: .traits.ownerId || .context.traits.ownerId ? 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.external_id = !(payload.external_id) && .destination.Config.sendAnonymousId && .message.anonymousId ? .message.anonymousId : payload.external_id; | ||
payload; | ||
|
||
- name: prepareIdentifyPayload | ||
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} | ||
template: | | ||
const endpoint = $.getBaseEndpoint(.destination) + "/" + "contacts"; | ||
$.context.payload = .message.context.mappedToDestination === true ? $.outputs.rEtlPayload : $.outputs.identifyEtlPayload; | ||
$.context.requestMethod = $.outputs.searchContact ? 'PUT' : 'POST'; | ||
$.context.endpoint = $.outputs.searchContact ? endpoint + "/" + $.outputs.searchContact : endpoint; | ||
$.context.payload = $.removeUndefinedAndNullValues($.context.payload); | ||
|
||
- name: validateIdentifyPayload | ||
condition: $.outputs.messageType === {{$.EventType.IDENTIFY}} | ||
template: | | ||
$.assert($.context.payload.external_id || $.context.payload.email, "Either email or userId is required for Identify call"); | ||
|
||
- name: trackEtlPayload | ||
condition: $.outputs.messageType === {{$.EventType.TRACK}} && !.message.context.mappedToDestination | ||
template: | | ||
let 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; | ||
payload; | ||
|
||
- name: prepareTrackPayload | ||
condition: $.outputs.messageType === {{$.EventType.TRACK}} | ||
template: | | ||
$.context.payload = .message.context.mappedToDestination === true ? $.outputs.rEtlPayload : $.outputs.trackEtlPayload; | ||
$.context.requestMethod = 'POST'; | ||
$.context.endpoint = $.getBaseEndpoint(.destination) + "/" + "events"; | ||
$.context.payload = $.removeUndefinedAndNullValues($.context.payload); | ||
|
||
- name: validateTrackPayload | ||
condition: $.outputs.messageType === {{$.EventType.TRACK}} | ||
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: groupEtlPayload | ||
condition: $.outputs.messageType === {{$.EventType.GROUP}} && !.message.context.mappedToDestination | ||
template: | | ||
const payload = .message.({ | ||
company_id: {{{{$.getGenericPaths("groupId")}}}}, | ||
name: {{{{$.getGenericPaths("name")}}}}, | ||
website: {{{{$.getGenericPaths("website")}}}}, | ||
plan: .traits.plan || .context.traits.plan, | ||
size: Number(.traits.size || .context.traits.size), | ||
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.custom_attributes = .message.traits || {}; | ||
payload.custom_attributes = $.filterCustomAttributes(payload, "company"); | ||
payload; | ||
|
||
- name: prepareAddUserToCompanyPayload | ||
condition: $.outputs.messageType === {{$.EventType.GROUP}} && $.isDefinedAndNotNull($.outputs.searchContact) | ||
template: | | ||
$.assert(.message.groupId, "groupId is required for group call"); | ||
let payload = .message.context.mappedToDestination === true ? $.outputs.rEtlPayload : $.outputs.groupEtlPayload; | ||
const contactId = $.outputs.searchContact; | ||
const companyId = await $.createOrUpdateCompany(payload, .destination); | ||
$.assert(companyId, "Unable to add user to company"); | ||
payload.requestBodyJson = { | ||
id: companyId | ||
} | ||
payload.endpoint = $.getBaseEndpoint(.destination) + "/" + "contacts" + "/" + contactId + "/" + "companies"; | ||
payload; | ||
|
||
- name: prepareCreateOrUpdateCompanyPayload | ||
condition: $.outputs.messageType === {{$.EventType.GROUP}} && !$.isDefinedAndNotNull($.outputs.searchContact) | ||
template: | | ||
$.assert(.message.groupId, "groupId is required for group call"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is required because groupId is mapped with company_id and intercom does lookup based on company_id. so it's always recommended to send groupId |
||
let payload = { | ||
requestBodyJson: .message.context.mappedToDestination === true ? $.outputs.rEtlPayload : $.outputs.groupEtlPayload | ||
} | ||
payload.endpoint = $.getBaseEndpoint(.destination) + "/" + "companies"; | ||
payload; | ||
|
||
- name: prepareGroupPayload | ||
condition: $.outputs.messageType === {{$.EventType.GROUP}} | ||
template: | | ||
$.context.payload = $.isDefinedAndNotNull($.outputs.searchContact) ? $.outputs.prepareAddUserToCompanyPayload.requestBodyJson : $.outputs.prepareCreateOrUpdateCompanyPayload.requestBodyJson; | ||
$.context.requestMethod = 'POST'; | ||
$.context.endpoint = $.isDefinedAndNotNull($.outputs.searchContact) ? $.outputs.prepareAddUserToCompanyPayload.endpoint : $.outputs.prepareCreateOrUpdateCompanyPayload.endpoint; | ||
$.context.payload = $.removeUndefinedAndNullValues($.context.payload); | ||
|
||
- name: buildResponseForProcessTransformation | ||
description: build response | ||
template: | | ||
const response = $.defaultRequestConfig(); | ||
response.body.JSON = $.removeUndefinedAndNullValues($.context.payload); | ||
response.endpoint = $.context.endpoint; | ||
response.method = $.context.requestMethod; | ||
response.headers = $.getHeaders(.destination); | ||
response; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
bindings: | ||
- name: handleRtTfSingleEventError | ||
path: ../../../../v0/util/index | ||
|
||
steps: | ||
- name: validateInput | ||
template: | | ||
$.assert(Array.isArray(^) && ^.length > 0, "Invalid event array") | ||
|
||
- name: transform | ||
externalWorkflow: | ||
path: ./procWorkflow.yaml | ||
loopOverInput: true | ||
|
||
- name: successfulEvents | ||
template: | | ||
$.outputs.transform#idx.output.({ | ||
"batchedRequest": ., | ||
"batched": false, | ||
"destination": ^[idx].destination, | ||
"metadata": ^[idx].metadata[], | ||
"statusCode": 200 | ||
})[] | ||
- name: failedEvents | ||
template: | | ||
$.outputs.transform#idx.error.( | ||
$.handleRtTfSingleEventError(^[idx], .originalError ?? ., {}) | ||
)[] | ||
- name: finalPayload | ||
template: | | ||
[...$.outputs.successfulEvents, ...$.outputs.failedEvents] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are creating/updating the company here and adding the user will be done from server. So we need to update the error messge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed