/**
* tawk.to ↔ Botpress webchat bridge
* ----------------------------------
* Include this script on every page that hosts your Botpress webchat.
*/
;(function () {
'use strict'
var TAWK_PROPERTY_ID = ''
var TAWK_WIDGET_ID = 'default'
var HIDE_TAWK_UNTIL_HANDOFF = true
var RETURN_TO_BOT_ON_CHAT_END = true
var TREAT_AWAY_AS_ONLINE = true
var tawkLoading = false
var pendingHandoff = null
function log() {
if (window.TAWK_BRIDGE_DEBUG) {
console.log.apply(console, ['[tawk-bridge]'].concat([].slice.call(arguments)))
}
}
function notifyBot(type, data) {
var payload = Object.assign({ type: type }, data || {})
try {
if (window.botpress && typeof window.botpress.sendEvent === 'function') {
window.botpress.sendEvent(payload)
return
}
} catch (err) {
log('sendEvent failed', err)
}
try {
if (window.botpressWebChat && typeof window.botpressWebChat.sendPayload === 'function') {
window.botpressWebChat.sendPayload({ type: 'trigger', payload: payload })
}
} catch (err) {
log('sendPayload failed', err)
}
}
function hideBotpressChat() {
try {
if (window.botpress && typeof window.botpress.close === 'function') {
window.botpress.close()
return
}
} catch (err) {}
try {
if (window.botpressWebChat && typeof window.botpressWebChat.sendEvent === 'function') {
window.botpressWebChat.sendEvent({ type: 'hide' })
}
} catch (err) {}
}
function showBotpressChat() {
try {
if (window.botpress && typeof window.botpress.open === 'function') {
window.botpress.open()
return
}
} catch (err) {}
try {
if (window.botpressWebChat && typeof window.botpressWebChat.sendEvent === 'function') {
window.botpressWebChat.sendEvent({ type: 'show' })
}
} catch (err) {}
}
function listenForHandoff() {
var handler = function (raw) {
var event = raw
if (typeof raw === 'string') {
try {
event = JSON.parse(raw)
} catch (err) {
return
}
}
if (event && event.type === 'TRIGGER' && event.value) {
event = typeof event.value === 'string' ? safeParse(event.value) : event.value
}
if (event && event.type === 'tawk:handoff') {
log('handoff event received', event)
startHandoff(event)
}
}
var tries = 0
var attach = setInterval(function () {
tries++
if (window.botpress && typeof window.botpress.on === 'function' && !window.__tawkBridgeAttachedV2) {
window.__tawkBridgeAttachedV2 = true
window.botpress.on('customEvent', handler)
log('listening on webchat v2/v3')
}
if (
window.botpressWebChat &&
typeof window.botpressWebChat.onEvent === 'function' &&
!window.__tawkBridgeAttachedV1
) {
window.__tawkBridgeAttachedV1 = true
window.botpressWebChat.onEvent(handler, ['TRIGGER'])
log('listening on webchat v1')
}
if ((window.__tawkBridgeAttachedV1 && window.__tawkBridgeAttachedV2) || tries > 100) {
clearInterval(attach)
}
}, 300)
}
function safeParse(value) {
try {
return JSON.parse(value)
} catch (err) {
return null
}
}
function ensureTawkLoaded(propertyId, widgetId, onReady) {
if (window.Tawk_API && window.Tawk_API.getStatus) {
onReady()
return
}
var pid = propertyId || TAWK_PROPERTY_ID
var wid = widgetId || TAWK_WIDGET_ID || 'default'
if (!pid) {
console.error('[tawk-bridge] tawk.to is not on this page and no TAWK_PROPERTY_ID is configured.')
notifyBot('tawk:handoff-failed', { status: 'not-configured' })
return
}
var existingOnLoad = window.Tawk_API && window.Tawk_API.onLoad
window.Tawk_API = window.Tawk_API || {}
window.Tawk_LoadStart = new Date()
window.Tawk_API.onLoad = function () {
if (typeof existingOnLoad === 'function') existingOnLoad()
if (HIDE_TAWK_UNTIL_HANDOFF && !pendingHandoff) window.Tawk_API.hideWidget()
wireTawkLifecycle()
onReady()
}
if (!tawkLoading) {
tawkLoading = true
var s1 = document.createElement('script')
s1.async = true
s1.src = 'https://embed.tawk.to/' + pid + '/' + wid
s1.charset = 'UTF-8'
s1.setAttribute('crossorigin', '*')
document.head.appendChild(s1)
log('injecting tawk.to embed', pid, wid)
}
}
function wireTawkLifecycle() {
var previous = window.Tawk_API.onChatEnded
window.Tawk_API.onChatEnded = function () {
if (typeof previous === 'function') previous()
log('tawk chat ended')
notifyBot('tawk:chat-ended', {})
if (RETURN_TO_BOT_ON_CHAT_END) {
if (HIDE_TAWK_UNTIL_HANDOFF) {
window.Tawk_API.minimize()
window.Tawk_API.hideWidget()
}
showBotpressChat()
}
}
}
function agentsAvailable() {
var status = window.Tawk_API.getStatus()
return status === 'online' || (TREAT_AWAY_AS_ONLINE && status === 'away')
}
function chunkText(text, size) {
var chunks = []
var remaining = String(text || '')
while (remaining.length > 0) {
chunks.push(remaining.slice(0, size))
remaining = remaining.slice(size)
}
return chunks
}
function pushSummaryToTawk(payload, done) {
var visitor = payload.visitor || {}
var attributes = {}
if (visitor.name) attributes.name = visitor.name
if (visitor.email) attributes.email = visitor.email
attributes['handoff-from'] = 'botpress'
attributes['handoff-time'] = payload.sentAt || new Date().toISOString()
window.Tawk_API.setAttributes(attributes, function (error) {
log('setAttributes result', error || 'success')
})
if (payload.tags && payload.tags.length) {
window.Tawk_API.addTags(payload.tags, function (error) {
log('addTags result', error || 'success')
})
}
var summary = payload.summary || {}
var sections = [
{ name: 'client-asked', text: summary.clientAsked },
{ name: 'bot-suggested', text: summary.botSuggested },
]
sections.forEach(function (section) {
if (!section.text) return
var chunks = chunkText(section.text, 240)
chunks.forEach(function (chunk, i) {
var eventName = chunks.length > 1 ? section.name + '-' + (i + 1) : section.name
window.Tawk_API.addEvent(eventName, { text: chunk }, function (error) {
log('addEvent result for ' + eventName, error || 'success')
})
})
})
done()
}
function startHandoff(payload) {
pendingHandoff = payload
var tawkIds = payload.tawk || {}
ensureTawkLoaded(tawkIds.propertyId, tawkIds.widgetId, function () {
if (!agentsAvailable()) {
log('handoff refused: tawk status is', window.Tawk_API.getStatus())
pendingHandoff = null
notifyBot('tawk:handoff-failed', { status: window.Tawk_API.getStatus() })
return
}
window.Tawk_API.showWidget()
hideBotpressChat()
window.Tawk_API.maximize()
pushSummaryToTawk(pendingHandoff, function () {
pendingHandoff = null
notifyBot('tawk:handoff-success', { status: window.Tawk_API.getStatus() })
log('handoff complete')
})
})
}
if (window.Tawk_API) {
var prevLoad = window.Tawk_API.onLoad
window.Tawk_API.onLoad = function () {
if (typeof prevLoad === 'function') prevLoad()
if (HIDE_TAWK_UNTIL_HANDOFF) window.Tawk_API.hideWidget()
wireTawkLifecycle()
}
}
listenForHandoff()
})()