Utviklerdokumentasjon

Legg Henvend til nettstedet

Installer widgeten med én script-tag. Legg til sidekontekst og teamruting ved behov.

Kom i gang

  1. Kopier widgetnøkkelen fra Innstillinger → Widget i Henvend.
  2. Legg inn nettstedets eksakte opprinnelse under Tillatte nettsteder.
  3. Lim inn script-taggen globalt, normalt rett før avsluttende body-tag.
HTML · grunnintegrasjon
<script
  src="https://henvend.no/widget.js"
  data-widget-key="YOUR_WIDGET_KEY"
  async>
</script>
Widgetnøkkelen er offentlig. Den identifiserer integrasjonen, men er ikke et hemmelig passord. Henvend validerer også nettstedets opprinnelse på serveren. Ikke gjenbruk en nøkkel for en annen organisasjon.

Integrasjonsreferanse

Åpne emnet du trenger for ditt nettsted.

Slik lastes widgeten

Loaderen finner nøkkelen i data-widget-key og bruker opprinnelsen til scriptfilen som Henvend-endepunkt.

  1. 1

    Nettleseren laster widget.js fra den konfigurerte Henvend-adressen.

  2. 2

    Henvend validerer widgetnøkkel og eksakt nettstedopprinnelse før konfigurasjonen returneres.

  3. 3

    Organisasjonens tekst, farger, plassering og tilgjengelighetsstatus lastes automatisk.

  4. 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 validerer den eksakte nettstedopprinnelsen på serveren.

Gyldige eksempler
https://example.no
https://www.example.no
http://localhost:3000
Ugyldige eksempler
http://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.

JavaScript · boligeksempel
Henvend.setContext({
  type: "property",
  externalId: "B304",
  title: "Leilighet B304",
  price: "4 790 000 kr",
  url: window.location.href
});
JavaScript · produkteksempel
Henvend.setContext({
  type: "product",
  externalId: "product-123",
  title: "Produktnavn",
  url: window.location.href,
  imageUrl: new URL("/images/product-123.jpg", window.location.origin).href
});
FeltPåkrevdRegel
typeJa1–40 tegn. Starter med liten bokstav; deretter små bokstaver, tall, _ eller -.
externalIdJa1–100 tegn. Stabil ID fra nettstedet eller CMS-et.
titleJa1–160 tegn. Lesbart navn som medarbeideren kjenner igjen.
urlJaHTTP(S)-adresse fra et godkjent nettsted, maks 2048 tegn, uten brukernavn eller passord.
priceNei1–80 tegn når feltet brukes. Presentasjonstekst, ikke et tallkrav.
imageUrlNeiValgfri HTTP(S)-bildeadresse fra et godkjent nettsted, maks 2048 tegn, uten brukernavn eller passord.
yearNeiHeltall 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.

Bruk lenker og bilder fra sidens egen godkjente opprinnelse. Lenker som ikke er godkjent, blir ikke klikkbare, og bildene utelates; henvendelsesteksten kan fortsatt brukes. Widgeten viser dessuten bare kontekstadresser fra nettstedet den åpnes på. Ikke legg et separat bilde-CDN til widgetens tillatte nettsteder bare for å vise et bilde: det vil også tillate innbygging der. Bruk et bilde fra samme opprinnelse, utelat det, eller kontakt Henvend om støtte for bildeverter.

Konteksten lagres når den nye samtalen opprettes. Senere kall endrer ikke konteksten på en aktiv samtale; de bestemmer konteksten for neste nye samtale. Bruk clearContext() når brukeren går til en generell side.

Å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.

HTML og JavaScript · egen knapp
<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.

Kontekst

Beskriver hva kunden spør om.

Ruting

Beskriver hvilken del av organisasjonen som bør motta det.

JavaScript · ruting
Henvend.setRoutingKey("sales");

// Når brukeren forlater denne delen av nettstedet:
Henvend.clearRoutingKey();
  1. 1. En gyldig, aktiv rutingnøkkel satt på siden.
  2. 2. Det aktive standardteamet som er konfigurert for widgetintegrasjonen.
  3. 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.

Teamet løses én gang når samtalen opprettes. Et ugyldig eller deaktivert eksplisitt team faller tilbake til standardteamet og deretter generell flyt. Sidebytter ruter ikke om en eksisterende samtale.

JavaScript-API

Det kanoniske globale grensesnittet er window.Henvend. Metodenavn og tekniske verdier er de samme uansett hvilket språk Henvend-grensesnittet bruker.

MetodeParametereVirkning
Henvend.open()Valgfritt objekt med context og routingKeyÅpner widgeten. Valgene gjelder en ny samtale, ikke en aktiv samtale som allerede finnes.
Henvend.close()IngenLukker panelet til den flytende åpneknappen uten å avslutte samtalen.
Henvend.setContext(context)Et gyldig kontekstobjektSetter sidekontekst som brukes ved opprettelse av neste nye samtale.
Henvend.clearContext()IngenFjerner sidekonteksten for neste nye samtale.
Henvend.setRoutingKey(key)Rutingnøkkel, maks 80 tegnNormaliserer nøkkelen til små bokstaver og bruker den ved neste nye samtale.
Henvend.clearRoutingKey()IngenFjerner eksplisitt sideruting; standardteam eller generell flyt kan fortsatt brukes.
Henvend.destroy()IngenFjerner denne installasjonen og stopper bakgrunnstilkoblingene. Beholder lokal samtalegjenoppretting for et senere besøk.

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.

Kompatibilitet: eldre integrasjoner kan fortsatt finne window.BilChat. Nye integrasjoner skal bruke Henvend; BilChat er kun et utfaset alias.

SPA og klientbaserte sidebytter

For en widget som skal finnes på hele nettstedet, last widget.js én gang i et vedvarende layout. Oppdater kontekst og ruting eksplisitt når gjeldende objekt eller nettsteddel endres.

JavaScript · SPA-livssyklus
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.

For en widget som bare skal vises på én side, kall Henvend.destroy() når siden forlates. close() lukker bare panelet. Loaderen må også håndtere navigasjon før scriptet er ferdig lastet, og laste et nytt script når siden åpnes igjen. Å fjerne script-taggen alene stopper ikke en pågående nedlasting eller widgeten. Ikke bruk destroy() ved vanlige sidebytter hvis widgeten skal finnes på hele nettstedet.

React og Next.js

Dette eksemplet gjelder en widget som beholdes i et vedvarende layout på hele nettstedet, med objektdata som oppdateres ved navigasjon. next/script laster den etter hydrering; onReady kjører når scriptet er klart og ved senere remontering.

TSX · Next.js App Router
"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>;
    };
  }
}

type Listing = { id: string; title: string };

export function HenvendWidget({ listing }: { listing: Listing | null }) {
  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.no/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.
For en widget som bare finnes på én side, bruk en loader med tilhørende oppstart og opprydding, også ved rask navigasjon og React Strict Mode. En bufret next/script onReady-callback oppretter ikke en widget på nytt etter destroy(); eksemplet for hele nettstedet skal ikke brukes til denne livssyklusen.

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.
HTML og JavaScript · malintegrasjon
<!-- 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.no/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

Avtal en testorganisasjon og et testmiljø med Henvend, og test hele flyten med fiktive data. En utviklingsadresse alene skiller ikke dataene: produksjonsscript og produksjonsnøkkel sender fortsatt henvendelser til produksjon.

  1. Legg til den eksakte utviklingsopprinnelsen i den avtalte testorganisasjonen.
  2. Last scriptet fra det avtalte Henvend-testmiljøet med testorganisasjonens offentlige widgetnøkkel.
  3. Bekreft at åpneknappen vises og kan åpnes.
  4. Send en testhenvendelse som kunde.
  5. Bekreft at riktig organisasjon og kvalifiserte medarbeidere mottar den.
  6. Svar fra arbeidsområdet og bekreft at svaret vises i widgeten.
  7. Kontroller kontekstkortet for en kontekstuell side.
  8. Kontroller team/ruting med en gyldig rutingnøkkel.
  9. Test generell flyt etter clearContext() og clearRoutingKey().
  10. Test mobilvisning og tastaturnavigasjon.
  11. 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.

Kontekstbildet eller lenken mangler

Kontroller adressens eksakte opprinnelse, inkludert www og port. Den må være godkjent for organisasjonen, og widgeten viser bare adresser fra nettstedet den åpnes på. Et separat CDN støttes ikke automatisk. Kontroller også nettstedets img-src-policy for bilder.

Bootstrap fra samme opprinnelse gir 403

Når widgeten kjører på Henvend-appens egen opprinnelse, kan nettleseren utelate Origin i GET-kall. Henvend kontrollerer da metadata for samme opprinnelse og Referer. Behold slike referenter, for eksempel med Referrer-Policy: same-origin. En generell no-referrer-policy bryter denne flyten. Vanlige innbygginger på andre nettsteder bruker Origin-headeren.

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 bilder fra nettstedets egen opprinnelse som sendes i imageUrl. Tillatelse i CSP overstyrer ikke Henvends kontroll av godkjente opprinnelser.
Det finnes foreløpig ingen universell, sikker kopier-og-lim CSP-streng i kodebasen fordi Supabase-endepunktene avhenger av Henvend-distribusjonen og bildeverter avhenger av kundenettstedet. Be Henvend om den eksakte allowlisten før en streng produksjonspolicy endres; ikke åpne hele policyen med * som snarvei.