Skip to main content
Scripts

Tawk.to is a free live chat widget.

useScriptTawkTo() loads the widget, types the window.Tawk_API command surface, and bridges the window events the embed script dispatches into reactive state and typed listeners.

Tawk.to

View source

Nuxt Config Setup

Add this to your nuxt.config.ts to load Tawk.to globally. Alternatively you can use the useScriptTawkTo composable for more control.

export default defineNuxtConfig({
  scripts: {
    registry: {
      tawkTo: {
        trigger: 'onNuxtReady',
      }
    }
  }
})

useScriptTawkTo()

The useScriptTawkTo composable lets you have fine-grain control over when and how Tawk.to is loaded on your site.

const { proxy } = useScriptTawkTo()

Please follow the Registry Scripts guide to learn more about advanced usage.

Example

Using Tawk.to in a component.

ConversionButton.vue
<script setup lang="ts">
const { proxy } = useScriptTawkTo()

// noop in development, ssr
// just works in production, client
function handleAction() {
  // use proxy methods here
}
</script>

<template>
  <div>
    <button @click="handleAction">
      Send Event
    </button>
  </div>
</template>

Bundling and proxying are both off. Nobody has verified how the embed script resolves its own API origin, or what live-chat polling connections a proxy would end up in front of, so neither capability is declared rather than guessed at.

Find propertyId and widgetId under Administration Settings → Channels → Chat Widget in your Tawk.to dashboard.

const { proxy } = useScriptTawkTo({
  propertyId: 'YOUR_PROPERTY_ID',
  widgetId: 'YOUR_WIDGET_ID',
})

function openChat() {
  proxy.maximize()
}

Reactive state and events

Tawk's embed script dispatches window CustomEvents (tawkLoad, tawkStatusChange, tawkChatMaximized, …) alongside its documented Tawk_API.onXxx = fn callback-property API. useScriptTawkTo() bridges those events into five readonly refs and twenty typed listeners, so you don't have to wire window.addEventListener yourself:

<script setup lang="ts">
const { isHidden, isMinimized, isMaximized, chatStatus, unreadCount, onChatStarted, onChatEnded } = useScriptTawkTo({
  propertyId: 'YOUR_PROPERTY_ID',
  widgetId: 'YOUR_WIDGET_ID',
})

onChatStarted(() => {
  console.log('visitor started a chat')
})
onChatEnded(() => {
  console.log('chat ended')
})
</script>

<template>
  <div v-if="!isHidden">
    {{ chatStatus }} · {{ unreadCount }} unread · {{ isMinimized ? 'minimized' : isMaximized ? 'maximized' : 'default' }}
  </div>
</template>

chatStatus is Tawk's own online/away/offline operator status (getStatus()). It's distinct from status, the generic script-load state every registry entry exposes.

Every onXxx listener returns a teardown function for use with onScopeDispose, mirroring the rest of the registry's event-listener helpers.

The state refs are a single instance shared by every useScriptTawkTo() call on the page (there's only ever one Tawk widget), not one instance per call.

Getters

proxy is fire-and-forget: calls queue until the script loads and replay once it does, but their return value is always discarded, even after loading. That's fine for actions like proxy.maximize(), which don't return anything meaningful anyway, but it can't carry a real synchronous getter. getWindowType, getStatus, isChatMaximized, isChatMinimized, isChatHidden, isChatOngoing, isVisitorEngaged, and widgetPosition are exposed directly on useScriptTawkTo()'s return value instead, calling straight through to window.Tawk_API:

const { getStatus, isChatHidden } = useScriptTawkTo({
  propertyId: 'YOUR_PROPERTY_ID',
  widgetId: 'YOUR_WIDGET_ID',
})

getStatus() // 'online' | 'away' | 'offline' | undefined
isChatHidden() // boolean, false before the widget has loaded

Identifying visitors

proxy.visitor = {...} doesn't work for the same reason: unhead's script proxy has no set trap, so a property assignment through it never reaches the real Tawk_API. Use setVisitor() instead.

It is pre-load only. Tawk honors Tawk_API.visitor before the embed script loads and ignores it afterwards, so once the embed has been requested the call warns and does nothing. Change identity after load with window.Tawk_API.setAttributes({ name, email, phone, hash }).

const { proxy, setVisitor } = useScriptTawkTo({
  propertyId: 'YOUR_PROPERTY_ID',
  widgetId: 'YOUR_WIDGET_ID',
})

setVisitor({
  name: 'Jane Doe',
  email: '[email protected]',
  // HMAC-SHA256 signature for Secure Mode, generated server-side
  hash: visitorHash,
})
proxy.setAttributes({ plan: 'pro' })
proxy.addTags(['vip'])

Switching properties at runtime

const { proxy } = useScriptTawkTo({
  propertyId: 'YOUR_PROPERTY_ID',
  widgetId: 'YOUR_WIDGET_ID',
})

proxy.switchWidget({ propertyId: 'OTHER_PROPERTY_ID', widgetId: 'OTHER_WIDGET_ID' })
propertyIdstring required

Your Tawk.to property ID: the first path segment of the widget embed URL `https://embed.tawk.to/<propertyId>/<widgetId>`.

widgetIdstring required

Your Tawk.to widget ID: the second path segment of the widget embed URL `https://embed.tawk.to/<propertyId>/<widgetId>`.

Partytown

Do not run Tawk.to under Partytown. The widget renders DOM overlays (the chat bubble, prechat and full chat panels) directly, and the window CustomEvents the reactive state and listeners depend on aren't configured for worker forwarding.

Was this page helpful?