1. Help Center
  2. Internal Knowledge

Use Certainly's Web SDK to switch between the Certainly and Zendesk Web Widgets (legacy)

Here, we'll cover how to ensure a smooth interaction between Certainly and Zendesk, leveraging a combination of Certainly's Conversational Web SDK and Zendesk's WebWidget Core API. This allows you to set up your Certainly chatbot as the first line of support and seamlessly hand over to your human agents on Zendesk for edge cases.

This is a legacy implementation. We recommend using a Certainly extension instead.

Unlike the Zendesk channel integration available in Bot Settings, this client-side integration does not require you to have a Zendesk Enterprise subscription.

Below, we'll address the following:

Requirements

First, you'll need to make sure you've met some basic requirements:

  1. You've created a chatbot on Certainly.
     
  2. In Bot Settings, you've enabled the ability to send Custom Variables with Bot Messages:
    ZDswitchsettings
     
  3. You have a Zendesk account with an active Zendesk Chat product.

  4. You've inserted the  wh_iconCertainly Get Conversation History Webhook in the Module preceding the specified handover Module.

Configuration

To set up the code for your use case, you'll have to configure the object widgetSwitchConfig:

Property Description
botId
(str)
Identifies the deployment ID of the chatbot to be launched. You can find the deployment ID of your bot in Bot Settings > Channels > Certainly Web Widget.
webchatKey
(str)
Unique Identifier for the webchat widget. You may have several widgets on your site and it's necessary to link this action to one of them.
handoverModuleId
(str)
ID of the Module that will trigger the handover from Certainly to Zendesk*
takeoverModuleId
(str)
ID of the Module from which the Certainly Widget will resume the conversation after the Zendesk chat has ended*
zendeskHumanDepartment
(str)
The department name under which your human agents operate on Zendesk. You can get the name from <yourSubdomain>.zendesk.com/chat/agent#departments

*The Module IDs need to match the handover (required) and takeover (optional) Modules created in your bot on the Certainly Platform:
switchmodules

Example code

Each of the following code blocks is required to make the solution work. The order illustrated below needs to be respected.

  1. Customize the Widget Switch settings:
      
    <script>
    // Here you can customize the switch between Certainly and Zendesk for your own use case
    widgetSwitchConfig = {
    botId: "d63450ae-9729-45c1-8277-5d7aea9a7492", // The deployment ID of the chatbot which you wish to enable on your site
    webchatKey: "Certainly", // A unique identified for the instance of the Certainly Widget
    handoverModuleId: "387991", // The module ID which will trigger the handover from Certainly to Zendesk
    takeoverModuleId: "387988", // The module from which the Certainly Widget will resume the conversation after the Zendesk chat has been ended
    zendeskHumanDepartment: "CS_Agent_Department" // The department under which your human agents operate on Zendesk
    }
    </script>

      

  2. Include your Zendesk Widget code. You can retrieve your code snippet directly from Zendesk at https://.zendesk.com/chat/agent#widget/getting_started

    <script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=27d6dc4b-1e71-4f61-ad5a-5e9567556631"></script>

      

  3. Copy and paste the following code to enable the Widget Switch functionalities code:

<script src="https://app.certainly.io/sdk/webchat.js"></script>

<script>
certainly.getCertainlyTransfer({
  actionName: widgetSwitchConfig.handoverModuleId,
  webchatKey: widgetSwitchConfig.webchatKey,
  callback: (data) => handoverToZendesk(data) // The data object contains information such as the latest visitor message and custom variables
});
</script>


<script>
function handoverToZendesk(data){	 
		certainly.widgetStatus(
				{
					action: "hide", // Required 
					webchatKey: widgetSwitchConfig.webchatKey, // Required if specified in initCertainlyWidget()
				}
			);
		console.log(data);		
		$zopim(function() {
			if (typeof data.cvars.userName === 'undefined' && typeof data.cvars.userEmail === 'undefined') {
				// The Certainly Widget has not collected the above cvars
				$zopim.livechat.setName('Anonymous visitor');
				$zopim.livechat.setEmail('visitor@email.com');
			}
			else {
				$zopim.livechat.setName(data.cvars.userName);
				$zopim.livechat.setEmail(data.cvars.userEmail);
			}
			$zopim.livechat.departments.setVisitorDepartment(widgetSwitchConfig.zendeskHumanDepartment);	
			$zopim.livechat.say(data.cvars.chatHistory);
		});
		activeWidget = "Zendesk";
		window.localStorage.setItem("activeWidget", activeWidget);
		zE(function() {
		// The Zendesk chat has started, but the Zendesk Widget is still hidden, so this displays it
			zE.activate();
		});
}
</script>

<script>
var departments;
var zendeskDepartmentStatus;
var CertainlyLoaded = false;
var activeWidget = window.localStorage.getItem("activeWidget");

document.addEventListener("DOMContentLoaded", function(event) {
	
	if (activeWidget != "Zendesk"){
		console.log("Launching Certainly Widget")
		
		zE(function() {
				$zopim(function() { // Retrieves the Zendesk departments statuses
					$zopim.livechat.setOnConnected(function() {
					  departments = $zopim.livechat.departments.getAllDepartments();
					  
						departments.forEach(function(department) {
							if(	department.name == widgetSwitchConfig.zendeskHumanDepartment){
								zendeskDepartmentStatus = department.status; //Saves the status of the Zendesk human department
							}
						});
						// Launch the Certainly Widget
						if (!CertainlyLoaded){
						initCertainlyWidget({
							id: widgetSwitchConfig.botId,
							webchatKey: widgetSwitchConfig.webchatKey,
							cvars: {
							  zendeskDepartmentStatus: zendeskDepartmentStatus //Passes the Zendesk human department status to the Certainly Widget, so it can be used by the bot
							}
						});
						CertainlyLoaded= true;
						}
					});
					zE.hide();
				});
			});
		}
		
		else {
			//Visitor had previously switched to Zendesk Widget	
			zE(function() {
				$zopim(function() {
					$zopim.livechat.setOnConnected(function() {
					  departments = $zopim.livechat.departments.getAllDepartments();
					  
						departments.forEach(function(department) {
							if(	department.name == "Chat"){
								zendeskDepartmentStatus = department.status;
							}
						});
				  });
				  zE.show();
				  zE.activate();
				});
			});
			
		}
	
	// Resume conversation on Certainly when the Zendesk chat is ended
	zE('webWidget:on', 'chat:end', function() {
		zE(function() {
			zE.hide();
		});
		
	    var certainlyWidget = document.getElementById("certainly-chat-"+widgetSwitchConfig.webchatKey);
		
	    if (certainlyWidget == null){ // If the Certainly Widget has not been launched before, this loads it
			console.log("Resuming Certainly Chat");
	        initCertainlyWidget({
						id: widgetSwitchConfig.botId,
						webchatKey: widgetSwitchConfig.webchatKey,
						ref: widgetSwitchConfig.takeoverModuleId,
						cvars: {
						  zendeskDepartmentStatus: zendeskDepartmentStatus
						}
					});
	    }
	    else {//Certainly Widget was already initialized, this will move the existing conversation to the takeover module
			certainly.goTo(
				{
					module: widgetSwitchConfig.takeoverModuleId, // Required
					webchatKey: widgetSwitchConfig.webchatKey, // Required if specified in initCertainlyWidget()
					cvars: {} // Pass custom variables to the bot (optional)
				},
				//As a callback, show the Certainly Widget
				certainly.widgetStatus(
					{
						action: "show", // Required 
						webchatKey: widgetSwitchConfig.webchatKey, // Required if specified in initCertainlyWidget()
					}
				)
			)
	    }
		window.localStorage.setItem("activeWidget", "Certainly");
	    activeWidget = window.localStorage.getItem("activeWidget");
		
  });
  
  zE('webWidget:on', 'close', function() {
	//Whenever the Zendesk widget is minimized, this displays the icon to maximize it agagain.
	//Otherwise, the visitor will have no Widget to interact with
	zE(function() {zE.show();});
  });
  
});
</script>