How can I combine Web Widget (Classic) API workflows?

Question

I want to modify the native behavior of the Web Widget (Classic) with JavaScript APIs. I read the Help Center and I found many different implementations. How can I combine these Web Widget (Classic) API workflows?

Answer

Disclaimer: This article is provided for instructional purposes only. Zendesk does not support or guarantee the code. Post any issues you have in the comments section or try a search for a solution online.

Apply your widget settings at the right moment. Some workflows must run after a department update, and others must run when the widget first connects or reconnects. This matters because the widget can load before a chat session exists, and a visitor can reconnect after a session timeout or page refresh. If your code runs only once on page load, the active chat session might miss some settings, or the widget might lose them after a reconnect.

This example shows how to set the CRM department. In this example, "CRM" is the name of a Chat department that you configure in the Chat widget settings (for example, a department used by a sales or account team). Replace "CRM" with the exact name of the department in your account.

<script id="ze-snippet"
src="https://static.zdassets.com/ekr/snippet.js?key=ACCOUNT_KEY">


// first hide the widget on page load
zE('webWidget', 'hide');

// whenever an unread message appears unhide and open the widget
zE('webWidget:on', 'chat:unreadMessages', function(number) {
zE('webWidget', 'show');
zE('webWidget', 'open');
});

// this callback runs whenever chat first connects (or reconnects)
zE('webWidget:on', 'chat:connected', function() {

// put any code you only want run once here

});

// this callback runs whenever a department status changes
zE('webWidget:on', 'chat:departmentStatus', function(dept) {

// only set the widget online for chat if this department was online
if (dept.name === 'CRM' && dept.status === 'online') {

// apply the chat widget settings
zE('webWidget', 'updateSettings', {
webWidget: {
chat: {
departments: {
enabled: [''],
select: 'CRM'
},
suppress: false
}
}
});
} else if (dept.name === 'CRM' && dept.status !== 'online') {

// or suppress chat (optional: apply contact form settings here)
zE('webWidget', 'updateSettings', {
webWidget: {
chat: {
suppress: true
}
}
});
}
});


Here are two points about the script. You can omit the initial hide and the subsequent show on an unread message without changing the rest of the script. Because those calls run as soon as the widget loads, the script places them at the top. They are optional.

Some custom workflows place an updateSettings API block in a chat:connected callback, but you can also put it in a chat:departmentStatus callback. The widget applies it when it first connects or after a reconnect due to a session timeout. As a rule, tie your workflow to the event when the setting must take effect:

Use chat:connected for logic that should run once per chat session, such as initial configuration that should not repeat after every department status refresh.

Use chat:departmentStatus for logic that must stay in sync with department availability or routing changes, because it can fire when department status changes and when the widget initializes.

For more information on different Web Widget (Classic) API workflows, see:

Can I configure the Web Widget (Classic) to present Chat on my webpage only when a specific department is online?

Can I reapply the department after a timed-out chat visitor reconnects?

How can I make sure the pre-chat form is presented to the visitor if they time out but reconnect?