Integrating Dux-Soup with Zoho CRM
With LinkedIn members now surpassing 750 million (756 million to be precise, according to LinkedIn) it’s clear that the platform remains the #1 B2B social selling network.
As more and more people use LinkedIn automation as an integrated and vital part of their overall lead generation process - we’re delighted to bring you a practical CRM integration blueprint designed by Martin Blonk, an automation process consultant who specialises in the Zoho CRM platform.
Zoho CRM was recently cited in a 2021 Gartner Magic Quadrant as a visionary in CRM Lead Management - due to the robust solution, exceptional customer experience, and increased market presence.
And, with more and more Dux-Soup users utilizing the Zoho CRM platform, it feels timely to bring you this step by step guide that Dux-Soup Turbo users can follow today.
The manual shows how you can integrate Dux-Soup with Zoho CRM to automatically create and update contact records in Zoho CRM with your LinkedIn activity - including messages sent and received
This enriches your Zoho CRM data - creating new contacts and enhancing your prospects CRM profile so you can better assess who is qualified and ready to buy.
Enjoy!
Introduction by Martin Blonk
In this manual I run through the steps needed to integrate Dux-Soup Turbo with Zoho CRM. The Zoho CRM integration that I built consists of three functions:
● Creating / Updating CRM Contact records from Visits or Connection requests via the Dux-Soup Webhook function.
● Sending LinkedIn messages (sent and received) from Dux-Soup to Zoho CRM and relating them to the Contacts.
● Sending messages from CRM to Dux-Soup via Remote Control (not in this manual yet)
Content
Zoho products used
Preparing Zoho CRM
Relating the Dux-Soup user id to the CRM User ID
Adding custom field(s) to the Contact record in Zoho CRM
Filling the Dux-Soup fields in the user record
Setting up Zoho Flow
Dux-Soup visits to CRM
Dux-Soup (LinkedIn) Messages to CRM
Testing
Appendix
Zoho products used
In order to make this integration work you need Zoho Flow and Zoho CRM. I used the Zoho One versions of these products, which means that Zoho CRM is the Enterprise edition and Zoho Flow the professional edition.
If you generate a lot of traffic via the integration you may need to purchase extra task credits for Zoho Flow and extra API credits for Zoho CRM.
Preparing Zoho CRM
Relating the Dux-Soup user id to the CRM User ID
In order to be able to relate the LinkedIn leads that come in from Dux-Soup to the right CRM user (as owner of the lead) you need to enter some Dux-Soup information in the CRM User record, and so you need to create custom fields. You need to have Administrator access to the CRM in order to configure this:
● In Zoho CRM go to Setting and click Users

● In the User section, edit a User Record and click "Manage Fields":

● Add 3 fields to the user record template
○ Duxsoup user ID
○ Duxsoup Remote Control URL
○ Duxsoup personal Key
For the field types see the picture below. NOTE: use the field names exactly as typed above (including exactly the upper- en lowercase characters. If you change this you will need to do a lot of troubleshooting before the integration will function properly.

● After adding the fields click the "Save and Close" button to store the new fields

Adding custom field(s) to the Contact record in Zoho CRM
● Go to Settings and click Modules and Fields

● In Modules and Fields click Contacts

● In Contacts click the layout to which you want to add the fields (if you have more than one layout defined):

● In the layout make sure you create the field:
● LinkedIn (again with the same upper- and lowercase characters)
The field has to be of type url and it has to be set to unique:

● In this field the LinkedIn profile url of the contact will be stored. You might already have a field for storing the LinkedIn profile url of a contact. In this case make sure that it is of the right type (url) and is unique and the API name of the field is "LinkedIn".
● You could create more fields e.g. for storing the connection status but that is not part of this manual.
Filling the Dux-Soup fields in the user record
In order to relate the Zoho CRM user account to the Dux-Soup user account we need to fill the fields that we created earlier in the Zoho CRM record with the values from Dux-Soup:

In the Duxsoup user ID, enter the Dux-Soup user ID that you find in the Dux Dash:

In the field Duxsoup Remote Control URL, enter the "Personal remote control url" that you can find in the Options / Connect screen and in the Duxsoup Personal Key, enter the "Personal remote control authentication key"
Setting up Zoho Flow
In Zoho Flow you will need to create a Connection to Zoho CRM. Use an account with at least the "Standard" (preferably Administrator) profile in CRM to create the connection.
Dux-Soup visits to CRM
Here you set up the sync of visits you make to Zoho CRM. NOTE: Disable the Webhook in Dux-Soup when you are browsing. Only switch it on when you use the Robot to visit (& connect) LinkedIn profiles.
Start with creating a Flow in Zoho Flow of the type "Webhook":

Choose payload format JSON and you may copy the Webhook url now (or later).

This webhook url goes to the Options/ Connect screen in Dux-Soup (check the "Visit" checkmark); leave the Webhook switch off for now:

In Zoho Flow, click Next and skip the test step (just click Done):


Now you may create the following flow; this may look complicated but most steps are necessary.

The syntax custom functions used in this flow are listed in the Appendix.
Below the description and config of each numbered item; NOTE: the "_<number" in variables may differ when you create a flow, e.g: the fetchUserByDuxsoupID_7 from step 2 could in your case be fetchUserByDuxsoupID_5 (this goes for all variable/output names).
1: Custom function to fetch the CRM User account based on the Dux-Soup user ID

2: If the CRM user account is not found, send an email to the admin (error)

3: Email with error message

4: This variable holds the value of the event from Dux-Soup; this can be "create" or "update". We need this later in order to avoid creation of duplicate records in CRM.

5: Fetch the CRM user based on the output of 1

6: Optional: get the City from the LinkedIn location

7: Fetch the Account based on the LinkedIn Company

8: Decision - type of event is "create" or "update"; if "update" delay of 2 minutes in order to avoid duplicate records

9: Delay of 2 minutes

10: Decision - if Account does not exist - create new Account

11: Create new account; this is a long form and I only show the filled in variables



(lead source)



12: Custom function to search contact in CRM based on LinkedIn profile

13: Decision - if contact exists; update contact, or else create a new contact

14: Create contact (contact does not exist in CRM); this again is a long form and only the filled in values are shown:









15: Update contact (contact exists in Zoho CRM); this again is a long form and only the filled in values are shown

Last name, Owner, First Name, Email, Account Name : see 14
Lead source is not filled in (because the contact already existed)
Dux-Soup (LinkedIn) Messages to CRM
The following flow logs the sent and received LinkedIn message to the CRM contacts. This flow adds a LinkedIn message as a Note to a contact. It is also possible to make a custom related module "LinkedIn messages" in the CRM and store the messages in that module. This will not be covered in this manual.
In Zoho Flow create a new flow of type "Webhook" again and copy the Webhook url in a second link in Dux-Soup:

Only the "Message" checkbox should be checked and the Message Bridge should be switched on.
The flow looks like this:

Explanation of the flow steps:
1: Stores message type

2: Stores "sent" or "received"

3: Custom function (same as used in the Visits flow) to find contact in CRM

Note that in this flow two payload variables are concatenated; this is because in all cases only one of these two variables has a value.
4: Decision: only proceed when contact is found in CRM

Note: one could extend the flow by creating a new contact when a contact is not found. In this example I have chosen to only add messages to existing contacts.
5: Determine message type (accept of message) (custom function in Appendix)

6: Fetch contact in CRM

7: Fetch user in CRM (for owner of the Note in CRM).

8: Convert time (different format in Dux-Soup and CRM); custom function

9: Add message to Contact in the form of a Note; custom function.

Testing
After you have setup the flows, you can test them from the Dux-Soup options panel (with the "Send Sample" buttons:

Success!
Please do reach out to me if you have questions about this integration or any aspect of Zoho CRM.
About the Author

Martin Blonk, ICT & Business Process Automation
I love to help people implement back office functions like Zoho CRM, Zoho Social and other appropriate software applications.
I speak the language of the entrepreneur and pay close attention to formulating the real question/need; as a result, I propose solutions that directly benefit you.
With more than 30 years of experience in ICT and more than 20 years of experience in automating business processes – feel free to reach out to me today to talk about how I can help your business.
Book some time to chat: https://www.martinblonk.com/contact
Email:martin@martinblonk.com
Web: www.martinblonk.com
Appendix
Custom functions in Zoho Flow
fetchUserByDuxsoupID
string fetchUserByDuxsoupID(string duxsoupID)
{
if(!(duxsoupID == null || duxsoupID == ""))
{
mp = Map();
users = zoho.crm.invokeConnector("crm.getusers",mp);
response = users.get("response").get("users");
for each user in response
{
p_duxsoupID = ifNull(user.getJSON("Duxsoup_user_ID"),"");
if(!p_duxsoupID == null)
{
p_Email = ifNull(user.getJSON("email"),"");
if(p_duxsoupID == duxsoupID)
{
return p_Email;
}
}
}
}
return "";
}
getCityFromLocation
string getCityFromLocation(string LILocation)
{
//Function to get the city from the LinkedIn location
hasComma = LILocation.find(",");
if(hasComma <= 0)
{
return LILocation;
}
else
{
return LILocation.left(hasComma);
}
}
searchContactByLinkedIN
string searchContactByLinkedIN(string LIProfile)
{
LIProfile = trim(LIProfile);
if(LIProfile.subString(LIProfile.length() - 1) == "/")
{
LIProfile = left(LIProfile,LIProfile.length() - 1);
}
//info LIProfile;
searchVar = "(LinkedIn:starts_with:" + trim(LIProfile) + ")";
resp = zoho.crm.searchRecords("Contacts",searchVar);
if(resp.isEmpty())
{
return "";
}
else
{
return resp.getJSON("id");
}
}
determineAcceptOrMessage
string determineAcceptOrMessage(string messageType, string messageText)
{
messageText = trim(messageText);
if(messageType.toUpperCase() == "INVITATION_ACCEPT")
{
result = "Invitation Accepted";
}
else
{
result = messageText;
}
return result;
}
convertTime
string convertTime(string timestamp)
{
//info timestamp;
myDate = timestamp.toTime("yyyy-MM-d'T'HH:mm:ss.SSS'Z'");
//info myDate;
dateTime = myDate.toString("yyyy-MM-dd'T'HH:mm:ss'Z'");
return dateTime;
}
addMessageToContactNote
void addMessageToContactNote(string messageText, string messageUrl, string messageType, string receivedOrSent, string timestamp, string contID, string noteOwner)
{
if(receivedOrSent == "received")
{
noteText = "Received message\n\n";
}
else if(receivedOrSent == "sent")
{
noteText = "Sent message\n\n";
}
noteText = noteText + "Message - type: " + messageType + "\n\n";
noteText = noteText + "Message-text: " + messageText + "\n" + "\n" + "Link to message: " + messageUrl + "\n";
myDate = timestamp.toTime("yyyy-MM-d'T'HH:mm:ss'Z'","Etc/UTC");
dateTime = myDate.toString("dd-MM-yyyy HH:mm:ss","Europe/Amsterdam");
newNote = Map();
newNote.put("Owner",noteOwner);
newNote.put("se_module","Contacts");
newNote.put("Parent_Id",contID);
newNote.put("Note_Title","LinkedIn message dd.: " + dateTime);
newNote.put("Note_Content",noteText);
resp = zoho.crm.createRecord("Notes",newNote);
info resp;
}
© Martin Blonk | martin@martinblonk.com, | www.martinblonk.com