Proactive Chat - Intercepting Chat Events

RightNow Syndicated Proactive Chat is a RightNow feature that exposes proactive chat functionality to external websites such as your homepage, shopping cart, or any other page that can execute some JavaScript. Like Proactive Chat in Customer Portal, syndicated proactive chat prompts the user for a chat session when certain conditions are met (such as if the user has been on a single page for a configurable time interval). Due to the fragmented documentation around this product feature, most people don't know that you can customize the proactive chat experience beyond the basic settings available in the Syndicated Chat Wizard.

This tutorial will give a glimpse at the advanced customization possible.

Changing what "Yes" and "No" means

A common request I've received is to change the behavior of the "Yes" and "No" buttons in proactive chat. These buttons do not behave like you would expect. When a user clicks "Yes" or "No" they are not prompted for another chat interaction for the duration of their browser session (i.e., until they close their browser). I would expect that behavior if I checked the "Do not ask again" checkbox, not when I simply clicked "Yes" or "No". The default behavior for when you select "Do not ask again" is to NEVER offer a proactive chat to that user ever again... or until they clear their browser cookies.

Using the hidden Proactive Chat API, we can easily change this behavior.

I will be using a cloud based tool named JSFiddle to demonstrate the Proactive Chat API's abilities. JSFiddle is a great tool for this because it will allow you to run each step (and view the underlying code) without having to do any server set-up on your own environment. You don't even need a RightNow CX site! If you are unfamiliar with JSFiddle, take a minute to check it out.

Step 1: Configure Basic Proactive Chat

Demo Code

To enable Proactive Chat, you need to include the RightNow Syndication JavaScript library on each of your pages where Proactive Chat widget will be used. This path will be different for each site. For my example, I will use the version (Yes, RightNow uses their own product). In JSFiddle, this include is configured in the left sidebar under the External Resources navigation section.

A Proactive Chat widget is initialized by including a snippet of JavaScript on your page (below the include). Basic customization can be achieved by passing different configuration values to the widget initialization code. RightNow includes a Wizard in the Customer Portal Administration area that helps generate this initialization JavaScript. You can find this wizard at: (substitute yourdomain for your site's subdomain).

I've tweaked my initialization code in this tutorial so that a proactive chat session is always prompted, regardless of agent availability or queue wait time.

RightNow.Client.Controller.addComponent( { instance_id: "spac_X", modal: true, avatar_image: "", logo_image: "", label_dialog_header: "", label_title: "", label_question: "Hi Sexy!!! Looking for a good time?", div_id: "myDiv", chat_login_page: "/app/chat/chat_launch", module: "ProactiveChat", min_agents_avail: 0, wait_threshold:99999, seconds: 5, type: 2 }, "//" );

A word of warning!!! When a proactive chat session is initially offered a cookie named noChat is set in your browser. This cookie will prevent the Proactive Chat widget from prompting you with another proactive chat session for the rest of your browsing session. This is the default behavior (and quite annoying). I've included a "Clear noChat Cookie" button on the demo page to assist in clearing the cookie.

Open the JSFiddle Demo Page and hit "Run". You should see a Proactive Chat session prompted after 5 seconds.

Step 2: Create a Widget Loaded event callback

Demo Code

Now that the Proactive Chat widget is working in its basic form, lets start customizing the behavior. Custom behavior can be defined as soon as the Proactive Chat widget is loaded (it loads asynchronously), so we will need to wait until this load event occurs before we execute our custom code. We can do this by subscribing a callback function to an event named "evt_widgetLoaded".

//Widget loaded callback RightNow.Client.Event.evt_widgetLoaded.subscribe(function (event_name, data) { if (data[0].id == "spac_X") { //Initialization alert('Widget Initialized'); } });

My code subscribes a lambda function as the callback. When the event fires, my function checks to make sure that the callback was executed for the widget with id of "spac_X". It is good practice to do this check because multiple RightNow syndicated widgets can be loaded on a page, an they each will fire the "evt_widgetLoaded" event. Finally, I display an alert box to confirm that the event has fired.

Open the JSFiddle Demo Page and hit "Run". You should see a JavaScript alert box pop up with a message of "Widget Initialized" (Note: this may take a second or two due to the asynchronous loading of the proactive chat widget).

Step 3: Override the "No" Button

Demo Code

Once the callback is fired, the Proactive Chat instance is ready to use (and customize). This instance is available under a global variable named spac_X (Note: this object name represents the instance_id parameter I provided in my initialization code.

If you inspect the object, you'll see that it contains a bunch of methods. We can use these methods to drive behavior.

If you were to include the code spac_X.offerChat(); inside of your callback, a proactive chat session would be offered immediately to the user.

Besides executing methods, we can also override them. There are different methods for each of the User Interface actions available on the widget, including one for when the Chat is offered to the user. This method is called chatOffered.

This method contains important default behavior, so we don't want to simply replace it. Instead, we want to execute the default method then call our custom code. We can do this by using the prototype behavior of JavaScript. First I take the default chatOffered method and store it on the prototype object. Next I redefine the chatOffered method on the spac_X object. My new method simply calls the old method from the prototype chain, then removes the noChat cookie (which is set as soon as the Chat is offered).

//Widget loaded callback RightNow.Client.Event.evt_widgetLoaded.subscribe(function (event_name, data) { if (data[0].id == "spac_X") { //Initialization alert('Widget Initialized'); //Reset prototype spac_X.prototype = {}; //Handle Chat Offered spac_X.prototype.chatOffered = spac_X.chatOffered; spac_X.chatOffered = function () { //console.log("Chat Offered Handled");; RightNow.Client.Util.setCookie("noChat",'',-10,'/','',''); }; } });

As we know from earlier in the tutorial, the noChat cookie is what prevents a chat from being automatically offered to the user. By removing the cookie after the chat is offered, we can ensure that the user will continue to receive a chat prompt on subsequent page loads.

Open the JSFiddle Demo Page and hit "Run" (you may need to clear the noChat cookie one last time). After the "Widget Initialized" alert, you will be offered a Proactive Chat session. Hit Run again (but don't hit the clear cookie button). You will be prompted again for a chat session, even if you previously hit the "No" button.

Step 4: Redefine "Do not ask again"

Demo Code

Our Proactive Chat instance now works as expected. We have one last task of redefining the "Do not ask again" checkbox's behavior. I would like this checkbox to disable chat for a single browser session. By default, it disables Proactive Chat for 1 month if selected. We can do this using the same technique that we employed in Step 3. This time, I'm going to redefine the chatRefused method. This method is called whenever the "Yes", "No", or "Close" button is clicked AND the Do not ask again checkbox is selected. Add the following code to our callback.

//Handle Chat Refused //Called when "Yes", "No", or "Close" is clicked //if the 'Do not ask again' is selected spac_X.prototype.chatRefused = spac_X.chatRefused; spac_X.chatRefused = function () { alert("Do not ask again Selected");; //Reset the Cookie to be valid only for the session RightNow.Client.Util.setCookie("noChat",'RNTLIVE',0,'/',true,''); };

With this code in place, whenever the Do not ask again checkbox is selected, our method is called. All our method does is set the noChat cookie with an expiration of 0, affectively making the cookie valid for the browsing session.

Open the JSFiddle Demo Page and hit "Run". After the "Widget Initialized" alert, you will be offered a Proactive Chat session. Select the Do not ask again checkbox and hit either the "Yes", "No" or "Close" buttons. You will see an alert confirming that our chatRefused method was called. Hit "Run" again and observe that a chat session is no longer offered. Hit the Clear noChat Cookie button and hit "Run" again. You will once again be prompted with a chat session.


Using this same technique with other Proactive Chat widget object methods, you can customize your customer experience beyond what is available through the Wizard. There are other methods that are available that correspond to other button clicks, such as the "Yes" button or "No" button. The final JSFiddle Demo Code includes stubs for these methods. Play around. Fork my JSFiddle. Inspect the spac_X variable and see what else is available.


Have you ever tried triggering the syndicated Proactive Chat widget using Javascript API?
I started customizing it by the use of two javascript functions chatAvailability() and offerChat().And I marked the seconds attribute of the widget to zero,so as to expose the Javascript API Functions.

But I am not getting the chat offer.Am I missing something?


Yep. You can use either method manually and roll your own logic (once the widgetLoaded callback occurs).

Make sure that the noChat cookie is not set. It can cause problems.

I've also noticed an issue with "offerChat" where a vertical scroll needs to happen before the UI appears. Newer releases may have fixed this, but it was an issue at one point.

A note with chatAvailability() is that you need to pass two parameters, The first is a callback function and the second is a context.

Can you please illustrate how to pass callback function and context in the chatAvailability function.?

I build a quick demo with the following scenario:
The demo has a list of available items for sale. You can add items to your "shopping" cart. When your cart total is greater than $500, the chatAvailability() method is used to check for available agent sessions. If one is available, the proactive chat prompt is initiated.

The key lines of code are lines 90 to 103:
widget.chatAvailability(function(data) //Callback function passed to chatAvailability()
	if(data.availableAgentSessions > 0)
		//Show chat prompt
		//No agents are available
		alert('there are no agents available to chat');   
I pass a callback (as an anonymous function) as the first parameter. I can optionally pass a context as a second parameter, but have decided not to.

I can't exactly nail this down, but it seems as if there is a function in the RightNow JS that causes this to not fire in Firefox. Since the Firefox paradigm is to update, and update often - its hard to have any quality control over the app when something like this happens - but wondering if you have suggestion as to why it doesn't work properly. We have several instances working now ... so its a miff as to the JS error that forks it up. I originally thought it was CSS, because the rendering just doesn't happen ... *shaking head*

i used your code, works great, when i then try to use the same on conditional chat and use its events it doesnt fire
i can see the widget load, i get my alert to show my code has fired but the event for click never gets used

any ideas or examples ?

Hey. Sorry for the slow reply. We've been having some notification issues with our site and I didn't see this comment until just now.

Conditional Chat has different event names. Try this event instead: evt_conditionalChatLinkClicked

I used this code and it worked for me:
RightNow.Client.Event.evt_conditionalChatLinkClicked.subscribe(function(event_name, data)

Also, i just wrote another example of modding the syndicated widgets here:

This article specifically deals with syndicated chat

Is it possible to inject this using Engagement Engine rules?

Hi Ori!
Should be. I did a project that used engagement engine and the syndicated widgets and I believe I got it all working. Although truthfully it's been a while and things are starting to blend together. In the end it's all javascript so it's pretty easy to hack/modify.


Zircon - This is a contributing Drupal Theme
Design by WeebPal.