In this blog, we’ll build a simple Integration Builder flow which monitors HubSpot CRM for new contacts. If a new contact is created in HubSpot, the flow will automatically create the same contact in Salesforce Sales Cloud. We’ll demonstrate the following key functions of the Integration Builder platform:
- Authentication with external services
- Data mapping
- Event triggers
Prerequisites
You’ll need the following for this tutorial:
- Axway AMPLIFY account – register for free at: https://platform.axway.com/
- HubSpot CRM account – sign up for a free account at: https://www.hubspot.com/
- Salesforce Sales Cloud account – Get a free developer account at: https://developer.salesforce.com/
Note: You will need to log into your Salesforce Developer account at least once before proceeding. The initial login triggers the creation of the sandbox environment which will be used in this example.
Overview of steps
- Create instances of HubSpot CRM and Salesforce Sales Cloud connectors
- Build a data mapping to create a normalized representation of a Customer
- Configure your connector instances to use the mapping
- Configure the HubSpot CRM connector instance to poll for updates
- Build a flow template using the connector instances and mapping
- Create a flow instance that triggers when the HubSpot CRM connector instance polls for an update
Create Connector Instances
- Log onto the AMPLIFY platform at https://platform.axway.com
- Click the Sandbox link on the Application Integration tile to enter the Integration Builder interface
- In the left-hand menu, select the Connectors tab
- Use the search bar to search for HubSpot CRM
- Hover over the HubSpot CRM connector tile and select Authenticate
- Name the connector HubSpot In
- Set Authentication Type to API Key
To obtain your API Key, log into the HubSpot console, navigate to Settings -> Integrations -> API Key. If you have no keys, then go ahead and create one. - Create a Connector Instance Tag named hubspot2salesforce and check the box labeled Create option: hubspot2salesforce
NOTE: Instance tags can be used to filter and search for objects in the UI. This becomes helpful when you have many objects and only want to view a subset. We’ll tag all of the objects in this demo with the same name so that we can view them as a group later. - Under Events Configuration, move the slider to Events Enabled. This will enable the polling we need to watch for updates.
- Under Configure Polling, deselect accounts and opportunities, since we are only interested in looking for new contacts.
- Set the Event poller refresh interval to 1 minute.
- Click the CREATE INSTANCE button. You’ll be redirected to the HubSpot authentication page
- Navigate to the Instances tab, and you should now have an Instance of the HubSpot CRM connector
- Return to the Connectors tab
- Search for Salesforce Sales Cloud
- Hover over the Salesforce Sales Cloud connector tile and select Authenticate
- Name the connector Salesforce Out
- Set Authentication Type to oauth2
- Use the hubspot2salesforce tag created earlier in the Connector Instance Tag field
- This connector instance will be invoked by a flow, so there is no need to configure polling
- Click the CREATE INSTANCE button, and you’ll be redirected to the Salesforce Cloud authentication page. Use your Salesforce Cloud credentials to authenticate the connector instance.
- Navigate to the Instances tab, and you should now have an Instance of the Salesforce connector
Create a mapping
Mappings can be used to create a normalized data model for use within Integration Builder. In this example, we’ll use a mapping on the inbound call to map the HubSpot-specific data model into a custom data model, mapping only the fields we need and giving them convenient names for internal reference. The map will also be used on the outbound call to Salesforce where it will map the internal data model to the appropriate fields in the Salesforce data model.
- Navigate to the Mappings tab and click the Build a new Mapping tile
- Click BUILD NEW RESOURCE
- Under Mappings Name and URL, enter myContacts
- Under Organizational Level Fields, click the + button (far right) 8 times to create 8 fields.
- Create the following fields:
Field Name Type Display Name email string Email firstName string First Name lastName string Last Name street string Street Address city string City state string State postalCode string Postal Code country string Country - Click Save next to the Mappings Name and URL field
Associate mapping with a Connector Instance
- Click Create New Transformation for “myContacts” under Mapped Transformations
- Under Connector Instances, click the the HubSpot In connector instance
- Under Connector Instance Resources, find and click on the contacts resource.
- Using the drop-down lists for each Field Name, select the HubSpot data model field to map to appropriate mapping field. You can start typing the name of the field to narrow the results to pick from.
Field Name HubSpot Field city properties.city country properties.country email properties.email firstName properties.firstname lastName properties.lastname postalCode properties.zip state properties.state street properties.address - Click the Transformation Settings button (gear icon)
- Enable Add to API Docs and Remove Unmapped Fields options
- Click Save
- Click the Save button next to the Transformation Settings icon
Test the mapping
- Click the Try it Out button (play icon in image above)
- Click the Send button
- A successful result will return the HubSpot demo data, showing only the fields in the map formatted per the defined JSON data model.
[ { "firstName": "Cool", "lastName": "Robot (Sample Contact)", "city": "Cambridge", "state": "MA", "email": "coolrobot@hubspot.com" }, { "firstName": "Brian", "lastName": "Halligan (Sample Contact)", "city": "Cambridge", "state": "MA", "email": "bh@hubspot.com" }, ...
Associate mapping with Salesforce Connector Instance
- Refresh the mappings view by clicking the Mappings button
- Click the Create New Transformation for “myContacts” button
- Under Connector Instances, select the Salesforce Out instance
- Under Connector Instance Resources, search for and select the Contact resource
- Map the following fields as done previously with the HubSpot connector
Field Name | Salesforce Field |
---|---|
city | MailingCity |
country | MailingCountry |
firstName | FirstName |
lastName | LastName |
postalCode | MailingPostalCode |
state | MailingState |
street | MailingStreet |
- Click the Transformation Settings (gear) icon
- Enable Add to API Docs and Remove Unmapped Fields options
- Click Save in the Transformation Settings window
- Click Save next the Mappings window
- Refresh the Mappings window again by clicking on the Mappings button as above
- Note that the HubSpot In and Salesforce Out Connector Instances are now associated with the myContacts mapping
Inspect API Docs
Understanding the changes made to the API Docs by the mapper will help to explain values used when building the flow in the next section.
- Navigate to the Instances tab in the Integration Builder UI
- Click the API DOCS button for the HubSpot In Connector instance
- Scroll down to the Contacts section and locate the /myContacts set of APIs. These are the APIs that were added by the mapper when the myContacts map was created.
Note the GET /myContacts and GET /myContacts/{id} APIs. These will get all contacts from HubSpot or contacts based on the result of a query string. Looking forward to the flow, the trigger event will contain the id of any newly created contact. The flow will then call the GET /myContacts/{id} and retrieve the fields defined in the mapping from the new contact entry.
Examine the API docs for the Salesforce Connector Instance. The flow will use the GET /myContacts/{id} to check if a contact already exists and then the POST /myContacts to create a new contact.
Create a flow
- Navigate to the Flows tab in the Integration Builder UI
- Click the Build New Flow Template tile
- Click the BUILD NEW FLOW option
- Name the flow HubspotToSalesforce
- Click CREATE
- Select Event as the trigger type by clicking the ADD EVENT button
- Under Connector Instance Variable, click the + button
- In the Select a flow Variable dialog, click the + button
- Click the Connector Instance icon
- Name the variable hubspot-origin
- Click Save
- Add a variable to associate with the Salesforce connector Instance by again clicking on the + button in the Select a flow variable dialog
- Select Connector Instance
- Name the variable salesforce-destination
- Click Save
- Select the hubspot-origin Flow Variable
- Click Save
- The Connector Instance Variable should now be populated with ${config.hubspot-origin}
- Click Save
Build the flow
- You should now be in the flow editor with the beginning of a flow on the pallet
- The first thing you need to do is determine what type of event the connector picked up
- Click the Add Step icon (blue plus)
- Select JS Filter (true/false) as the flow step type.
- Enter a name of isCreateContact
- In the body of the code editor, enter
let theEvent = trigger.event.eventType; let theObject = trigger.event.objectType; done((theEvent === 'CREATED') && (theObject === 'contact' || theObject === 'contacts'));
This code inspects values within the inbound trigger event and returns true or false based on values of the eventType and eventObject. This example will evaluate to True if the event type is CREATED and the object type is contact or contacts.
- The completed step should look like:
Note: The function begin and end are supplied for you. You just need to supply the logic. - Click Save
- Click on the isCreateContact step in the flow editor and select ADD ONSUCCESS
- Select Connector API Request as the step type
- Configure the step:
Name: getNewContact
Connector Instance Variable: ${config.hubspot-origin}
Method: GET
API: /myContacts/${trigger.event.objectId}
Here you are defining the connector instance variable that will be used in this step. When we later create a flow instance from the template, this variable will be associated with a specific connector instance. The API call will retrieve the fields defined in the myContacts mapping for the ID with a value retrieved from the contact create event. - Click Save
- Click on the getNewContact step in the flow editor and select ADD ONSUCCESS
- Select JS Script as the step type
- Configure the step:Name: buildEmailQueryParam
Code:var email = steps.getNewContact.response.body.email; console.log(email); var urlEncoded = encodeURIComponent("name=" + "'" + email + "'"); var encodedParam = "where=" + urlEncoded;console.log(encodedParam); done(encodedParam);
We’ll use the contact’s email address as a unique identifier. So, we need to build a URL-encoded string that will be used as a query parameter in the next step. The script will return the value of encodedParam that can then be referenced in subsequent steps.
- Click on the buildEmailQueryParam step in the flow editor and select ADD ONSUCCESS
- Select Connector API Request as the step type
- Configure the step:
Name: queryDestinationContact
Connector Instance Variable: ${config.salesforce-destination}
Method: GET
API: /myContacts?${steps.buildEmailQueryParam}
The API call uses the output of the buildEmailQueryParam step as a query parameter to the /myContacts API. - Click Save
- Click the queryDestinationContact step in the flow editor and select ADD ONSUCCESS
- Select JS Filter (true/false) as the step type
- Configure the filter:
Name: isNewContact
Code:var obj = steps.queryDestinationContact.response.body; if ((obj.length === 0) || obj[0] === null) { done(true); } else { done(false); }
This filter will return True if the query in the previous step returns a null or empty result. This indicates that no contact with the given email address exists in the Salesforce instance. If a contact with the given email address does exist, then the filter will return False.
- Click Save
- Click on the isNewContact step in the flow editor and select ADD ONSUCCESS
- Select Connector API Request as the step type
- Click the SHOW ADVANCED button
- Configure the step:
Name: createNewContact
Connector Instance Variable: ${config.salesforce-destination}
Method: POST
API: /myContacts
Body: ${steps.getNewContact.response.body}
This step will take the JSON object containing the contact fields defined in the myContacts mapping that was retrieved in the getNewContact step and pass it as input to the POST /myContacts API on the destination connector instance.
Complete the flow logic
This flow has two true/false filters where we have covered the True condition. We should add graceful exits to the False conditions and capture the output. I’m not sure if it’s necessary, but I have found it useful to understand why the filter evaluated to False when examining the flow instance execution trace.
- Click on the isCreateContact step in the flow editor and select ADD ONFAILURE
- Configure the step:
Name: notCreateEvent
Code:console.log("Not a CREATE event."); done(true);
- Click Save
- Click on the isNewContact step in the flow editor and select ADD ONFAILURE
- Configure the step:
Name: notNewContact
Code:console.log("Contact already exists."); done(true);
- Click Save
- The completed flow template should look like this:
Create a Flow Instance
Now that we have a complete flow template, it’s time to create an executable instance. This is where the Connector Instance Variables in the template will be associated with specific Connector Instances.
- Navigate to the Flows tab in the Integration Builder UI. This will return you to your list of Flow Templates
- Hover over the HubSpotToSalesforce Flow Template tile and select CREATE INSTANCE
- Name the instance Sync HubSpot Contact to Salesforce
- Under Variables click the + button on the salesforce-destination tile
- In the Connector Instance list, select Salesforce Out
- Click the + button on the hubspot-origin variable tile
- In the Connector Instance list, select HubSpot In
- Click CREATE INSTANCE
Test the flow
Now would be a good time to set the polling interval of the HubSpot, in the instance of the HubSpot CRM connector to a low value if you haven’t done so already.
- Navigate to the Instances tab in the Integration Builder UI
- Click on the Instance Options (gear icon) for the HubSpot In Connector Instance
- Select Edit
- Scroll down to the Event poller refresh interval and move the slider to 1 (min).
- Click UPDATE
- In a separate browser tab, navigate to HubSpot at https://apps.hubspot.com and log in
- Select Contacts from the HubSpot navigation menu
- Click Create contact
Email: bsmith@acmedemo.com
First name: Bob
Last name: Smith
Job tile: Superhero
City: Phoenix
Country: US
Street address: 6811 E Mayo Blvd
Sate/Region: AZ
Postal code: 85054 - Click Create Contact
- Return to the Integration Builder UI
- Navigate to the Flows tab
- Hover over the HubSpotToSalesforce tile and select EXECUTIONS
- You should see at least one execution of the flow listed under Flow Executions
- If you see more than one, click through the Flow Execution until you find one that shows a successful createNewContact step. You can click on each Step to view the associated input, output, headers, URI, etc. for that step. Available data depends on the type of step being viewed. This is very helpful for debugging and troubleshooting.
If you have a Flow Execution with a green createNewContact step, congratulations! Everything worked and you should have a new contact for Bob Smith in your Salesforce instance. If you get a red step, then it is time to do some troubleshooting. Click on the Steps to view their execution information and try to determine what went wrong.
- Log into your Salesforce instance at https://developer.salesforce.com/
- Navigate to the Contact view
- Observe the newly synchronized contact
In this blog, we demonstrated how to create Connector Instances and authenticate them against external services, define a custom Mapping to create normalized data model and build a flow to tie everything together. While this is a simple scenario, it provides an example that can be used in more complex situations.