Building an OmniChannel Experience: Context Aware Interactions using Salesforce Integration

September 26, 2025
Written by
Reviewed by

Introduction

In today's digital landscape, providing seamless customer experiences across multiple channels is crucial for business success. This article shows how to integrate and get customer context from Salesforce that creates a true omnichannel experience using Twilio's Studio, Serverless functions and Flex plugin architecture. In a business scenario, the agents will be using Salesforce as the primary tool and Flex embedded into the Salesforce interface using CTI connector.

Challenges

The out-of-the-box Flex integration with Salesforce provides a generic approach which will have capabilities—such as record pop-ups during interactions and automatic Task creation once a call or chat ends. While useful, these generic features often lead to additional manual work and restrict how effectively a business can streamline its processes. To unlock greater efficiency, the integration should go beyond the default OpenCTI adapter by enabling deeper data exchange and automation. Leveraging Salesforce REST APIs allows for a more robust and end-to-end integration, ensuring that business workflows are seamlessly executed with minimal manual intervention.

Key Technologies Used

  • Twilio Serverless: Cloud functions for backend processing and additional business logic

  • Twilio TaskRouter: Intelligent task distribution, routing and worker management 

  • Salesforce: CRM system for customer data management

  • JSForce: Node.js library for Salesforce API integration

  • Twilio Studio: Creating user journeys and integration to Salesforce

 

Problem Statement: Know your customer

In a contact centre environment, it is crucial to identify the customer as soon as their call or chat enters the Twilio environment. Early identification enables intelligent routing, offers relevant self-service options, and in many cases, resolves queries without the need for a human agent.

When interactions do reach an agent, having access to the customer’s profile, potential reason for contact, and additional contextual information empowers the agent to deliver a more personalized experience. This not only improves customer satisfaction but also helps reduce the average handling time of each interaction.

Solution

With the help of Twilio Studio and Twilio Functions, identifying the customer at the earliest stages is easy. 

 

High Level Architecture

 

 

Diagram showing a phone call workflow from user to Salesforce via Studio and Task Router.
Diagram showing a phone call workflow from user to Salesforce via Studio and Task Router.

This can be achieved by implementing the following steps:

Twilio Functions Salesforce REST API

This new twilio function will interact with the respective objects in Salesforce using the phone number of the called in person or any other data point which uniquely identifies the customer in CRM depending on the communication channel. The function makes use of Salesforce REST API and based on the business objectives, query the respective object to get the details back.

Capture Customer Identifier

  • The function receives an incoming request (call or chat) in the Twilio environment.

  • A customer identifier is extracted, such as the caller’s phone number, email address, or another unique data point depending on the communication channel.

Salesforce Query via REST API

  • The Twilio Function authenticates with Salesforce using OAuth 2.0.

  • It queries the relevant Salesforce object(s)—such as Contact, Account, or Case—based on the business requirements.

  • The query returns structured customer data, such as profile details, open cases, recent interactions, or account status.

Return and Use of Data

  • The retrieved data is returned to Twilio Flex (or other workflow components).

Information can be used for:

  • Intelligent Routing (e.g., Sales, Service, Warranty etc)

  • Self-Service Journeys (e.g., provide automated updates on order or case status)

  • Agent Context (e.g., pre-populating screen pops with customer info, recent history, and probable reason for contact)

File: index.js

exports.handler = async function (context, event, callback) {

   const functions = Runtime.getFunctions();
   const sfdcHelperPath = functions['helpers/fdc/index'].path;
   const sfdcHelper = require(sfdcHelperPath);
   const field = event.field?event.field:'phone';
   const value = event.value?event.value: '';

   try {
	if (value) {
       let data = await sfdcHelper.getSFReferenceData(context, field, value); 
       callback(null, data);
} else {
	callback(null);
   } catch(e) {
       console.log(e);
       callback(e);
   }
  }

File: helpers/sfdc/index.js

var jsforce = require('jsforce'); // Salesforce integration library
const getConnection =  async (context) => {

   // Create a jsforce connection
   // Salesforce login URL (default is production, use test.salesforce.com for sandbox)
   const loginUrl = context.LOGIN_URL;
   // Replace with your Salesforce username, password, and security token (if needed)
   const username = context.SALESFORCE_USERNAME;
   const password = context.SALESFORCE_PASSWORD + context.SALESFORCE_TOKEN;
   // Login to Salesforce
   console.log("Connecting..");
   try {
       const connection = new jsforce.Connection({ loginUrl, version: '63.0' });
       await connection.login(username, password);
       console.log("Connected");
       return connection;
   } catch (e) {
       console.log(e.message);
       return null;
   }
}
const searchCases = async (conn, field, value) => {
   try {
       let query = `SELECT Id,
                           (
                               SELECT Id, Status, IsClosed
                               FROM Cases WHERE IsClosed=false
                           ),
                            Phone
                       FROM Contact
                       WHERE `;
       if (field == "phone") {
           query = query + `Phone LIKE '${value}' OR MobilePhone LIKE '${value}' OR OtherPhone LIKE '${value}' OR HomePhone LIKE '${value}' OR AssistantPhone LIKE '${value}'`;
       } else if(field == "email") {
           query = query + `EmailAddress LIKE '${value}'`
       }

       const data = await conn.query(query);
       return data;
   } catch (e) {
       console.log(e.message);
       return null;
   }
}
// get the object details based on the logic defined
const getSFReferenceData = async (context, field, value) => {
   const conn =  await getConnection(context);
   if (!conn) {
       console.error("Unable to authenticate with Salesfoce");
       return null;
   }
   const caseData = await searchCases(conn, field, value);
   const contactId = caseData?.records[0]?.Id;
   if (caseData?.records[0]?.Cases?.totalSize) {
       const cases = caseData.records[0].Cases;
       console.log("Cases found:", cases.totalSize);
       if (cases.totalSize > 1) {
           // more open cases
           return {"object": "Contact", "sfdcObjectId": caseData.records[0].Id, "intent": "Sales", "contactId": contactId}
       } else {
           // one open case
           return {"object": "Case", "sfdcObjectId": cases.records[0].Id, "intent": "Warranty",  "contactId": contactId}
       }
   } else {
       if (contactId) {
           return {"object": "Contact", "sfdcObjectId": contactId, "intent": "Sales", "contactId": contactId}
       }
       return null;
   }
}
module.exports = {getSFReferenceData};

The above function will query the Contact and Case object inside Salesforce using the caller phone number and return an exact Case ObjectId if there is one open case available, or return Contact Object Id, if there are multiple cases or no cases available.

Conclusion

This Twilio-Salesforce integration demonstrates how modern cloud technologies can create a truly omnichannel customer experience. By combining Twilio's communication platform with Salesforce's CRM capabilities through serverless functions and intelligent routing, organizations can:

  • Provide seamless customer experiences across all channels

  • Enable agents with real-time customer context

The modular design allows for easy customization and extension, making it suitable for organizations of all sizes looking to modernize their customer service operations.

Next Steps

This architecture provides a solid foundation for building sophisticated customer service solutions that can adapt to changing business needs and customer expectations. This can be extended to a way to present the data fetched from the Salesforce to the customer using a custom Twilio Flex plugin, and update the activity log in Salesforce based on various actions, channels in Twilio.