Docs/Feature
// feature
Customer support
Il support è cablato con due strade, e il repo sceglie da solo quale usare: chat Crisp se hai messo un website ID in config, altrimenti apre il client email dell'utente sul tuo indirizzo di supporto. Un solo componente, ButtonSupport, copre entrambi i casi.
Com'è messo adesso
crisp-sdk-web è già tra le dipendenze del package.json, ma in config.ts il campo crisp.id è una stringa vuota. Tradotto: la chat è spenta e in questo momento il support gira sul fallback email, che punta a resend.supportEmail.
crisp: {
// Vuoto = chat disattivata. Incolla qui il Website ID per accenderla.
id: "",
// Il widget resta visibile SOLO su queste route
onlyShowOnRoutes: ["/"],
},
resend: {
// Usato dal fallback mailto quando crisp.id è vuoto
supportEmail: "tuaemail@example.com",
},ButtonSupport
Il componente è in components/ButtonSupport.tsx. Al click controlla il config nell'ordine: prima Crisp, poi email.
const handleClick = () => {
if (config.crisp?.id) {
Crisp.chat.show();
Crisp.chat.open();
} else if (config.resend?.supportEmail) {
window.open(
`mailto:${config.resend.supportEmail}?subject=Serve aiuto con ${config.appName}`,
"_blank"
);
}
};Se svuoti entrambi i campi il bottone diventa decorativo: click, e non succede niente. Tienine sempre almeno uno pieno.
Nel repo il bottone è già usato in due posti: app/error.tsx e app/not-found.tsx. Cioè esattamente dove l'utente è bloccato e ha bisogno di parlarti. Aggiungilo dove vuoi con un import:
import ButtonSupport from "@/components/ButtonSupport";
<ButtonSupport />Accendere Crisp
- Crea un account su crisp.chat e un website.
- Settings → Website Settings → Setup instructions: copia il Website ID (un UUID).
- Incollalo in
config.tssottocrisp.id. Fine — non c'è nessuno script da mettere inlayout.tsx, ci pensa il boot del client layout.
Il website ID non è un segreto (finisce comunque nel bundle browser), quindi sta bene in config e non in .env.
Il boot in LayoutClient
components/LayoutClient.tsx contiene un componente CrispChat che non renderizza niente e fa tre cose: avvia Crisp, applica la regola di visibilità, e identifica l'utente loggato.
useEffect(() => {
if (config?.crisp?.id) {
Crisp.configure(config.crisp.id);
if (
config.crisp.onlyShowOnRoutes &&
!config.crisp.onlyShowOnRoutes?.includes(pathname)
) {
Crisp.chat.hide();
Crisp.chat.onChatClosed(() => {
Crisp.chat.hide();
});
}
}
}, [pathname]);Tutto è avvolto in if (config?.crisp?.id): con l'id vuoto lo script Crisp non parte proprio, zero JavaScript di terze parti caricato. È il motivo per cui puoi lasciare la dipendenza installata senza pagare nulla in performance.
Come funziona onlyShowOnRoutes
È un array di path dove la bolla di chat resta visibile. Su ogni altra route il codice chiama Crisp.chat.hide(), e con onChatClosed la rinasconde appena l'utente chiude la finestra. Il default [“/”] significa: bolla solo in home, sparita ovunque altro.
onlyShowOnRoutes: [“/”]— bolla solo sulla landing. Nelle altre pagine il support si apre con<ButtonSupport />, che chiamaCrisp.chat.show()eopen().onlyShowOnRoutes: [“/”, “/pricing”]— bolla anche sulla pagina prezzi, dove le domande pre-acquisto valgono soldi veri.- Togli del tutto la chiave
onlyShowOnRoutesdal config e la bolla resta visibile su tutte le route.
Il confronto è una includes() esatta sul pathname: /blog nell'array non copre /blog/mio-post. Se ti serve il match per prefisso, sostituisci l'includes con uno some((r) => pathname.startsWith(r)).
Riconoscere chi ti scrive
Un terzo effect legge l'utente Supabase e passa il suo id a Crisp, così nella tua inbox vedi chi ha aperto la conversazione invece di un visitatore anonimo:
useEffect(() => {
if (data?.user && config?.crisp?.id) {
Crisp.session.setData({ userId: data.user?.id });
}
}, [data]);Puoi aggiungere altri campi allo stesso oggetto (piano acquistato, data di iscrizione) e ritrovarteli nel pannello Crisp accanto alla chat.
Se preferisci solo email
Lascia crisp.id vuoto e metti un indirizzo vero in resend.supportEmail. Il mailto: apre il client dell'utente con oggetto già compilato — meno immediato di una chat, ma zero costi e zero script di terze parti. Puoi anche rimuovere crisp-sdk-web dalle dipendenze e cancellare il componente CrispChat da LayoutClient.