Documentation
Déployez votre Agent de conversion Versiq sur votre site en quelques minutes. Script tag ou NPM, à vous de choisir.
Vos données (catalogue · CRM · base de connaissances) → Agent
Agent → events → Votre CRM / analytics
L'Agent vit dans le portail
Vous le configurez une fois (verticale, marque, objectifs). Le widget est son canal d'affichage, pas l'Agent lui-même.
Vos données ancrent les réponses
Branchez vos sources (inventaire, CRM, base de connaissances) : l'Agent répond depuis vos données réelles, pas depuis la moyenne du web.
La clé publiable relie le tout
Une clé pk_* rattache le widget embarqué à un Agent et à sa configuration, résolue au chargement.
Choisissez votre approche
Idéal pour: WordPress, Shopify, sites statiques
VoirIdéal pour: React, Next.js, Vue
VoirIdéal pour: Découverte, évaluation
Essayer1. Créez l'Agent dans le portail
Dans /app/portal, créez un Agent : donnez-lui un nom et choisissez sa verticale (immobilier, B2B…).
2. Récupérez une clé test
Générez une clé pk_test_* depuis /app/portal/api-keys. Elle fonctionne sur localhost sans configuration de domaine.
3. Embarquez le widget
Collez le script tag (ci-dessous) avec votre clé dans une page servie en local. Aucune étape de build.
4. Conversez
Ouvrez la page : l'Agent démarre la conversation. Branchez l'événement ready ou qualified pour réagir côté site.
<!-- Add this script to your page -->
<!-- Production tip: pin a version + SRI, e.g. @0.2.0 + integrity="sha384-..." -->
<script
src="https://unpkg.com/@dolard.eu/versiq-widget@latest/dist/widget.umd.js"
data-api-key="pk_your_key"
></script>Le widget sépare volontairement deux types de clés publiques. Une clé test (pk_test_*) est conçue pour le développement local : elle fonctionne toujours sur localhost, 127.0.0.1 et *.localtest.me, sans aucune configuration de domaine. Une clé live (pk_live_*) est conçue pour vos environnements publics : elle refuse localhost et exige une whitelist de domaines explicite.
1. Développement local
Clé : pk_test_*- Domaine : aucune déclaration requise — les clés test autorisent toujours localhost, 127.0.0.1 et *.localtest.me.
Créez une clé test depuis /app/portal/api-keys, embarquez le widget sur http://localhost:3000 (ou le port de votre dev-serveur), et exercez toutes les fonctionnalités sans toucher à la page Domaines.
2. Staging / preview
Clé : pk_live_* (dédiée au staging)- Domaine à déclarer : https://staging.monsite.fr (URL exacte de votre environnement de preview)
Créez une clé live dédiée au staging — ne réutilisez jamais la clé de prod. Ajoutez l'URL exacte de votre environnement de preview dans /app/portal/domains. Si votre staging tourne sur un port custom (ex : preview-42.monsite.fr:8443), ajoutez l'URL complète avec port.
3. Production
Clé : pk_live_*- Domaine à déclarer : https://monsite.fr (ou wildcard *.monsite.fr pour couvrir plusieurs sous-domaines d'un coup)
Pour un site qui sert plusieurs sous-domaines (app, www, checkout…), un wildcard *.monsite.fr est plus maintenable que plusieurs entrées exactes. Attention : le wildcard couvre uniquement les sous-domaines directs — ajoutez monsite.fr en plus si le domaine apex sert aussi le widget.
Pourquoi cette séparation ?
Une clé live pk_live_* refuse localhost même en dev, et exige une whitelist de domaines. C'est intentionnel : si une clé live est volée (fuite dans un repo GitHub public, extension navigateur compromise, capture d'écran accidentelle), elle ne peut pas être utilisée depuis une page HTML locale ni depuis un site tiers non déclaré. L'attaquant qui récupère la clé ne peut rien en faire sans aussi contrôler un des domaines que vous avez explicitement autorisés. C'est la ceinture de sécurité qui compense l'exposition publique de la clé dans le HTML de vos pages.
Syntaxe des wildcards
Un wildcard *.monsite.fr matche app.monsite.fr, www.monsite.fr, checkout.monsite.fr — mais pas monsite.fr lui-même. Pour couvrir le domaine apex, ajoutez-le en entrée séparée. Les wildcards ne supportent qu'un seul niveau (*.monsite.fr ≠ **.monsite.fr) : a.b.monsite.fr n'est pas matché, il faut ajouter *.b.monsite.fr en plus.
Que se passe-t-il si le domaine n'est pas autorisé ?
Le serveur Versiq renvoie une erreur 403 ORIGIN_NOT_ALLOWED et le widget reste silencieux (aucune fenêtre de chat ne s'ouvre). Activez l'option debug du widget pendant l'intégration pour voir la réponse dans la console — c'est souvent la première chose à vérifier quand le widget ne s'affiche pas en staging.
npm install @dolard.eu/versiq-widgetimport { createWidget } from "@dolard.eu/versiq-widget";
const widget = createWidget({ apiKey: "pk_your_key" });
// Control the widget
widget.open();
widget.close();
widget.reset();| Option | Type | Défaut | Description |
|---|---|---|---|
| data-api-key | string | required | Clé API publiable (pk_*) — obligatoire, identifie votre Agent |
| data-container | string | - | Sélecteur CSS du conteneur pour le mode inline (ex: '#chat'). Côté SDK programmatique, accepte aussi un HTMLElement directement. |
| data-base-url | string | Production URL | URL de base pour l'embed |
| data-debug | boolean | false | Activer les logs de debug |
| data-email | string | - | Email pré-identifié du visiteur (vérification HMAC) |
| data-user-id | string | - | Identifiant utilisateur côté site hôte (vérification HMAC) |
| data-user-hash | string | - | HMAC-SHA256 du userId (ou email en fallback), signé avec le secret d'identité |
Flottant
Le widget apparaît comme un bouton flottant dans un coin de la page. C'est le mode par défaut : aucune option HTML n'est requise — la position se règle dans /app/portal/widget.
Intégré
Le widget est intégré directement dans un conteneur de votre page. Idéal pour une page contact ou une landing page dédiée. Indiquez un sélecteur CSS via data-container, ou un HTMLElement via le SDK programmatique.
import { createWidget } from "@dolard.eu/versiq-widget";
// container accepts a CSS selector OR an HTMLElement
const widget = createWidget({
apiKey: "pk_your_key",
container: "#chat-container",
});Script Tags
<!-- B2B qualification widget -->
<script
src="https://unpkg.com/@dolard.eu/versiq-widget@latest/dist/widget.umd.js"
data-api-key="pk_your_b2b_key"
></script>
<!-- Real estate widget (same page) -->
<script
src="https://unpkg.com/@dolard.eu/versiq-widget@latest/dist/widget.umd.js"
data-api-key="pk_your_immo_key"
></script>API programmatique
import { createWidget } from "@dolard.eu/versiq-widget";
// Each API key maps to an Agent with its own vertical, theme, and
// position — all configured from the admin portal.
const b2bWidget = createWidget({ apiKey: "pk_your_b2b_key" });
const immoWidget = createWidget({
apiKey: "pk_your_immo_key",
// container pins the widget to a specific DOM node (inline mode).
container: document.getElementById("demo-immo"),
});
// Access instances after they're ready
b2bWidget.on("ready", () => {
// window.VersiqApps.get(b2bWidget.applicationId) → VersiqAPI
console.log("B2B widget ready:", b2bWidget.applicationId);
});Configuration centralisée dans le portail
Depuis la version 2024.11, la personnalisation (couleurs, typographie, rayon des bordures, mode clair/sombre, position) est gérée depuis /app/portal/widget. Le widget résout ces réglages au chargement via la clé publiable — aucune modification côté HTML n'est nécessaire.
Ouvrir le portail →Basculer le mode clair/sombre à l'exécution
Pour synchroniser le mode d'affichage du widget avec celui de votre site hôte (toggle utilisateur, préférence système), utilisez l'API JavaScript window.Versiq.setColorScheme('light' | 'dark' | 'auto').
Versiq se connecte à vos données via une interface générique. Chaque source déclare ses capabilities, et les outils IA s'adaptent automatiquement.
Interface DataSource
Implémentez cette interface TypeScript pour brancher votre propre source de données.
interface DataSource {
readonly id: string;
readonly displayName: string;
readonly coverageDescription: string;
getCapabilities(): ReadonlySet<DataSourceCapability>;
search?(params: Record<string, unknown>): Promise<unknown[]>;
getStats?(zone: string): Promise<Record<string, unknown>>;
getAreaMetrics?(zone: string, filters: Record<string, unknown>): Promise<Record<string, unknown>>;
estimate?(params: Record<string, unknown>): Promise<Record<string, unknown>>;
count?(areas: string[], filters: Record<string, unknown>): Promise<number>;
checkCoverage?(zone: string): Promise<{ covered: boolean; message?: string }>;
}Capabilities
Chaque capability active un ou plusieurs outils IA dans la conversation.
| Capability | Méthode | Outils | Description |
|---|---|---|---|
search | search() | searchProperties | Recherche de biens/produits avec filtres |
stats | getStats() | getCityStats | Statistiques agrégées par zone |
areaMetrics | getAreaMetrics() | getAreasOverview | Métriques détaillées par zone (overview) |
estimate | estimate() | estimateProperty, estimateRent | Estimation de prix ou valeur |
count | count() | getPropertyCount | Comptage avec filtres |
coverage | checkCoverage() | checkZoneCoverage | Vérification de zone couverte |
Exemple : API REST
Un exemple concret d'implémentation connectée à une API REST tierce.
class MyApiDataSource implements DataSource {
readonly id = "my-api";
readonly displayName = "Mon API Produits";
readonly coverageDescription = "Catalogue produit via API REST";
getCapabilities() {
return new Set(["search", "count"]);
}
async search(params) {
const res = await fetch(`https://api.example.com/products?${qs(params)}`);
return res.json();
}
async count(areas, filters) {
const res = await fetch("https://api.example.com/products/count", {
method: "POST",
body: JSON.stringify({ areas, filters }),
});
const data = await res.json();
return data.count;
}
}Dégradation gracieuse
Quand une source ne supporte que certaines capabilities, les outils non supportés sont automatiquement masqués. Le partenaire n'a rien à configurer côté outils.
searchstatsestimatecountareaMetricscoverageModes d'accès
Versiq s'adapte à votre infrastructure. Le mode custom (DataSource) est disponible aujourd'hui ; les connecteurs natifs et les protocoles standard arrivent.
Quand l'utiliser
La vérification d'identité est conçue pour les zones authentifiées où les visiteurs sont déjà connectés — dashboards SaaS, portails clients, espaces membres. Elle n'est pas destinée aux pages marketing publiques où les visiteurs sont anonymes.
Niveaux d'identité
| Option | Type | Défaut | Description |
|---|---|---|---|
| Anonyme | Cookie / ID de session | - | Par défaut pour tous les visiteurs — aucune configuration requise |
| Identifié | Email partagé dans le chat | - | Le visiteur partage son email pendant la conversation |
| Vérifié | HMAC attesté par le site hôte | - | Le site hôte atteste cryptographiquement l'identité du visiteur — zéro friction |
Étape 1 : Calculer le HMAC côté serveur
Le HMAC doit être calculé sur votre backend. N'exposez jamais le secret dans le code client.
Node.js
import crypto from "node:crypto";
// Sign the stable userId when you have one (recommended), else the email.
// Send both data-user-id and data-user-hash; data-email stays optional.
const signedValue = user.id ?? user.email;
const hmac = crypto
.createHmac("sha256", process.env.VERSIQ_IDENTITY_SECRET)
.update(signedValue)
.digest("hex");Python
import hmac
import hashlib
import os
# Sign the stable user id when you have one (recommended), else the email.
# Send both data-user-id and data-user-hash; data-email stays optional.
signed_value = user.id or user.email
user_hash = hmac.new(
os.environ["VERSIQ_IDENTITY_SECRET"].encode(),
signed_value.encode(),
hashlib.sha256,
).hexdigest()Étape 2 : Transmettre l'identité au widget
Ajoutez les attributs d'identité à votre balise script widget, ou utilisez l'API programmatique après le login.
Balise script
<script
src="https://unpkg.com/@dolard.eu/versiq-widget@latest/dist/widget.umd.js"
data-api-key="pk_live_..."
data-email="${user.email}"
data-user-id="${user.id}"
data-user-hash="${hmac}"
></script>Dynamique (post-login)
Pour les SPA, identifiez le visiteur après le login sans recharger la page.
// After user logs in, identify them dynamically
window.Versiq.identify({
email: "user@example.com",
userId: "usr_123",
userHash: "<computed_hmac>",
});Entrée HMAC
Le HMAC est calculé sur le userId s'il est fourni (identifiant stable, recommandé), ou l'email en fallback. Utiliser le userId permet de garder le HMAC valide même si l'utilisateur change d'email.
Sécurité
Le secret d'identité ne doit jamais apparaître dans le code client. Générez-le dans votre tableau de bord Versiq sous Paramètres > Vérification d'identité.
| Option | Type | Défaut | Description |
|---|---|---|---|
| ready | - | - | Le widget est chargé et prêt |
| open | - | - | Le widget a été ouvert |
| close | - | - | Le widget a été fermé |
| message | WidgetMessage | - | Nouveau message dans la conversation |
| profile-update | WidgetProfile | - | Le profil utilisateur a été mis à jour |
| qualified | { profile, score } | - | Lead qualifié avec score de pertinence |
| quota-warning | { remaining, limit } | - | Le quota API approche de la limite |
| quota-exceeded | - | - | Le quota API est dépassé |
| error | { code, message } | - | Une erreur s'est produite |
| identity-verified | { email, userId? } | - | L'identité du visiteur a été vérifiée par HMAC |
Exemple d'utilisation
// Subscribe to events
window.Versiq.on("ready", () => {
console.log("Agent is ready");
});
window.Versiq.on("profile-update", (data) => {
console.log("Profile updated:", data.profile);
});
window.Versiq.on("qualified", (data) => {
console.log("Lead qualified:", data.profile);
console.log("Score:", data.score);
// Send to your CRM
});
window.Versiq.on("identity-verified", (data) => {
console.log("Identity verified:", data.email);
});
window.Versiq.on("quota-warning", (data) => {
console.warn("Quota low:", data.remaining, "/", data.limit);
});
window.Versiq.on("error", (data) => {
console.error("Error:", data.code, data.message);
});| Option | Type | Défaut | Description |
|---|---|---|---|
| open() | void | - | Ouvrir le widget |
| close() | void | - | Fermer le widget |
| reset() | void | - | Réinitialiser la conversation |
| setTheme(theme) | void | - | Changer le thème dynamiquement |
| setColorScheme(scheme) | void | - | Basculer le mode d'affichage ('light' | 'dark' | 'auto') — utile pour câbler le toggle du site host |
| on(event, handler) | void | - | S'abonner à un événement |
| off(event, handler) | void | - | Se désabonner d'un événement |
| destroy() | void | - | Supprimer le widget et libérer les ressources |
| identify(params) | void | - | Identifier un visiteur avec vérification HMAC |
| version | string | - | Version courante du SDK (lecture seule) |
| applicationId | string | "" | ID de l'Agent (applicationId) résolu après chargement (vide tant que ready n'a pas été émis) |
| window.VersiqApps | Map<string, VersiqAPI> | - | Map globale des instances widget — clé : applicationId, valeur : VersiqAPI |