Replace the default Tawk.to widget bubble with your own custom button. Hide the native bubble and show your own UI instead.
<script setup lang="ts">
const {
isHidden,
unreadCount,
status,
showWidget,
hideWidget,
onLoad,
onUnreadCountChanged
} = useTawk()
const cleanupFns: Array<() => void> = []
onMounted(() => {
// Hide the native bubble once loaded
cleanupFns.push(
onLoad(() => hideWidget())
)
// Track unread count changes
cleanupFns.push(
onUnreadCountChanged((count) => {
console.log('Unread:', count)
})
)
})
onUnmounted(() => cleanupFns.forEach(fn => fn()))
</script>
<template>
<button
class="fixed bottom-6 right-6 w-14 h-14 rounded-full bg-green-500 text-white shadow-lg flex items-center justify-center"
@click="isHidden ? showWidget() : hideWidget()"
>
💬
<span
v-if="unreadCount > 0"
class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center"
>
{{ unreadCount }}
</span>
</button>
</template>
When a user logs into your app, forward their identity to Tawk.to so agents see who they're talking to.
<script setup lang="ts">
const { visitor, setAttributes } = useTawk()
const user = useUser() // your auth composable
watchEffect(() => {
if (user.value) {
// Set basic visitor info
visitor({
name: user.value.name,
email: user.value.email,
hash: user.value.tawkHash // HMAC-SHA256 from your backend
})
// Set extra attributes visible in the dashboard
setAttributes({
plan: user.value.plan,
accountId: user.value.id
})
}
})
</script>
hash field enables Tawk.to Secure Mode. Generate it server-side using HMAC-SHA256 on the visitor's email with your Tawk.to API key.Display real-time agent availability to let users know if live chat is available before they open the widget.
<script setup lang="ts">
const { status } = useTawk()
const statusLabel = computed(() => ({
online: 'We\'re online',
away: 'We\'re away',
offline: 'Leave a message'
}[status.value]))
const statusColor = computed(() => ({
online: 'text-green-500',
away: 'text-yellow-500',
offline: 'text-gray-400'
}[status.value]))
</script>
<template>
<div class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full" :class="statusColor" />
<span>{{ statusLabel }}</span>
</div>
</template>
Fire custom analytics events when visitors start or end chats.
export default defineNuxtPlugin(() => {
const { onChatStarted, onChatEnded, onOfflineSubmit } = useTawk()
onChatStarted(() => {
// Example: Google Analytics 4
gtag('event', 'chat_started')
})
onChatEnded(() => {
gtag('event', 'chat_ended')
})
onOfflineSubmit((data) => {
gtag('event', 'offline_form_submitted', { email: data.email })
})
})
Switch the Tawk.to widget at runtime based on the current route — useful for multi-brand or multi-tenant apps.
<script setup lang="ts">
const { switchWidget } = useTawk()
const route = useRoute()
const widgetMap: Record<string, { propertyId: string, widgetId: string }> = {
'/support': { propertyId: 'support-property-id', widgetId: 'support-widget' },
'/sales': { propertyId: 'sales-property-id', widgetId: 'sales-widget' }
}
watch(() => route.path, (path) => {
const widget = widgetMap[path]
if (widget) switchWidget(widget)
})
</script>
Use hideWidget / showWidget based on the current page, e.g. hide on checkout pages.
export default defineNuxtPlugin(() => {
const { hideWidget, showWidget, onLoad } = useTawk()
const route = useRoute()
const hiddenRoutes = ['/checkout', '/payment']
// Apply after widget loads
onLoad(() => {
if (hiddenRoutes.includes(route.path)) {
hideWidget()
}
})
// Re-evaluate on route change
watch(() => route.path, (path) => {
if (hiddenRoutes.includes(path)) {
hideWidget()
} else {
showWidget()
}
})
})