Guida per sviluppatori

API di identificazione dei visitatori

Identifica via codice gli utenti che hanno effettuato l'accesso, così non vedono mai la richiesta dell'email e le loro conversazioni vengono collegate automaticamente a un contatto.

Quando usarla

Se il tuo sito web ha utenti che effettuano l'accesso (app SaaS, dashboard, aree riservate), sai già chi sono. Usa il comando identify per passare la loro email a Sonny, così non devono inserirla di nuovo.

  • Salta del tutto la richiesta dell'email per gli utenti che hanno effettuato l'accesso
  • Collega automaticamente le conversazioni in chat alla scheda del contatto
  • Vedi subito nome ed email del visitatore nella posta in arrivo
  • Continua la cronologia su browser e dispositivi diversi con l'identità verificata

Continuità su tutti i dispositivi

Identità verificata del visitatore

L'identificazione di base tramite email è comoda, ma il browser può dichiarare qualsiasi email. L'identità verificata aggiunge un JWT a breve durata firmato dal tuo server. Sonny può così usare in sicurezza il contatto del cliente come titolare della cronologia delle chat sul sito web, e le stesse conversazioni compaiono su un altro browser o dispositivo.

Disattivata

L'impostazione predefinita. Nulla cambia per gli embed o i visitatori esistenti; la cronologia resta legata all'ID visitatore del browser.

Verifica facoltativa (consigliata)

I JWT validi ottengono la cronologia su più dispositivi. I visitatori senza JWT mantengono l'esperienza attuale, anonima o con identificazione tramite email.

Richiedi una prova per l'identificazione

La chat anonima continua a funzionare, ma le chiamate identify e quelle per gli attributi personalizzati richiedono un JWT firmato valido.

La modalità di verifica non rende facoltativi i campi pre-chat obbligatori. Scopri come ogni modalità soddisfa un'email obbligatoria in dati pre-chat obbligatori.

1. Genera un segreto di firma

Apri Canali → il tuo canale → Chat dal vivo, trova Identità sicura del visitatore, scegli una modalità e genera un segreto. Il testo in chiaro viene mostrato una sola volta. Salvalo nel gestore dei segreti del tuo backend come SONNY_IDENTITY_SECRET. Non inserire mai il segreto di firma nel codice del browser, in uno snippet di embed, in una variabile d'ambiente pubblica o nel tuo repository.

2. Genera un JWT a breve durata sul tuo backend

Firma con HS256. Sonny richiede user_id, email, iat ed exp. user_id deve essere un ID stabile del tuo database, non un indirizzo email. I token possono durare al massimo 24 ore; 15 minuti è un buon valore predefinito. Gli orologi possono differire fino a 60 secondi.

Puoi includere anche un oggetto traits firmato dal server per contesto di assistenza affidabile, come merchantName, subdomain, plan, platform e role. I valori degli attributi devono essere stringhe, numeri finiti, booleani o null. Sonny li salva nell'identità verificata del contatto, limitata al sito web. Gli attributi forniti dal browser restano non verificati e non vengono mai promossi a questi attributi firmati.

Node.js
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);
}
Ruby
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')
end
Python
import 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")
PHP
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. Passa al widget solo il JWT

Restituisci il JWT da un endpoint protetto dalla normale sessione della tua applicazione. Chiama identify prima o dopo init. Il widget conserva il JWT solo in memoria: non viene mai salvato in localStorage, nei cookie o in un URL.

JavaScript
// 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 });
});

Aggiorna, esci e ruota in sicurezza

  • Aggiornamento: aggiorna il JWT prima che scada (circa 10 minuti per un token da 15 minuti), poi chiama sonny('identify', { userJwt }). Ascolta anche sonny:identity-required come soluzione di riserva in caso di scadenza o di cambio della chiave di firma.
  • Logout: chiama sonny('reset'). Elimina il JWT in memoria, cancella la sessione del widget nel browser e avvia un nuovo visitatore anonimo.
  • Cambio di account: chiama sonny('reset') per l'utente A prima di recuperare il JWT dell'utente B e chiamare sonny('identify', { userJwt }). Non portare mai il token di un utente in un'altra sessione con accesso.
  • Rotazione ordinaria: Sonny accetta il segreto precedente per 24 ore, dandoti il tempo di aggiornare ogni istanza del backend. Una seconda rotazione ordinaria è bloccata finché questa sovrapposizione non termina.
  • Sospetta fuga del segreto: scegli Sostituisci subito. Entrambe le vecchie chiavi di firma smettono subito di autenticare le nuove richieste; i widget connessi chiedono alla pagina un nuovo JWT.
  • Disattivare la verifica: Sonny elimina il segreto di firma attuale e quello precedente e disconnette i widget verificati. Genera un nuovo segreto prima di riattivare la verifica.

I conflitti di identità non vengono uniti automaticamente

Se un ID utente stabile e un'email puntano a contatti Sonny diversi, la verifica restituisce un conflitto invece di unire silenziosamente le schede dei clienti. Correggi il token o unisci i contatti in Sonny, poi riprova.

Una chat collegata solo tramite un'email non firmata precedente non viene trattata automaticamente come cronologia verificata. In questo modo un'email fornita dal browser non può sbloccare le conversazioni di un altro cliente.

Accesso al centro assistenza

Collega l'accesso clienti che hai già alle pagine di assistenza ospitate o sul tuo dominio personalizzato. Usa lo stesso segreto di firma del sito web e lo stesso JWT a breve durata del widget. L'identificazione di base tramite email e l'accesso dello staff di Sonny non concedono l'accesso da lettore verificato.

  1. Completa prima la configurazione dell'identità verificata del visitatore qui sopra per questo canale. Attiva Verifica facoltativa o Richiedi una prova per l'identificazione in Canali → il tuo canale → Chat dal vivo.
  2. Implementa nella tua app un endpoint autenticato che restituisca { "userJwt": "SIGNED_TOKEN" }. Genera il token sul tuo server a partire dal cliente che ha effettuato l'accesso e da attributi affidabili; non accettare mai dal browser un piano o un ruolo richiesto.
  3. In Canali → il tuo canale → Centro assistenza → Accesso al centro assistenza, scegli Clienti verificati e un Pubblico di clienti facoltativo. Inserisci la pagina di login della tua app come URL di accesso dei clienti e seleziona Salva accesso.
  4. Dopo il login del cliente, esegui lo scambio qui sotto, sostituendo YOUR_SLUG con l'Indirizzo del centro assistenza. L'URL di login da solo non basta: la tua app deve completare questo scambio.
JavaScript
// 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);

Per un dominio personalizzato, imposta signIn su https://help.example.com/auth e torna a / o /articles/getting-started. I percorsi di ritorno ospitati iniziano con /help/YOUR_SLUG. Le destinazioni di ritorno devono restare sullo stesso host.

Lo scambio imposta un cookie sicuro e HTTP-only e reindirizza per rimuovere il token dall'URL. La sessione del lettore scade insieme al JWT, al massimo dopo 24 ore. Usa token a breve durata ed evita di registrare nei log l'URL di scambio. Il JWT serve solo per questo scambio di accesso, non nei link agli articoli condivisi.

Prova accesso e permessi

  1. Visita un centro privato senza aver effettuato l'accesso. Segui il suo pulsante di accesso, accedi alla tua app e verifica di tornare al centro assistenza sullo stesso dominio ospitato o personalizzato.
  2. Controlla un articolo consentito e uno negato navigando, cercando e tramite URL diretto. Un cliente fuori dal pubblico del centro vede un messaggio di accesso; un articolo negato restituisce “non trovato”.
  3. Usa Esci nel centro assistenza e verifica che i contenuti privati scompaiano. Ripeti con un cliente che ha attributi diversi.

Aggiornamento e uscita

Il widget invia automaticamente il suo JWT attuale. Aggiornalo quando Sonny lo richiede e chiama sonny('reset') quando il cliente esce dall'account. L'identità del widget e il cookie del centro assistenza sono separati: reimpostare il widget non chiude una sessione del centro assistenza ospitato.

Per uscire dalle pagine ospitate, vai a /help/YOUR_SLUG/auth/logout; sul tuo dominio personalizzato, usa /auth/logout. Collega questa azione al flusso di logout della tua app se devi chiudere entrambe le sessioni. Le credenziali non valide o scadute hanno accesso da visitatore. Con la verifica dell'identità disattivata, ogni lettore ha accesso da visitatore.

Quando gli attributi di un cliente cambiano, genera un nuovo JWT ed esegui di nuovo l'identificazione nel widget; ripeti lo scambio di accesso per le pagine ospitate. I cookie di lettura esistenti mantengono i precedenti attributi firmati fino alla scadenza. Le modifiche alle regole dei pubblici si applicano dalla richiesta successiva.

Crea pubblici, visualizza l'anteprima degli accessi e risolvi i problemi delle restrizioni

L'identificazione tramite email non è un'autenticazione

L'email fornita dal browser migliora il contesto per l'assistenza, ma non autentica il visitatore. Un visitatore può ispezionare ed eseguire JavaScript sulla propria pagina, quindi email, nome e attributi personalizzati non sbloccano mai la cronologia Sonny di un altro cliente. L'identità verificata richiede il JWT firmato dal server descritto sopra. Mantieni l'autorizzazione per le azioni nel tuo prodotto all'interno della tua applicazione con accesso.

Quando la verifica dei visitatori è attiva, un badge Verificata nella posta in arrivo indica che la conversazione è stata collegata con un JWT firmato dal server. Un badge Non verificata indica che nessuna identità firmata dal server ha autenticato la conversazione. Il nome o l'email mostrati sono solo contesto fornito dal visitatore, non una prova d'identità.

Esempi di codice

La chiamata più semplice: passa solo l'email dell'utente:

JavaScript
// Identify a logged-in user
sonny('identify', {
  email: 'jane@example.com'
});

Passa anche il nome dell'utente, così gli agenti lo vedono nella posta in arrivo:

JavaScript
// Identify with full name
sonny('identify', {
  email: 'jane@example.com',
  name: 'Jane Smith'
});

Aggiungi contesto utile per l'assistenza durante l'identificazione, aggiornalo in seguito oppure osserva un valore che cambia mentre la pagina è aperta:

JavaScript
// 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 });

Esempio completo con lo snippet asincrono. Nota che identify può essere chiamato prima di init: l'identità viene messa in coda e inviata appena il widget si connette:

HTML
<!-- 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>

Chiama reset quando l'utente esce dall'account per cancellarne l'identità e avviare una nuova sessione:

JavaScript
// Reset on logout — clears identity and starts a fresh session
sonny('reset');

Come funziona

  1. 01

    Il widget si carica e si connette

    Il widget si connette a Sonny e, al collegamento, invia l'eventuale identità salvata.

  2. 02

    L'identità viene inviata al server

    Sonny cerca un contatto con quell'email nel tuo spazio di lavoro e, se non esiste ancora, lo crea.

  3. 03

    Le conversazioni vengono collegate

    Le conversazioni non collegate della sessione visitatore del browser attuale vengono collegate al contatto identificato. L'identificazione non unisce la cronologia tra browser o dispositivi.

  4. 04

    La richiesta dell'email viene saltata

    Poiché il visitatore è già identificato, la richiesta dell'email nel widget viene soppressa: nessuna interruzione per l'utente.

Regole per gli attributi personalizzati

  • Invia al massimo 50 attributi per chiamata.
  • Un valore può essere una stringa, un numero, un booleano o null. Le stringhe sono limitate a 1000 caratteri. Passa null o una stringa vuota per cancellare un valore salvato.
  • Le chiavi devono iniziare con una lettera e contenere solo lettere, numeri e trattini bassi, fino a un massimo di 64 caratteri.
  • Queste chiavi sono riservate e vengono ignorate: email, name, id, phone, createdAt, updatedAt.

Riferimento API

sonny('identify', { email, name?, attributes? })
Identifica il visitatore attuale. Imposta l'email e il nome facoltativo, salta la richiesta dell'email e invia l'identità al server. Può essere chiamato prima o dopo init.
  • emailstringIndirizzo email del visitatore
  • namestring?Nome visualizzato del visitatore
  • attributesobject?Attributi personalizzati da associare al contatto (consulta la guida alla configurazione del widget per le regole su chiavi e valori)
sonny('identify', { userJwt, name?, attributes? })
Identifica in modo sicuro il cliente attuale che ha effettuato l'accesso, a partire da un JWT generato dal server. Il token resta in memoria e viene inviato solo nei payload autenticati delle richieste o del socket.
  • userJwtstringUn JWT HS256 appena generato dal tuo backend autenticato
  • namestring?Nome visualizzato del visitatore
  • attributesobject?Attributi personalizzati da associare al contatto verificato
sonny('setAttributes', { ... })
Aggiorna gli attributi personalizzati del visitatore identificato. Vengono inviati solo i valori modificati. Se il visitatore non è ancora identificato, gli aggiornamenti restano in attesa e vengono inviati dopo l'esecuzione di identify.
  • attributesobjectCoppie chiave-valore da impostare. Passa null come valore per cancellare un attributo.
sonny('watchAttributes', getter, { interval? })
Chiama periodicamente la tua funzione getter e sincronizza automaticamente gli attributi modificati. Utile quando valori come il piano o l'utilizzo cambiano mentre la pagina è aperta.
  • getterfunctionUna funzione che restituisce l'oggetto con gli attributi attuali
  • intervalnumber?Ogni quanto controllare, in millisecondi. Predefinito 10000, minimo 2000.
sonny('reset')
Cancella l'ID del widget, l'email, il nome e la cronologia locale delle conversazioni del browser attuale, poi avvia una nuova sessione visitatore. Non elimina il contatto né le sue proprietà salvate in Sonny. Usalo al logout.

Ti serve aiuto?

Consulta la guida alla configurazione del widget o contatta il nostro team.

Guide correlate