Integrazione dei widget
Integra il widget ChatHub nel tuo sito web per fornire supporto chat in tempo reale ai tuoi clienti.
Panoramica
Il widget ChatHub è un componente JavaScript che:
- Incorpora in qualsiasi sito web
- Fornisce un'interfaccia di chat in tempo reale
- Mette in contatto i clienti con gli operatori
- Richiede il token di autenticazione dell'operatore
- Carica come modulo ES
Avvio rapido
1. Ottieni il token operatore
Per prima cosa, ottieni un token operatore seguendo il flusso di autenticazione:
// 1. Get company token
const companyToken = await getCompanyToken(login, password);
// 2. Get organization
const organizations = await getOrganizations(companyToken);
const orgId = organizations[0].id;
// 3. Get operator
const operators = await getOperators(companyToken, orgId);
const operatorId = operators[0].id;
// 4. Generate operator token
const operatorToken = await getOperatorToken(
companyToken,
operatorId,
expiresAt
);
// 5. Validate token
const isValid = await validateToken(companyToken, operatorToken);
2. Incorpora widget
Aggiungi lo script del widget al tuo HTML:
<!DOCTYPE html>
<html>
<head>
<title>Your Website</title>
</head>
<body>
<!-- Your website content -->
<!-- ChatHub Widget -->
<script type="module" id="operator-chat-panel-script"
src="https://widget.smsbat.com/operator-chat-panel/widget-script.js"
token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."></script>
</body>
</html>
Parametri dello script
| Attributo | Valore | Obbligatorio | Descrizione |
|---|---|---|---|
| "tipo" | modulo |
Sì | Tipo di modulo ES |
id |
script-pannello-chat-operatore |
Sì | Identificatore univoco dello script |
src |
URL del widget | Sì | Posizione dello script del widget |
gettone |
Gettone JWT | Sì | Token di autenticazione dell'operatore |
Metodi di integrazione
HTML statico
Per i siti Web statici, incorporali direttamente in HTML:
CODICE_BLOCCO_2
Iniezione dinamica (JavaScript)
Per le applicazioni a pagina singola, inserire dinamicamente:
function loadChatHubWidget(operatorToken) {
// Check if widget already loaded
const existing = document.getElementById('operator-chat-panel-script');
if (existing) {
existing.remove();
}
// Create script element
const script = document.createElement('script');
script.type = 'module';
script.id = 'operator-chat-panel-script';
script.src = 'https://widget.smsbat.com/operator-chat-panel/widget-script.js';
script.setAttribute('token', operatorToken);
// Append to body
document.body.appendChild(script);
}
// Usage
const token = await getOperatorToken();
loadChatHubWidget(token);
Reagisci
import { useEffect } from 'react';
function ChatHubWidget({ operatorToken }) {
useEffect(() => {
if (!operatorToken) return;
// Load widget
const script = document.createElement('script');
script.type = 'module';
script.id = 'operator-chat-panel-script';
script.src = 'https://widget.smsbat.com/operator-chat-panel/widget-script.js';
script.setAttribute('token', operatorToken);
document.body.appendChild(script);
// Cleanup on unmount
return () => {
const existing = document.getElementById('operator-chat-panel-script');
if (existing) {
existing.remove();
}
};
}, [operatorToken]);
return null;
}
// Usage
function App() {
const [token, setToken] = useState('');
useEffect(() => {
async function init() {
const operatorToken = await fetchOperatorToken();
setToken(operatorToken);
}
init();
}, []);
return (
<div>
<h1>My App</h1>
<ChatHubWidget operatorToken={token} />
</div>
);
}
Vue.js
CODICE_BLOCCO_5
Angolare
CODICE_BLOCCO_6
Gestione dei token
Generazione di token lato server
Non esporre mai le credenziali aziendali nel codice lato client. Genera token sul tuo server:
CODICE_BLOCCO_7
Aggiornamento del token
Implementa l'aggiornamento automatico dei token:
class WidgetTokenManager {
constructor() {
this.token = null;
this.expiresAt = null;
this.refreshInterval = null;
}
async initialize() {
await this.refreshToken();
// Refresh token 1 hour before expiration
this.refreshInterval = setInterval(
() => this.checkAndRefresh(),
60 * 60 * 1000 // Check every hour
);
}
async refreshToken() {
const response = await fetch('/api/chathub/token');
const data = await response.json();
this.token = data.token;
this.expiresAt = new Date(data.expiresAt);
this.reloadWidget();
}
async checkAndRefresh() {
const oneHour = 60 * 60 * 1000;
const timeUntilExpiry = this.expiresAt - Date.now();
if (timeUntilExpiry < oneHour) {
await this.refreshToken();
}
}
reloadWidget() {
// Remove old widget
const existing = document.getElementById('operator-chat-panel-script');
if (existing) {
existing.remove();
}
// Load new widget with fresh token
const script = document.createElement('script');
script.type = 'module';
script.id = 'operator-chat-panel-script';
script.src = 'https://widget.smsbat.com/operator-chat-panel/widget-script.js';
script.setAttribute('token', this.token);
document.body.appendChild(script);
}
destroy() {
if (this.refreshInterval) {
clearInterval(this.refreshInterval);
}
}
}
// Usage
const widgetManager = new WidgetTokenManager();
await widgetManager.initialize();
Organizzazioni multiple
Carica widget diversi per organizzazioni diverse:
function loadWidgetForOrganization(organizationId) {
return new Promise((resolve, reject) => {
// Get operator for this organization
fetch(`/api/chathub/token?org=${organizationId}`)
.then(response => response.json())
.then(data => {
const script = document.createElement('script');
script.type = 'module';
script.id = `operator-chat-panel-script-${organizationId}`;
script.src = 'https://widget.smsbat.com/operator-chat-panel/widget-script.js';
script.setAttribute('token', data.token);
script.onload = () => resolve();
script.onerror = () => reject(new Error('Failed to load widget'));
document.body.appendChild(script);
})
.catch(reject);
});
}
// Usage
await loadWidgetForOrganization('sales');
await loadWidgetForOrganization('support');
Migliori pratiche
Sicurezza
- ✅ Genera token lato server
- ✅ Non esporre mai le credenziali aziendali nel codice cliente
- ✅ Utilizza HTTPS per tutte le richieste API
- ✅ Implementare la scadenza dei token
- ✅ Convalida i token prima dell'uso
- ❌ Non archiviare token in localStorage senza crittografia
- ❌ Non impegnare i token nel controllo della versione
Prestazioni
- ✅ Carica widget in modo asincrono
- ✅ Utilizza i moduli ES (browser moderni)
- ✅ Implementa la memorizzazione nella cache dei token
- ✅ Gestisci gli errori con garbo
- ❌Non bloccare il caricamento della pagina
Esperienza utente
- ✅ Mostra lo stato di caricamento durante l'inizializzazione del widget
- ✅ Gestire gli errori di rete
- ✅ Fornire un metodo di contatto di riserva
- ✅ Prova su diversi browser e dispositivi
Gestione degli errori
async function loadWidgetSafely(operatorToken) {
try {
// Validate token first
const isValid = await validateToken(operatorToken);
if (!isValid) {
console.error('Invalid operator token');
showFallbackContact();
return;
}
// Load widget
await loadWidget(operatorToken);
} catch (error) {
console.error('Failed to load chat widget:', error);
showFallbackContact();
}
}
function showFallbackContact() {
// Show alternative contact method
const fallback = document.createElement('div');
fallback.innerHTML = `
<div class="chat-fallback">
<p>Chat is temporarily unavailable.</p>
<p>Contact us: <a href="mailto:support@example.com">support@example.com</a></p>
</div>
`;
document.body.appendChild(fallback);
}
Risoluzione dei problemi
Widget non caricato
- Verificare che il token dell'operatore sia valido
- Verifica che il token non sia scaduto
- Assicurarsi che l'URL dello script sia corretto
- Controlla la presenza di errori nella console del browser
- Verificare la connettività di rete
Gettone scaduto
// Detect expired token and refresh
window.addEventListener('error', async (event) => {
if (event.message.includes('token expired')) {
console.log('Token expired, refreshing...');
await refreshWidgetToken();
}
});
Istanze multiple di widget
Assicurati che venga caricato solo un widget alla volta:
CODICE_BLOCCO_12
Problemi multiorigine
Assicurati che il tuo dominio sia autorizzato. Contatta l'assistenza se riscontri errori CORS.
Test
Sviluppo locale
// Use test token for development
const isDevelopment = process.env.NODE_ENV === 'development';
const token = isDevelopment
? 'test-token-for-development'
: await getProductionToken();
loadWidget(token);
Test di integrazione
CODICE_BLOCCO_14
Passaggi successivi
- Autenticazione - Gestisci i token
- Operatori - Imposta gli operatori
- Organizzazioni - Configura le organizzazioni