Out of the box syncing User mentions cannot be done because the user ID that the remote site has is not the same ID Salesforce uses.
To sync over User mentions you would need to map the ID from the remote side to their email address, so on Salesforce we can get the User ID with that email.
I have to examples for Jira cloud & Azure DevOps (they are quit similar so this should work on other connectors too).
First we will work on the outgoing script to transform the User ID to the linked email.
As you can see in the scripts above the only changes are the regex to find the userID and the getUser() function
// The nodeHelper has a function called getUser() // On jira the function expects a String, On ADO it expects a String and the project name // Usage Jira Cloud nodeHelper.getUser(String userID) // Usage Azure DevOps nodeHelper.getUser(String userID, String projectName)
Now we have the email addres in the comment instead of the ID we can implement the script to add the comment in Salesforce.
This is the full script you need in your Salesfroce incoming script.
Things you need:
import groovy.json.JsonOutput // function to get the right Segment def getMessageSegment(String type){ def mentionMatch = type =~ /\[~accountid:(.*?)]/ if(mentionMatch.find()){ // if no id was found add the email address as text not as mention. def userId = nodeHelper.getUserByEmail(mentionMatch.group(1))?.key if (!userId) return [type:"Text",text:mentionMatch.group(1)] return [type:"Mention",id:userId] } return [type:"Text",text:type] } // Function that created the Segment body (needed in the API POST) def createSegmentBody(String comment){ def regex = /\[~accountid:.*?]/ // Use findAll to capture all user mentions def matches = comment.findAll(regex) def splitString = comment.split(regex) // Merge the split strings and matches def splittedComment = [] for (int i = 0; i < splitString.size(); i++) { splittedComment << splitString[i] if (i < matches.size()) { splittedComment << matches[i] } } def segmentBody = [] // iterate over the list and add the segment body for (int i = 0; i < splittedComment.size(); i++){ if (splittedComment[i] == "") continue; segmentBody.add(getMessageSegment(splittedComment[i])) } // Return json object return JsonOutput.toJson([subjectId: entity.key, body: [ messageSegments: segmentBody]]) } // This will add the comments in your salesfroce case and will add it to the stack trace. def addComments(def comments){ def SFCommentId = "" // collect all comments and post the createSegmentBody... comments.collect{ c -> if (c.body){ def res = httpClient.post("/services/data/v54.0/chatter/feed-elements/",createSegmentBody(c.body),null, ["Content-Type":["application/json"]]){ req, res -> // When the rest api call is successfully fulfilled set the SFCommentId var. if (res.code == 201) { SFCommentId = res?.body?.id } else { debug.error("error while creating comment:" + res.code + " message:" + res.body) } } // Add trace if ( SFCommentId ) { def trace = new com.exalate.basic.domain.BasicNonPersistentTrace() .setType(com.exalate.api.domain.twintrace.TraceType.COMMENT) .setToSynchronize(true) .setLocalId(SFCommentId as String) .setRemoteId(c.remoteId as String) .setAction(com.exalate.api.domain.twintrace.TraceAction.NONE) traces.add(trace) } } } } // Now we need to call the addComments() function, we need to store the case in the first sync so we have the case ID to add the comments to. if(entity.entityType == "Case"){ if(firstSync){ // Add the required fields you need to create a case in the firstSync. // Store to create the Case ID so we can add the comment in the right case. store(entity) } // Add the fields you need below.. // Set comments with or without user mentions addComments(replica.addedComments) }
This is how to set usermentions in Salesforce.
You can find my source code in this GitHub Repo.