Kom i gang
Den normale integrasjonen trenger tre ting. Du trenger ikke bygge eller style selve samtalegrensesnittet.
Widget-loaderen
Organisasjonens widgetnøkkel
Et registrert nettsted
<script
src="https://henvend.vercel.app/widget.js"
data-widget-key="YOUR_WIDGET_KEY"
async>
</script>- Kopier widgetnøkkelen fra Innstillinger → Widget i Henvend.
- Legg inn nettstedets eksakte opprinnelse under Tillatte nettsteder.
- Lim inn script-taggen globalt, normalt rett før avsluttende body-tag.
Slik lastes widgeten
Loaderen finner nøkkelen i data-widget-key og bruker opprinnelsen til scriptfilen som Henvend-endepunkt.
- 1
Nettleseren laster widget.js fra den konfigurerte Henvend-adressen.
- 2
Henvend validerer widgetnøkkel og eksakt nettstedopprinnelse før konfigurasjonen returneres.
- 3
Organisasjonens tekst, farger, plassering og tilgjengelighetsstatus lastes automatisk.
- 4
Widgeten oppretter en privat, anonym kundesesjon først når en ny henvendelse sendes.
Widgeten rendres i Shadow DOM. Det isolerer Henvends stil fra nettstedets CSS, og nettstedet skal ikke gjenskape eller overstyre widgetgrensesnittet.
Kundens anonyme sesjon og aktive samtalereferanse lagres lokalt i samme nettleser og nettstedopprinnelse. Det gjør at samtalen kan fortsette etter navigasjon eller ny innlasting på samme enhet.
Når widgeten deaktiveres i Henvend, fjernes åpneknappen og nye henvendelser avvises. Historiske samtaledata slettes ikke av denne handlingen.
Tillatte nettsteder
En opprinnelse består av protokoll, vertsnavn og eventuell port. Henvend sammenligner den eksakte Origin-verdien fra nettleseren.
https://example.no
https://www.example.no
http://localhost:3000http://example.no
https://example.no/shop
https://example.no?preview=1- https://example.no og https://www.example.no er forskjellige opprinnelser og må legges inn hver for seg dersom begge brukes.
- Produksjonsnettsteder må bruke HTTPS. HTTP godtas bare for localhost, 127.0.0.1 og lokal IPv6 under utvikling.
- Ikke ta med sti, spørring, fragment eller innloggingsinformasjon. Bruk bare opprinnelsen.
- Legg til hvert faktisk produksjons-, underdomene- og utviklingsopphav som skal laste widgeten.
Kontekst: hva spør kunden om?
Henvend.setContext() knytter det kunden ser på til en ny henvendelse. type er en beskrivende, bransjenøytral verdi – for eksempel property, product, venue, vehicle eller listing.
Henvend.setContext({
type: "property",
externalId: "B304",
title: "Leilighet B304",
price: "4 790 000 kr",
url: window.location.href
});Henvend.setContext({
type: "product",
externalId: "product-123",
title: "Produktnavn",
url: window.location.href,
imageUrl: "https://www.example.no/images/product-123.jpg"
});| Felt | Påkrevd | Regel |
|---|---|---|
| type | Ja | 1–40 tegn. Starter med liten bokstav; deretter små bokstaver, tall, _ eller -. |
| externalId | Ja | 1–100 tegn. Stabil ID fra nettstedet eller CMS-et. |
| title | Ja | 1–160 tegn. Lesbart navn som medarbeideren kjenner igjen. |
| url | Ja | HTTP(S)-adresse, maks 2048 tegn, uten brukernavn eller passord. |
| price | Nei | 1–80 tegn når feltet brukes. Presentasjonstekst, ikke et tallkrav. |
| imageUrl | Nei | HTTP(S)-adresse, maks 2048 tegn, uten brukernavn eller passord. Valgfritt bilde fra nettstedet. |
| year | Nei | Heltall fra 1900 til 2200. Beholdes for kompatible objekttyper. |
Kontekstobjektet kan bare inneholde feltene i tabellen. Ukjente felt, manglende påkrevde verdier eller ugyldige grenser gjør konteksten ugyldig.
Åpne Henvend fra egne knapper
Den flytende åpneknappen er ikke den eneste inngangen. En side kan åpne widgeten fra en kontekstuell knapp og sende konteksten i samme kall.
<button type="button" id="ask-about-item">
Spør om dette objektet
</button>
<script>
document.getElementById("ask-about-item").addEventListener("click", () => {
const openHenvend = () => Henvend.open({
context: {
type: "listing",
externalId: "B304",
title: "Eksempelobjekt B304",
url: window.location.href
}
});
if (window.Henvend) openHenvend();
else window.addEventListener("henvend:ready", openHenvend, { once: true });
});
</script>Henvend.open() kan kalles uten argumenter, eller med et objekt som inneholder context og/eller routingKey. Alternativt kan du kalle setContext() og setRoutingKey() før open().
Ruting: hvem bør motta henvendelsen?
Ruting er valgfritt og uavhengig av kontekst. Bruk en offentlig rutingnøkkel som er opprettet i organisasjonens rutinginnstillinger.
Beskriver hva kunden spør om.
Beskriver hvilken del av organisasjonen som bør motta det.
Henvend.setRoutingKey("sales");
// Når brukeren forlater denne delen av nettstedet:
Henvend.clearRoutingKey();- 1. En gyldig, aktiv rutingnøkkel satt på siden.
- 2. Det aktive standardteamet som er konfigurert for widgetintegrasjonen.
- 3. Generell / ikke rutet organisasjonsflyt dersom ingen av de to første gir et team.
En rutingnøkkel kan være opptil 80 tegn og bruker små bokstaver, tall og enkle bindestreker, for eksempel sales eller project-harbour.
Rutingnøkler er offentlige identifikatorer, ikke hemmeligheter. De løses bare innen organisasjonen som allerede er validert av widgetnøkkel og opprinnelse. Nettleseren kan ikke velge organisasjon, team eller medarbeider med en UUID.
JavaScript-API
Det kanoniske globale grensesnittet er window.Henvend. Metodenavn og tekniske verdier er de samme uansett hvilket språk Henvend-grensesnittet bruker.
| Metode | Parametere | Virkning |
|---|---|---|
| Henvend.open() | Valgfritt objekt med context og routingKey | Åpner widgeten. Valgene gjelder en ny samtale, ikke en aktiv samtale som allerede finnes. |
| Henvend.close() | Ingen | Lukker panelet til den flytende åpneknappen uten å avslutte samtalen. |
| Henvend.setContext(context) | Et gyldig kontekstobjekt | Setter sidekontekst som brukes ved opprettelse av neste nye samtale. |
| Henvend.clearContext() | Ingen | Fjerner sidekonteksten for neste nye samtale. |
| Henvend.setRoutingKey(key) | Rutingnøkkel, maks 80 tegn | Normaliserer nøkkelen til små bokstaver og bruker den ved neste nye samtale. |
| Henvend.clearRoutingKey() | Ingen | Fjerner eksplisitt sideruting; standardteam eller generell flyt kan fortsatt brukes. |
Så snart widget.js er kjørt, oppretter loaderen et synkront Henvend-grensesnitt. Kall køes mens widgetkonfigurasjonen lastes. Kode som kan kjøre før selve scriptfilen er lastet, bør vente på scriptets load/onReady eller henvend:ready.
Når widgeten er initialisert, sender nettleseren hendelsen henvend:ready på window.
SPA og klientbaserte sidebytter
En SPA laster normalt widget.js bare én gang. Oppdater derfor kontekst og ruting eksplisitt når gjeldende objekt eller nettsteddel endres.
function showListing(listing) {
Henvend.setContext({
type: "listing",
externalId: listing.id,
title: listing.title,
price: listing.price,
url: window.location.href
});
Henvend.setRoutingKey("sales");
}
function leaveListing() {
Henvend.clearContext();
Henvend.clearRoutingKey();
}Kall clearContext() og clearRoutingKey() når brukeren forlater en kontekstuell/rutet del. Dette hindrer at en senere ny samtale arver opplysninger fra forrige skjerm. En allerede opprettet samtale forblir uendret.
React og Next.js
next/script kan laste widgeten etter hydrering. onReady kjører i en klientkomponent når scriptet er klart og ved senere remontering.
"use client";
import Script from "next/script";
import { useEffect, useState } from "react";
declare global {
interface Window {
Henvend?: {
setContext: (context: unknown) => Promise<void>;
clearContext: () => Promise<void>;
};
}
}
export function HenvendWidget({ listing }) {
const [ready, setReady] = useState(false);
useEffect(() => {
if (!ready) return;
if (listing) {
void window.Henvend?.setContext({
type: "listing",
externalId: listing.id,
title: listing.title,
url: window.location.href
});
} else {
void window.Henvend?.clearContext();
}
return () => {
void window.Henvend?.clearContext();
};
}, [listing, ready]);
return (
<Script
src="https://henvend.vercel.app/widget.js"
data-widget-key="YOUR_WIDGET_KEY"
strategy="afterInteractive"
onReady={() => setReady(true)}
/>
);
}- onReady og tilgang til window krever en Client Component.
- Kall API-et i onReady eller i en effekt som først kjører etter at scriptet er klart.
- Oppdater eller nullstill kontekst når route- eller produktdata endres. Ikke forvent at scriptet lastes på nytt ved klientnavigasjon.
WordPress og andre CMS-er
Legg loaderen inn globalt via tema/mal, en sikker kodeplassering i nettstedbyggeren eller nettstedets egen scriptfunksjon. Henvend krever ikke en bestemt tredjepartsplugin.
- Last widgetscriptet én gang globalt.
- La objekt- eller produktmalen skrive ut setContext() med data for den aktuelle siden.
- Kode CMS-verdier korrekt som JavaScript/JSON. Ikke sett sammen ubeskyttet brukergenerert tekst i en script-tag.
- Registrer henvend:ready-lytteren før den asynkrone loaderen for å unngå en lastingskonkurranse.
<!-- Skriv ut dette fra objektmalen med sikkert kodede CMS-verdier. -->
<script>
window.addEventListener("henvend:ready", function () {
Henvend.setContext({
type: "listing",
externalId: "LISTING_ID",
title: "LISTING_TITLE",
url: window.location.href
});
}, { once: true });
</script>
<script
src="https://henvend.vercel.app/widget.js"
data-widget-key="YOUR_WIDGET_KEY"
async>
</script>Utseende, tekst og tilgjengelighet
Widgeten henter organisasjonens lagrede oppsett automatisk. Nettstedutvikleren skal normalt ikke endre grensesnittet.
- Åpneknapp, overskrifter, samtaletekst og kontaktoppfordringer styres fra Innstillinger → Widget.
- Farger, plassering og avrunding styres fra samme sted og forhåndsvises før lagring.
- Åpningstider, tidssone og tilgjengelighetstekst beregnes av Henvend fra organisasjonens innstillinger.
- Ikke bruk CSS-overstyringer. Shadow DOM isolerer widgeten, og strukturerte Henvend-innstillinger er den støttede tilpasningen.
Test integrasjonen
Test hele flyten på en separat utviklingsopprinnelse før produksjonslansering.
- Legg til den eksakte utviklingsopprinnelsen i Henvend.
- Last widgetscriptet med riktig offentlig nøkkel.
- Bekreft at åpneknappen vises og kan åpnes.
- Send en testhenvendelse som kunde.
- Bekreft at riktig organisasjon og kvalifiserte medarbeidere mottar den.
- Svar fra arbeidsområdet og bekreft at svaret vises i widgeten.
- Kontroller kontekstkortet for en kontekstuell side.
- Kontroller team/ruting med en gyldig rutingnøkkel.
- Test generell flyt etter clearContext() og clearRoutingKey().
- Test mobilvisning og tastaturnavigasjon.
- Last siden på nytt i samme nettleser og bekreft at den private kundesamtalen fortsetter.
Feilsøking
Widgeten vises ikke
Kontroller scriptadressen, data-widget-key, at widgeten er aktivert, og at nettleserens eksakte opprinnelse er registrert. Kontroller deretter at widget.js og bootstrap-kallet faktisk lastes i Network-panelet.
Konteksten mangler
Kontroller at setContext() kjøres før den nye henvendelsen opprettes, at alle påkrevde felt er med, at URL-ene bruker HTTP(S), og at SPA-en nullstiller/oppdaterer data ved sidebytter.
Feil team mottar henvendelsen
Kontroller rutingnøkkelen, at teamet er aktivt, og hvilket standardteam integrasjonen bruker. En ugyldig/deaktivert nøkkel faller videre til standardteam og deretter generell flyt.
Bruk nettleserens Console- og Network-panel til å se om loaderen eller forespørsler feiler, men ikke del kundetokens, Authorization-headere eller private samtaledata i supportsaker.
Content Security Policy (CSP)
Nettsteder med streng CSP må tillate de ressursene widgeten faktisk bruker.
- script-src må tillate den konfigurerte Henvend-opprinnelsen som leverer widget.js.
- connect-src må tillate Henvend-opprinnelsen og Henvends distribusjonsspesifikke Supabase HTTPS- og WSS-endepunkter for anonym sesjon, data og sanntidssvar.
- img-src må tillate vertene som nettstedet selv sender i imageUrl dersom kontekstbilder brukes.