Widget pour votre site web
Le widget est le chat que les visiteurs voient sur votre site. Il charge le bot que vous avez publié et gère toute la conversation dans le navigateur. Sans modèle de langage, sans requêtes vers des tiers, pour environ 22 Ko après compression. Le chat avec un conseiller est chargé depuis un fichier distinct, uniquement lorsque vous l’activez.
Installation
Collez cette ligne avant </body> sur chaque page où le bot doit apparaître. Le tableau de bord l’affiche avec votre clé sur la page Installation.
<script src="https://cdn.kavchat.com/v1/kavchat.js" data-key="pk_live_..." async></script>Vous pouvez placer la clé publique (pk_live_...) dans une page. Ne placez jamais la clé secrète (sk_live_...) dans une page.
Attributs
| Attribut | Valeur par défaut | Description |
|---|---|---|
data-key | Obligatoire | Votre clé publique. |
data-api | https://api.kavchat.com | Adresse de l’API. |
data-locale | Langue du navigateur | Langue de l’interface du widget (boutons, formulaire, messages) : he, en, ar, ru, es, fr, de, pt, it, tr. Si aucune traduction n’est disponible, la langue du bot est utilisée. Le contenu du script s’affiche toujours tel que vous l’avez rédigé. he et ar s’affichent de droite à gauche. |
data-user-token | Aucune | Jeton d’identité d’un utilisateur connecté. Voir Identification des utilisateurs. |
data-user-name | Aucune | Affiché dans le message d’accueil ({name}) et prérempli dans le formulaire de contact. |
data-open | false | Avec "true", le chat s’ouvre dès son chargement. |
<script
src="https://cdn.kavchat.com/v1/kavchat.js"
data-key="pk_live_..."
data-locale="he"
data-user-token="<identity JWT>"
data-user-name="Dana"
data-open="false"
async></script>API JavaScript
Le script installe window.Kavchat :
Kavchat.init({
publicKey: 'pk_live_...',
apiBase: 'https://api.kavchat.com', // optional
locale: 'he', // optional
userToken: '<identity JWT>', // optional
userName: 'Dana', // optional
open: false, // optional
onScreen(screen, targetId) {}, // optional: "screen" buttons in your scripts
onEvent(event) {}, // optional: ready, unavailable, open, close, effect, ticket
});
Kavchat.open();
Kavchat.close();
Kavchat.toggle();
Kavchat.setUser({ token: '<identity JWT>', name: 'Dana' }); // on login; setUser(null) on logout
Kavchat.offset({ bottom: 80 }); // lift the launcher, e.g. above a cookie banner; offset(null) resets
Kavchat.destroy();L’appel à init n’est pas nécessaire si la balise du script contient data-key. Un nouvel appel à init remplace le widget en cours d’exécution.
Appeler l’API avant le chargement du script
La balise du script est async : votre code peut donc s’exécuter avant son chargement. Créez une file d’attente et ajoutez-y les appels. Le widget les exécute dans l’ordre à son chargement. init s’exécute toujours en premier, et ses paramètres priment sur les attributs de la balise.
<script>
window.Kavchat = window.Kavchat || { q: [] };
Kavchat.q.push(['init', { publicKey: 'pk_live_...', onScreen: function (s, id) { location.href = '/' + s + '/' + id; } }]);
Kavchat.q.push(['setUser', { token: '<identity JWT>', name: 'Dana' }]);
</script>
<script src="https://cdn.kavchat.com/v1/kavchat.js" async></script>Chaque élément de la file est de la forme [methodName, ...args]. Après le chargement du script, Kavchat.q.push(...) continue de fonctionner et exécute l’appel immédiatement. Le même code convient donc aux deux cas.
Prévoir de la place pour un bandeau de cookies
Si votre site comporte un élément fixe en bas de l’écran, comme un bandeau de cookies, vous pouvez déplacer le bouton, la fenêtre et les bulles au-dessus de cet élément. Deux méthodes sont possibles : la variable CSS --kavchat-bottom ou la commande Kavchat.offset, qui accepte un nombre en pixels ou une valeur de longueur comme 5rem. Le décalage s’ajoute à la hauteur définie dans l’interface d’administration. À la fermeture du bandeau, supprimez la variable ou appelez offset(null). Les deux méthodes fonctionnent aussi sur un site doté d’une CSP stricte. Sur téléphone, la fenêtre s’ouvre en plein écran et ne se décale pas.
/* while your cookie banner is shown */
body.cookie-banner-open { --kavchat-bottom: 80px; }// works before or after the widget script loads
window.Kavchat = window.Kavchat || { q: [] };
Kavchat.q.push(['offset', { bottom: banner.offsetHeight + 12 }]);
// after the visitor makes a choice
Kavchat.q.push(['offset', null]);Événements
La fonction onEvent reçoit l’un des événements suivants :
type | Champs | Déclenchement |
|---|---|---|
ready | version, offline | Le bot a été chargé depuis le réseau, ou depuis la copie enregistrée en l’absence de connexion. |
unavailable | reason? ('quota') | Le bot est désactivé, réservé aux utilisateurs de test ou son quota est épuisé. Rien ne s’affiche. |
open, close | La fenêtre a été ouverte ou fermée. | |
effect | effect | Un bouton a demandé l’ouverture du formulaire de contact, d’un lien ou d’un écran. |
ticket | id, number | Un ticket a été créé. |
live | state, id | L’état de la conversation avec le conseiller a changé : queued, active, closed ou ticket. |
Kavchat.init({
publicKey: 'pk_live_...',
onEvent(event) {
if (event.type === 'ready') console.log('Bot version', event.version, event.offline ? '(offline copy)' : '');
if (event.type === 'ticket') console.log('Request opened', event.number);
},
});Actions du script
- Contact : ouvre le formulaire de contact dans le chat. La transcription de la conversation est jointe au ticket.
- Lien : ouvre les liens
https:ettel:dans un nouvel onglet (rel="noopener noreferrer"). Les autres types de liens ne sont pas ouverts. - Écran : appelle votre fonction
onScreen(screen, targetId). Sans cette fonction, le bouton n’a aucun effet sur le site.
Liste des écrans dans l’éditeur
Déclarez une seule fois les écrans que l’application peut ouvrir dans l’option screens de Kavchat.init. Le SDK envoie lui-même la liste à Kavchat. L’éditeur de scripts propose alors ces écrans avec leurs noms dans une liste déroulante, à la place d’un champ de texte libre. Il demande aussi un identifiant d’élément lorsqu’un écran en a besoin et signale les boutons qui pointent vers un écran non déclaré. Personne n’a à saisir manuellement la liste des écrans dans le tableau de bord.
Kavchat.init({
publicKey: 'pk_live_...',
screens: [
{ id: 'orders', label: 'My orders' },
{ id: 'product', label: 'Product page', needsTarget: true }, // the button also carries a product id
],
onScreen(screen, targetId) {
location.href = targetId ? `/${screen}/${targetId}` : `/${screen}`;
},
});idest la valeur transmise àonScreen: lettres latines, chiffres,_,.et-, dans la limite de 40 caractères.labelest le nom affiché pour l’administrateur, dans la limite de 60 caractères. Jusqu’à 100 écrans. Les entrées non valides et les identifiants en double sont ignorés.needsTarget: le bouton contient aussi un identifiant d’élément (par exemple, un identifiant de produit), transmis àonScreensous la forme detargetId.- La liste est envoyée en arrière-plan après le chargement de la version, uniquement si elle a changé ou une fois par semaine. Un échec reste invisible et l’envoi est retenté au prochain lancement. Rien ne s’affiche pour l’utilisateur.
- Les écrans enregistrés apparaissent dans le tableau de bord sous Bot, Paramètres, « Écrans de l’application », avec les plateformes qui ont déclaré chaque écran. Vous pouvez y supprimer un écran retiré de l’application.
Identification de vos utilisateurs
Pour associer votre propre identifiant utilisateur aux conversations et aux tickets, ou pour afficher le bot uniquement aux utilisateurs de test, signez un JWT sur votre serveur et transmettez-le via data-user-token ou userToken. Appelez Kavchat.setUser(...) lorsque l’utilisateur se connecte ou se déconnecte. Le widget envoie le jeton dans l’en-tête Authorization: Bearer <token> à chaque appel. Un utilisateur connecté peut ouvrir un ticket sans laisser d’adresse e-mail ni de numéro de téléphone. Pour créer le jeton, consultez Identification des utilisateurs.
Politique CSP
Le widget fonctionne sur un site avec une CSP stricte, sans 'unsafe-inline' ni 'unsafe-eval'. Il suffit d’autoriser nos deux sources :
script-src https://cdn.kavchat.com;
connect-src https://api.kavchat.com;Les styles sont chargés sous forme de constructable stylesheets dans le Shadow DOM. Il n’est donc pas nécessaire de modifier style-src. Si le bot possède sa propre image ou si les scénarios contiennent des images, ajoutez à img-src le serveur depuis lequel elles sont chargées. Le widget ne charge aucune ressource depuis une autre source et n’ouvre aucun iframe.
Chat avec un conseiller
Vous n’avez rien à configurer sur le site. Lorsque vous activez le chat avec des conseillers dans l’interface d’administration, le widget charge un fichier supplémentaire, kavchat-live.js, depuis le même dossier et dans la même version que kavchat.js. Les sites sans chat avec des conseillers ne téléchargent pas ce fichier.
- L’option : l’option « Discuter avec un conseiller » apparaît à côté de « Contacter l’équipe », uniquement après confirmation par le serveur qu’un conseiller est disponible. En dehors des horaires d’ouverture, ou lorsque tous les conseillers sont occupés, seul le formulaire de contact s’affiche. Une courte explication l’accompagne, ainsi que l’heure de retour de l’équipe si elle est connue. Lorsque le quota mensuel est épuisé, le formulaire s’affiche sans explication.
- La demande : les visiteurs non connectés laissent une adresse e-mail ou un numéro de téléphone, au cas où aucun conseiller ne se libérerait à temps. Ils peuvent aussi ajouter un nom et un premier message. Si plusieurs services sont ouverts, ils en choisissent un. Les utilisateurs identifiés (
userToken) n’ont pas à saisir leurs coordonnées. Si aucun conseiller ne peut prendre la conversation, le formulaire de contact s’ouvre avec les informations déjà saisies. - L’attente : le message « En attente d’un conseiller » s’affiche avec un compte à rebours jusqu’à la fin du délai d’attente que vous avez défini, ainsi que les boutons « Laisser un message à la place » et « Terminer la conversation ». Les visiteurs peuvent déjà écrire pendant l’attente. À la fin du délai, la conversation est automatiquement convertie en ticket. Le visiteur voit le numéro du ticket et une explication indiquant qu’aucun conseiller ne s’est libéré à temps.
- La conversation : nom du conseiller, messages, indicateur de saisie, transfert à un autre conseiller et fin de la conversation. Tout ce qui provient du serveur s’affiche en texte brut, sans HTML ni liens. Les lecteurs d’écran annoncent les nouveaux messages et, lorsque la fenêtre est fermée, un point apparaît sur le bouton flottant.
- Temps réel : la connexion utilise Server-Sent Events. En cas de coupure, le widget tente de se reconnecter à intervalles croissants et récupère tout ce qui a été manqué. Ainsi, aucun message n’est perdu ni affiché deux fois. Sur les réseaux qui bloquent cette connexion, le widget passe à des requêtes répétées (long-poll). Chaque message possède un identifiant : une nouvelle tentative ne crée donc pas de doublon. Un message non envoyé est signalé et peut être renvoyé d’un clic.
- Rechargement : l’autorisation d’accès à la conversation est conservée dans
localStorage, par clé publique et par conversation, jamais dans l’URL. Elle reste valide jusqu’à 12 heures ou jusqu’à la fin de la conversation. Après un rechargement ou le passage à une autre page, toute la conversation est donc restaurée : la partie avec le bot, puis celle avec le conseiller. - Sans preflight : les appels sont envoyés sans en-têtes particuliers, et le corps de la requête est du JSON envoyé en
text/plain.
Réponses de l’IA (Premium)
Vous n’avez rien à configurer sur le site. Lorsque vous activez les réponses de l’IA dans l’interface d’administration (avec votre propre clé de fournisseur d’IA), toute question à laquelle aucun script ne répond est envoyée à Kavchat. Pendant l’attente, jusqu’à 20 secondes, le chat indique que le bot est en train d’écrire. La réponse s’affiche en texte brut avec une petite mention « Réponse de l’IA » dans la langue de l’interface. En dessous figurent un bouton vers un sujet connexe, s’il y en a un, et un bouton « Contacter l’équipe ».
En l’absence de réponse, ou si la requête échoue, prend trop de temps ou dépasse la limite (10 réponses par conversation toutes les 15 minutes), le chat affiche son message habituel « Je n’ai pas trouvé de réponse ». La question figure toujours dans le rapport des questions sans réponse, et les réponses de l’IA sont conservées dans la conversation enregistrée comme tout autre message.
Fonctionnement du widget
- Isolation : tout s’affiche dans un Shadow DOM. Votre CSS n’affecte pas le widget, et le CSS du widget n’affecte pas la page.
- Cache : le bot publié est conservé dans
localStoragepar clé publique, avec son ETag. À chaque chargement, l’en-têteIf-None-Matchest envoyé. Si rien n’a changé, le serveur répond avec le code 304. En l’absence de connexion, le widget utilise la copie enregistrée et affiche un message pour le signaler. - Conversations : un identifiant de conversation aléatoire est conservé dans
sessionStorage, ce qui permet de poursuivre la même conversation d’une page à l’autre. - Chat avec un conseiller : une conversation ouverte est conservée dans
localStorageet restaurée sur la page suivante. - Données : le déroulement de la conversation est transmis environ 2 secondes après chaque action, ainsi que lorsque la page est masquée.
- Badge Kavchat : il s’affiche dans toutes les offres. Avec Premium, vous pouvez le masquer dans les paramètres du bot.
- Accessibilité : la fenêtre est une boîte de dialogue dotée d’un libellé. Le focus y entre à l’ouverture et revient à son point de départ à la fermeture. La touche Échap la ferme, les boutons sont de véritables boutons, les nouveaux messages du bot sont lus par les lecteurs d’écran et les animations sont réduites lorsque le visiteur en a fait la demande.
Installation via npm
Dans une application monopage, vous pouvez intégrer le widget à votre code plutôt que de charger la balise du script :
yarn add @kavchat/widget
# or: npm install @kavchat/widgetimport { createWidget } from '@kavchat/widget';
const widget = createWidget({ publicKey: 'pk_live_...' });
await widget.ready;
widget.open();