Guide développeur
API d'identification des visiteurs
Identifiez par programmation les utilisateurs connectés : ils ne voient jamais la demande d'e-mail, et leurs conversations sont automatiquement rattachées à un contact.
Quand l'utiliser
Si votre site a des utilisateurs connectés (applications SaaS, tableaux de bord, espaces membres), vous savez déjà qui ils sont. Utilisez la commande identify pour transmettre leur e-mail à Sonny afin qu'ils n'aient pas à le saisir de nouveau.
- Supprimez complètement la demande d'e-mail pour les utilisateurs connectés
- Rattachez automatiquement les conversations de chat à leur fiche contact
- Voyez immédiatement le nom et l'e-mail du visiteur dans votre boîte de réception
- Retrouvez l'historique d'un navigateur et d'un appareil à l'autre grâce à l'identité vérifiée
Continuité entre appareils
Identité vérifiée des visiteurs
L'identification simple par e-mail est pratique, mais le navigateur peut prétendre n'importe quel e-mail. L'identité vérifiée ajoute un JWT de courte durée signé par votre serveur. Sonny peut alors utiliser en toute sécurité le contact du client comme propriétaire de son historique de chat sur le site : les mêmes conversations apparaissent sur un autre navigateur ou appareil.
Désactivé
Le réglage par défaut. Rien ne change pour les intégrations ou les visiteurs existants ; l'historique reste lié à l'identifiant visiteur du navigateur.
Vérification facultative (recommandé)
Les JWT valides bénéficient de l'historique entre appareils. Les visiteurs sans JWT conservent l'expérience actuelle, anonyme ou identifiée par e-mail.
Exiger une preuve pour l'identification
Le chat anonyme fonctionne toujours, mais les appels identify et d'attributs personnalisés exigent un JWT signé valide.
Le mode de vérification ne rend pas facultatifs les champs obligatoires avant le chat. Découvrez comment chaque mode satisfait un e-mail obligatoire dans informations obligatoires avant le chat.
1. Générer un secret de signature
Ouvrez Canaux → votre canal → Chat en direct, repérez Identité visiteur sécurisée, choisissez un mode et générez un secret. Le texte en clair n'est affiché qu'une seule fois. Enregistrez-le dans le gestionnaire de secrets de votre backend sous SONNY_IDENTITY_SECRET. Ne placez jamais le secret de signature dans du code exécuté par le navigateur, un extrait d'intégration, une variable d'environnement publique ou votre dépôt de code source.
2. Émettre un JWT de courte durée sur votre backend
Signez avec HS256. Sonny exige user_id, email, iat et exp. Le user_id doit être un identifiant stable de votre propre base de données, pas une adresse e-mail. Les jetons peuvent durer au maximum 24 heures ; 15 minutes est une bonne valeur par défaut. Les horloges peuvent différer de 60 secondes au plus.
Vous pouvez aussi inclure un objet traits signé par le serveur pour un contexte de support fiable, comme merchantName, subdomain, plan, platform et role. Les valeurs des attributs doivent être des chaînes, des nombres finis, des booléens ou null. Sonny les enregistre sur l'identité de contact vérifiée propre au site. Les attributs fournis par le navigateur restent non vérifiés et ne sont jamais promus parmi ces attributs signés.
import { SignJWT } from 'jose';
export async function createSonnyIdentityToken(user) {
const secret = new TextEncoder().encode(process.env.SONNY_IDENTITY_SECRET);
return new SignJWT({
user_id: String(user.id),
email: user.email,
traits: {
merchantName: user.merchant.name,
subdomain: user.merchant.subdomain,
plan: user.merchant.plan,
platform: user.merchant.platform,
role: user.role
}
})
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('15m')
.sign(secret);
}require 'jwt'
def sonny_identity_token(user)
now = Time.now.to_i
payload = {
user_id: user.id.to_s,
email: user.email,
traits: {
merchantName: user.merchant.name,
subdomain: user.merchant.subdomain,
plan: user.merchant.plan,
platform: user.merchant.platform,
role: user.role
},
iat: now,
exp: now + 15 * 60
}
JWT.encode(payload, ENV.fetch('SONNY_IDENTITY_SECRET'), 'HS256')
endimport os
from datetime import datetime, timedelta, timezone
import jwt
def sonny_identity_token(user):
now = datetime.now(timezone.utc)
return jwt.encode({
"user_id": str(user.id),
"email": user.email,
"traits": {
"merchantName": user.merchant.name,
"subdomain": user.merchant.subdomain,
"plan": user.merchant.plan,
"platform": user.merchant.platform,
"role": user.role,
},
"iat": now,
"exp": now + timedelta(minutes=15),
}, os.environ["SONNY_IDENTITY_SECRET"], algorithm="HS256")use Firebase\JWT\JWT;
function sonnyIdentityToken($user): string {
$now = time();
return JWT::encode([
'user_id' => (string) $user->id,
'email' => $user->email,
'traits' => [
'merchantName' => $user->merchant->name,
'subdomain' => $user->merchant->subdomain,
'plan' => $user->merchant->plan,
'platform' => $user->merchant->platform,
'role' => $user->role,
],
'iat' => $now,
'exp' => $now + (15 * 60),
], $_ENV['SONNY_IDENTITY_SECRET'], 'HS256');
}3. Ne transmettre que le JWT au widget
Renvoyez le JWT depuis un point de terminaison protégé par la session habituelle de votre application. Appelez identify avant ou après init. Le widget garde le JWT uniquement en mémoire : il n'est jamais enregistré dans localStorage, dans des cookies ni dans une URL.
// Fetch a short-lived JWT from your authenticated backend.
// Your signing secret never reaches this code.
const { userJwt } = await fetch('/api/sonny-identity').then((res) => res.json());
sonny('identify', { userJwt });
sonny('init', { siteId: 'YOUR_SITE_ID' });
// Sonny asks for a fresh token after expiry or an emergency key change.
window.addEventListener('sonny:identity-required', async () => {
const { userJwt } = await fetch('/api/sonny-identity').then((res) => res.json());
sonny('identify', { userJwt });
});Actualiser, se déconnecter et faire tourner les secrets en toute sécurité
- Actualisation : actualisez le JWT avant son expiration — vers 10 minutes pour un jeton de 15 minutes — puis appelez
sonny('identify', { userJwt }). Écoutez aussisonny:identity-required, solution de repli en cas d'expiration ou de changement de clé de signature. - Déconnexion : appelez
sonny('reset'). Cela supprime le JWT en mémoire, efface la session du widget dans le navigateur et démarre un nouveau visiteur anonyme. - Changement de compte : appelez
sonny('reset')pour l'utilisateur A avant de récupérer le JWT de l'utilisateur B et d'appelersonny('identify', { userJwt }). Ne transférez jamais le jeton d'un utilisateur vers une autre session connectée. - Rotation de routine : Sonny accepte l'ancien secret pendant 24 heures, ce qui vous laisse le temps de mettre à jour chaque instance de votre backend. Une deuxième rotation de routine est bloquée tant que ce chevauchement n'est pas terminé.
- Fuite de secret suspectée : choisissez Remplacer immédiatement. Les deux anciennes clés de signature cessent aussitôt d'authentifier les nouvelles requêtes ; les widgets connectés demandent un nouveau JWT à la page hôte.
- Désactiver la vérification : Sonny supprime les secrets de signature actuel et précédent et déconnecte les widgets vérifiés. Générez un nouveau secret avant de réactiver la vérification.
Les conflits d'identité ne sont pas fusionnés automatiquement
Si un identifiant utilisateur stable et un e-mail pointent vers des contacts Sonny différents, la vérification renvoie un conflit au lieu de combiner silencieusement les fiches clients. Corrigez le jeton ou fusionnez les contacts dans Sonny, puis réessayez.
Un chat rattaché uniquement par un ancien e-mail non signé n'est pas automatiquement considéré comme un historique vérifié. Cela empêche un e-mail fourni par le navigateur de débloquer les conversations d'un autre client.
Connexion au centre d'aide
Reliez la connexion client existante de votre application aux pages d'aide hébergées ou sur domaine personnalisé. Utilisez le même secret de signature du site et le même JWT de courte durée que pour le widget. L'identification simple par e-mail et la connexion du personnel Sonny n'accordent pas l'accès lecteur vérifié.
- Terminez d'abord la configuration de l'identité vérifiée des visiteurs ci-dessus pour ce canal. Activez Vérification facultative ou Exiger une preuve pour l'identification sous Canaux → votre canal → Chat en direct.
- Implémentez dans votre application un point de terminaison authentifié qui renvoie
{ "userJwt": "SIGNED_TOKEN" }. Émettez le jeton sur votre serveur à partir du client connecté et d'attributs fiables ; n'acceptez jamais un forfait ou un rôle demandé par le navigateur. - Dans Canaux → votre canal → Centre d'aide → Accès au centre d'aide, choisissez Clients vérifiés et, si vous le souhaitez, une Audience client. Saisissez la page de connexion de votre application comme URL de connexion client et sélectionnez Enregistrer l'accès.
- Une fois le client connecté, exécutez l'échange ci-dessous en remplaçant YOUR_SLUG par l'adresse du centre d'aide. L'URL de connexion seule ne suffit pas : votre application doit effectuer cet échange.
// Run after your application authenticates the customer.
// This endpoint must use the server's session and trusted customer traits.
const response = await fetch('/api/sonny-identity');
if (!response.ok) throw new Error('Unable to sign in to the help center');
const { userJwt } = await response.json();
const signIn = new URL('https://www.usesonny.com/help/YOUR_SLUG/auth');
signIn.searchParams.set('token', userJwt);
signIn.searchParams.set('return', '/help/YOUR_SLUG');
window.location.assign(signIn);Pour un domaine personnalisé, définissez signIn sur https://help.example.com/auth et le retour sur / ou /articles/getting-started. Les chemins de retour hébergés commencent par /help/YOUR_SLUG. Les destinations de retour doivent rester sur le même hôte.
L'échange définit un cookie sécurisé HTTP-only et redirige pour retirer le jeton de l'URL. La session lecteur expire avec le JWT, au maximum 24 heures. Utilisez des jetons de courte durée et évitez de journaliser l'URL d'échange. Le JWT n'a sa place que dans cet échange de connexion, pas dans les liens d'articles partagés.
Tester la connexion et les accès
- Visitez un centre privé en étant déconnecté. Suivez son bouton de connexion, connectez-vous à votre application et vérifiez que vous revenez au centre d'aide sur le même domaine hébergé ou personnalisé.
- Vérifiez un article autorisé et un article refusé dans la navigation, la recherche et par URL directe. Un client hors de l'audience du centre voit un message d'accès ; un article refusé renvoie « introuvable ».
- Utilisez Se déconnecter dans le centre d'aide et vérifiez que le contenu privé disparaît. Recommencez avec un client qui a des attributs différents.
Actualisation et déconnexion
Le widget envoie automatiquement son JWT actuel. Actualisez-le quand Sonny en demande un, et appelez sonny('reset') quand votre client se déconnecte. L'identité du widget et le cookie du centre d'aide sont distincts : réinitialiser le widget ne déconnecte pas une session du centre d'aide hébergé.
Pour se déconnecter des pages hébergées, rendez-vous sur /help/YOUR_SLUG/auth/logout ; sur votre domaine personnalisé, utilisez /auth/logout. Intégrez cette action au processus de déconnexion de votre application si vous devez mettre fin aux deux sessions. Les identifiants invalides ou expirés ont un accès visiteur. Si la vérification d'identité est désactivée, tous les lecteurs ont un accès visiteur.
Quand les attributs d'un client changent, émettez un nouveau JWT et identifiez-le de nouveau dans le widget ; répétez l'échange de connexion pour les pages hébergées. Les cookies lecteur existants conservent les anciens attributs signés jusqu'à leur expiration. Les changements de règles d'audience s'appliquent dès la requête suivante.
Créer des audiences, prévisualiser les accès et résoudre les restrictionsL'identification par e-mail n'est pas une authentification
L'e-mail fourni par le navigateur enrichit le contexte de support, mais n'authentifie pas le visiteur. Un visiteur peut inspecter sa propre page et y exécuter du JavaScript : l'e-mail, le nom et les attributs personnalisés ne débloquent donc jamais l'historique Sonny d'un autre client. L'identité vérifiée exige le JWT signé par le serveur décrit plus haut. Gardez l'autorisation des actions de votre propre produit dans votre application connectée.
Lorsque la vérification des visiteurs est activée, un badge Vérifiée dans la boîte de réception signifie que la conversation a été rattachée grâce à un JWT signé par le serveur. Un badge Non vérifiée signifie qu'aucune identité signée par le serveur n'a authentifié la conversation. Le nom ou l'e-mail affiché est alors un contexte de support fourni par le visiteur, pas une preuve d'identité.
Exemples de code
L'appel le plus simple — transmettez juste l'e-mail de l'utilisateur :
// Identify a logged-in user
sonny('identify', {
email: 'jane@example.com'
});Transmettez aussi le nom de l'utilisateur, pour que les agents le voient dans la boîte de réception :
// Identify with full name
sonny('identify', {
email: 'jane@example.com',
name: 'Jane Smith'
});Ajoutez un contexte de support utile lors de l'identification, mettez-le à jour plus tard ou surveillez une valeur qui change pendant que la page est ouverte :
// Identify with support context
sonny('identify', {
email: 'jane@example.com',
name: 'Jane Smith',
attributes: {
plan: 'starter',
seats: 5,
trial: true
}
});
// Update only the values that changed
sonny('setAttributes', {
plan: 'growth',
seats: 8,
trial: null // Clears this property
});
// Keep a changing value in sync (checks every 10 seconds)
sonny('watchAttributes', () => ({
monthly_usage: window.currentUsage
}), { interval: 10000 });Exemple complet avec l'extrait asynchrone. Notez que identify peut être appelé avant init — l'identité est mise en file d'attente et envoyée dès que le widget se connecte :
<!-- Sonny widget snippet -->
<script>
(function(w,d,s,o,f,js,fjs){
w['Sonny']=o;w[o]=w[o]||function(){
(w[o].q=w[o].q||[]).push(arguments)};
js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
})(window,document,'script','sonny','https://www.usesonny.com/widget.js');
// Identify before init — identity is queued and sent on connect
sonny('identify', {
email: 'jane@example.com',
name: 'Jane Smith'
});
sonny('init', { siteId: 'YOUR_SITE_ID' });
</script>Appelez reset quand l'utilisateur se déconnecte pour effacer son identité et démarrer une nouvelle session :
// Reset on logout — clears identity and starts a fresh session
sonny('reset');Comment ça marche
- 01
Le widget se charge et se connecte
Le widget se connecte à Sonny et envoie l'identité éventuellement enregistrée au moment de sa connexion.
- 02
L'identité est envoyée au serveur
Sonny cherche un contact avec cet e-mail dans votre espace de travail, et le crée s'il n'existe pas encore.
- 03
Les conversations sont rattachées
Les conversations non rattachées de la session visiteur du navigateur actuel sont rattachées au contact identifié. L'identification ne fusionne pas l'historique entre navigateurs ou appareils.
- 04
La demande d'e-mail est ignorée
Comme le visiteur est déjà identifié, la demande d'e-mail dans le widget est supprimée — aucune interruption pour l'utilisateur.
Règles des attributs personnalisés
- Envoyez au maximum 50 attributs par appel.
- Une valeur peut être une chaîne, un nombre, un booléen ou null. Les chaînes sont limitées à 1000 caractères. Passez null ou une chaîne vide pour effacer une valeur enregistrée.
- Les clés doivent commencer par une lettre et ne contenir que des lettres, des chiffres et des tirets bas, avec 64 caractères maximum.
- Ces clés sont réservées et ignorées :
email, name, id, phone, createdAt, updatedAt.
Référence de l'API
sonny('identify', { email, name?, attributes? })- Identifie le visiteur actuel. Définit l'e-mail et le nom facultatif, supprime la demande d'e-mail et envoie l'identité au serveur. Peut être appelé avant ou après init.
emailstringAdresse e-mail du visiteurnamestring?Nom affiché du visiteurattributesobject?Attributs personnalisés à associer au contact (voir le guide d'installation du widget pour les règles sur les clés et les valeurs)
sonny('identify', { userJwt, name?, attributes? })- Identifie de façon sécurisée le client connecté actuel à partir d'un JWT généré par le serveur. Le jeton reste en mémoire et n'est envoyé que dans les requêtes authentifiées ou les charges utiles du socket.
userJwtstringUn JWT HS256 récent émis par votre backend authentifiénamestring?Nom affiché du visiteurattributesobject?Attributs personnalisés à associer au contact vérifié
sonny('setAttributes', { ... })- Met à jour les attributs personnalisés du visiteur identifié. Seules les valeurs modifiées sont envoyées. Si le visiteur n'est pas encore identifié, les mises à jour attendent et sont envoyées après l'exécution de identify.
attributesobjectPaires clé-valeur à définir. Passez null comme valeur pour effacer un attribut.
sonny('watchAttributes', getter, { interval? })- Appelle votre fonction getter à intervalles réguliers et synchronise automatiquement les attributs modifiés. Pratique quand des valeurs comme le forfait ou l'utilisation changent pendant que la page est ouverte.
getterfunctionUne fonction qui renvoie l'objet des attributs actuelsintervalnumber?Fréquence de vérification, en millisecondes. 10000 par défaut, 2000 minimum.
sonny('reset')- Efface l'identifiant du widget, l'e-mail, le nom et l'historique de conversation local du navigateur actuel, puis démarre une nouvelle session visiteur. Cela ne supprime ni le contact ni ses propriétés enregistrées dans Sonny. À utiliser lors de la déconnexion.
Besoin d'aide ?
Consultez le guide d'installation du widget ou contactez notre équipe.
Documentation associée
- Installation du widget
Installez le widget de chat en direct Sonny sur votre site avec une seule balise script.
- Personnalisation du widget
Adaptez le widget à votre marque : couleurs, logos, messages et comportement.
- Contacts
Découvrez comment les contacts sont créés, gérés, étiquetés et fusionnés dans Sonny.
- Historique de chat
Découvrez comment le widget reconnaît les visiteurs récurrents et recharge les messages précédents.