Skip to content

Installation

You can add the widget to your site through the CDN (a script tag) or the npm package. At its simplest a single line is enough; below are examples for each environment.

Setup

If you are using npm, add the package first:

bash
yarn add @webfon/client

Then mount the widget the way your environment expects:

html
<!-- Static site, WordPress, or any HTML page -->
<script src="https://assets.webfon.io/sdk.js" data-provider-id="PROVIDER_ID" async></script>
vue
<script setup>
import { onMounted, onUnmounted } from 'vue';
import { initWebfon } from '@webfon/client';

let widget;
onMounted(() => { widget = initWebfon({ providerId: 'PROVIDER_ID' }); });
onUnmounted(() => widget?.destroy());
</script>
jsx
import { useEffect } from 'react';
import { initWebfon } from '@webfon/client';

export function WebfonWidget() {
  useEffect(() => {
    const widget = initWebfon({ providerId: 'PROVIDER_ID' });
    return () => widget?.destroy();          // clean up on unmount
  }, []);

  return null; // the widget adds its own host element to Shadow DOM
}
svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  import { initWebfon } from '@webfon/client';

  let widget;
  onMount(() => { widget = initWebfon({ providerId: 'PROVIDER_ID' }); });
  onDestroy(() => widget?.destroy());
</script>

When the DOM is ready and it finds a providerId, the CDN bundle mounts the widget automatically. On npm, initWebfon(config) returns an instance — see Method Reference for all methods. The widget creates its own Shadow DOM host; that host is independent of your Vue/React/Svelte application.

CDN data-* attributes

data-* can only carry strings:

AttributeRequiredDescription
data-provider-idProvider ID
data-api-urlOverrides the API base URL (default: https://api.webfon.io)

Settings that carry a function, such as getToken, cannot be passed through data-*; define window.WebfonConfig before the script instead (see the full example below). For manual control (instead of automatic mounting), use window.Webfon.init().

Full example

A complete setup with member login (getToken), your own "Chat" button, an event callback, and cleanup. getToken receives the fingerprint of the widget's connection key (jkt) and forwards it to your backend; your backend signs the socket token (see Authentication).

html
<script>
  window.WebfonConfig = {
    providerId: 'PROVIDER_ID',
    apiUrl: 'https://api.webfon.io',            // optional (this is the default)
    getToken: async ({ jkt }) => {              // null for non-members → visitor
      const res = await fetch('/api/webfon-token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ jkt }),
      });
      return res.ok ? (await res.json()).token : null;
    },
    onMessage: (m) => console.log('new message', m),
  };
</script>
<script src="https://assets.webfon.io/sdk.js" async></script>
<button onclick="window.Webfon.open()">Live Support</button>
vue
<script setup>
import { onMounted, onUnmounted } from 'vue';
import { initWebfon, toggleApp } from '@webfon/client';

let widget;
onMounted(() => {
  widget = initWebfon({
    providerId: 'PROVIDER_ID',
    getToken: async ({ jkt }) => {              // null for non-members → visitor
      const res = await fetch('/api/webfon-token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ jkt }),
      });
      return res.ok ? (await res.json()).token : null;
    },
    onMessage: (m) => console.log('new message', m),
  });
});
onUnmounted(() => widget?.destroy());
</script>

<template>
  <button @click="toggleApp(true)">Live Support</button>
</template>
jsx
import { useEffect } from 'react';
import { initWebfon, toggleApp } from '@webfon/client';

export function WebfonWidget() {
  useEffect(() => {
    const widget = initWebfon({
      providerId: 'PROVIDER_ID',
      getToken: async ({ jkt }) => {            // null for non-members → visitor
        const res = await fetch('/api/webfon-token', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include',
          body: JSON.stringify({ jkt }),
        });
        return res.ok ? (await res.json()).token : null;
      },
      onMessage: (m) => console.log('new message', m),
    });
    return () => widget?.destroy();
  }, []);

  return <button onClick={() => toggleApp(true)}>Live Support</button>;
}
svelte
<script>
  import { onMount, onDestroy } from 'svelte';
  import { initWebfon, toggleApp } from '@webfon/client';

  let widget;
  onMount(() => {
    widget = initWebfon({
      providerId: 'PROVIDER_ID',
      getToken: async ({ jkt }) => {            // null for non-members → visitor
        const res = await fetch('/api/webfon-token', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include',
          body: JSON.stringify({ jkt }),
        });
        return res.ok ? (await res.json()).token : null;
      },
      onMessage: (m) => console.log('new message', m),
    });
  });
  onDestroy(() => widget?.destroy());
</script>

<button on:click={() => toggleApp(true)}>Live Support</button>

TIP

See Configuration for every parameter you can pass, and Authentication for member login and token-signing examples.

Webfon live-support widget documentation