Integrating Websockets With PusherJS In Salesforce For Real-Time Messaging

The Scenario

Organizations are striving to engage with clients through modern communication channels such as social media, text messaging, and mobile calling. To deliver a real-time chat/texting experience, the application must establish instant communication between the client (browser) and server. Initially, the application used a polling mechanism, which significantly increased server loads to retrieve real-time chat data for advisors. This polling mechanism posed several challenges:

  • Advisors had to wait 5 seconds to send/receive data.
  • Browser/server polling led to a higher number of API calls.
  • It lacked scalability as the number of advisor users grew on the platform.
  • It did not offer a real-time chat/texting experience.

While fostering adoption and robust client engagement is crucial, the polling mechanism failed to ensure real-time synchronization of text message activities in Salesforce.

To deliver a real-time chat experience, a scalable, seamless, and low-latency service is necessary. This is where Pusher came into the picture.

By migrating to a WebSocket-based solution, the server load decreased significantly, alleviating the strain on their servers.

Introduction to Pusher

Pusher provides real time infrastructure as a service for communicating with application servers and clients. Clients can be web browsers or mobile devices. Since pusher is a hosted service, it is massively scalable, secure and quick. They use WebSockets to publish and receive information to/from application servers and clients.

WebSockets have represented a long awaited evolution in client/server web technology. They allow a long-held single TCP socket connection to be established between the client and server, enabling bi-directional, full duplex messages to be instantly distributed with little overhead, resulting in a highly efficient, very low latency connection.

Pusher has 2 products which should be used based on the use case. 

Channels logo

Pusher Channels provides real time communication between servers, apps and devices. Channels is used for real time charts, realtime user lists, realtime maps, multiplayer gaming, and many other kinds of UI updates.

Beams logo

Pusher Beams is an API for mobile app developers to add Push Notifications sending capability to their apps.

Pusher Channels Service

In the Salesforce application scenario, we utilized Pusher Channels to offer real-time communication capabilities to Salesforce advisors and agents. This functionality employs a Publish/Subscribe mechanism using WebSockets. Channels enables sending and receiving messages to and from a server, delivering event-driven responses without the need for continuous polling. This approach results in a highly efficient data transfer model. Currently, there are four types of channels available:

  • Public channels: These can be subscribed to by anyone who knows their name.
  • Private channels: These channels should have a private- prefix. They introduce a mechanism that allows your server to control access to the data being broadcasted.
  • Private encrypted channels: These channels should have a private-encrypted- prefix. They enhance the authorization mechanism of private channels by adding encryption to the data payloads, ensuring that even Pusher cannot access it without authorization.
  • Presence channels: These channels should have a presence- prefix and are an extension of private channels. They enable you to ‘register’ user information upon subscription and inform other channel members about who is currently online.

Integration of Pusher with Salesforce

To achieve real-time chat functionality within Salesforce, we implemented Pusher’s Private Channels with an authorization mechanism from an external platform’s application server.

Requirements for Private Channels Integration

Before integrating Private Channels, there are several prerequisites to address:

  • The Advisor/Agent in Salesforce must log into the external application using the OAuth flow. The user authentication token should then be stored in a protected custom setting.
  • Download the latest version of the Pusher JavaScript file from the provided link and upload it to Static Resource in Salesforce.
  • Note that Pusher JS does not encounter issues with the Locker service, but it is currently incompatible with Salesforce Lightning Web Security (LWS). In Salesforce Summer ’23, LWS applies to Aura components as well.
  • Verify the compatibility of the Pusher JS library with LWS in the LWS Console. If there are no issues, proceed with developing your components directly in Lightning Web Components (LWC).
  • If there are compatibility issues between LWS and the latest Pusher JS version, consider the following options:
    • Navigate to Setup → Session Settings and uncheck the “Use Lightning Web Security” checkbox.
    • It’s important to note that disabling LWS in Salesforce setup is not recommended as a general practice.

We anticipate that Pusher JS will eventually provide support for LWS. However, if we prefer not to disable LWS, the alternative option is to integrate Pusher JS within a Visualforce Page. Below are the instructions for embedding Pusher JS inside a Visualforce Page and interfacing with Parent Lightning Web Components or Aura Components.

Integration with Pusher

For the Pusher Salesforce integration use case, the texting widgets utilizing PusherJS were constructed using custom Aura, Visualforce, and LWC components. These components can be seamlessly added to Salesforce homepages and record pages to enhance customer engagement insights. Here are some high-level use cases that offer a scalable and high-performing real-time chat/texting experience:

  1. Notification utility bar component: This component notifies agents about multiple client interactions.
  2. Home page component: Displays a list of all conversations for the agent.
  3. Record page component: Displays the chat/texting widget with complete conversation history.

Due to PusherJS restrictions with Lightning Web Security, the recommended approach below utilizes Visualforce for integration. If LWS supports Pusher JS in the future, we can directly integrate it with Lightning Web Components.

Here’s the suggested approach:

  1. Develop a Visualforce wrapper to embed the Pusher JS script and bind it to a private channel. Sample code is provided below.
  2. Utilize Javascript remoting to make apex controller calls for retrieving the Pusher Key and authentication token. If the application is a managed package, the Pusher Key can be stored in protected custom settings as part of an admin setting.
  3. The auth_token should be initially retrieved as part of the application server API authentication. Public channels do not require any authentication.

Note: To experiment with Public Channels, set up your account in Pusher and obtain your free API keys. Every published event in Pusher has an “event name”; the event you publish will have the event name “my-event.”

[Sample Visualforce code for embedding Pusher JS script and binding to a private channel]

<apex:page >
    <apex:includeScript value="{!$Resource.PusherJS}" />
    <script>
        // Initialize Pusher with your Pusher Key and authentication token
        var pusher = new Pusher('YOUR_PUSHER_KEY', {
            auth: {
                headers: {
                    'Authorization': 'Bearer {!$RemoteAction.ControllerName.getAuthToken()}'
                }
            }
        });

        // Subscribe to the private channel
        var channel = pusher.subscribe('private-channel');
        
        // Bind to events on the channel
        channel.bind('my-event', function(data) {
            // Handle incoming data from Pusher
            console.log(data);
        });
    </script>
</apex:page>

In this code snippet, replace 'YOUR_PUSHER_KEY' with your actual Pusher Key, and ensure that ControllerName.getAuthToken() retrieves the authentication token from the server using Javascript remoting