Opsætning af Webhook Integration

Hvad er et webhook?

Et webhook går i alt sin enkelthed ud på, at hver gang der sker en hændelse (når et call tracking opkald afsluttes i dette tilfælde), så sender vi en forespørgsel til en web-adresse som du konfigurerer. Denne forespørgsel indeholder de væsentligste data vedrørende opkaldet, som du kan gemme eller behandle efter behov. Med vores webhook integration, kan opkaldsdata således synkroniseres mellem vores og dit system. Måske ønsker du at gemme opkaldsdata i din egen database for at sammenkæde data på kryds og tværs. Eller måske ønsker du at tilføje opkald som leads eller kunde i dit CRM-system. Mulighederne er mange. Et webhook gør det væsentligt nemmere at modtage data automatisk end fx en API adgang, da det kræver væsentligt færre udviklingstimer at få opsat. Derudover har et webhook også den fordel, at du modtager data i tæt på realtid.

Vil du vide hvordan Webhook-integrationen opsættes i Trailhub, så se denne guide.

Tekniske detaljer

Umiddelbart efter et opkald er blevet afsluttet, sendes en POST request til den konfigurererede adresse. Request body består af et JSON objekt bestående af nedenstående felter.

Felt Type Beskrivelse
event string Hvilken hændelse der forårsagede forespørgslen. I øjeblikket er værdien altid call.ended. Vi anbefaler dog at dette felt tjekkes for at håndtere andre event typer der måtte blive tilføjet i fremtiden.
uuid UUID (v4) Det unikke ID for opkaldet.
status string

Værdier:

  • ANSWERED
  • UNANSWERED
  • ERROR
Status for opkaldet. ERROR betyder, at der skete en tele-teknisk eller uspecificeret fejl. Såfremt værdien er ANSWERED, blev opkaldet besvaret, hvorimod dette ikke er tilfældet hvis værdien er UNANSWERED.
campaign object Et objekt som indeholder detaljer om den kampagne, som opkaldet tilhører.
campaign.uuid UUID (v4) Det unikke ID for opkaldets kampagne.
campaign.name string Navnet på den tilhørende kampagne.
campaign.type string

Værdier:

  • DYNAMIC
  • STATIC
Typen af kampagne.
started_at ISO 8601 Hvornår opkaldet startede.
connected_at ISO 8601 | NULL Hvornår opkaldet blev besvaret. NULL hvis opkaldet ikke blev besvaret, eller hvis status er ERROR.
ended_at ISO 8601 | NULL Hvornår opkaldet blev afsluttet. NULL hvis status er ERROR.
duration integer | NULL Varigheden af opkaldet i sekunder. NULL hvis opkaldet ikke blev besvaret, eller hvis status er ERROR.
caller_id E.164 | NULL Telefon nummeret der blev ringet fra. Hvis der bliver ringet fra et anonymt nummer, er værdien NULL.
ct_phone_number E.164 Telefon nummeret der blev ringet til (call tracking nummeret).
acquisition * object Information om hvordan Trailhub har attribueret opkaldet.
acquisition.source string Opkaldets kilde, fx google eller linkedin.
acquisition.medium string | NULL Opkaldets trafikkanal, fx cpc eller organic.
params * object Et objekt som indeholder en række standard parametre tilknyttet Trailhub sessionen.

Bemærk at de enkelte parametre udelades hvis der ingen værdi er, så tjek altid om et parameter er tilgængeligt før det bruges.

params.gclid string Google Click ID.
params.wbraid string Værdien af wbraid query parametret.
params.fbclid string Facebook Click ID.
params.msclkid string Microsoft Click ID.
params.li_fat_id string LinkedIn Click ID.
params.utm_campaign string Værdien af utm_campaign query parametret.
params.utm_source string Værdien af utm_source query parametret.
params.utm_medium string Værdien af utm_medium query parametret.
params.utm_content string Værdien af utm_content query parametret.
params.utm_term string Værdien af utm_term query parametret.
params.ga_cid string Google Analytics Client ID (CID). Tilføjes kun hvis Google Analytics integrationen er slået til.
params.ga_sid string Google Analytics Session ID (SID). Tilføjes kun hvis Google Analytics 4 integrationen er slået til.
params._gcl_aw string Værdien af _gcl_aw cookie.
params._fbc string Værdien af _fbc cookie.
params._fbp string Værdien af _fbp cookie.
consent * object Detaljer om hvilke cookies den besøgende gav consent for. Tilføjes kun hvis den besøgende har afgivet consent og vi lykkedes med at læse denne.

I øjeblikket understøttes Cookiebot, CookieInformation og CookieYes.

consent.platform string Hvilken Consent Management Platform (CMP) der er implementeret.

Værdier: cookiebot, cookieinformation eller cookieyes

consent.necessary boolean Hvorvidt den besøgende har tilladt nødvendige cookies.
consent.functional boolean Hvorvidt den besøgende har tilladt funktionelle cookies.
consent.statistics boolean Hvorvidt den besøgende har tilladt statistik cookies.
consent.marketing boolean Hvorvidt den besøgende har tilladt marketing cookies.
page_url * string | NULL Den fulde sti på siden der blev ringet fra.
page_title * string | NULL Titlen på siden der blev ringet fra.

* Tilføjes kun for opkald på dynamiske kampagner.

Forespørgslen bliver sendt med en User-Agent header som er sat til trailhub/<version>, fx trailhub/1.0.

Adressen vi sender forespørgsler til, skal kryptere trafik med TLS (ofte kendt som SSL eller HTTPS). Dette er af hensyn til sikkerhed, da vi vil beskytte dine såvel som vores data bedst muligt. Vi understøtter derfor heller ikke self-signed certifikater.

For at en forespørgsel kategoriseres som succesfuldt, skal adressen besvare vores forespørgsel med en HTTP status der er imellem 200 og 300 (2xx), førstnævnte inklusiv. Såfremt dette ikke er tilfældet, forsøger vi at sende forespørgslen igen, indtil den accepteres eller alle forsøg er opbrugte. Læs mere i afsnittet om timeouts og retries. Dette betyder også, at vi ikke understøtter redirects for webhooks.

Bemærk at adressen skal være offentligt tilgængelig (dog meget gerne beskyttet ved hjælp af autentificering). Dette skyldes, at vores servere kører i skyen, så vi har ikke mulighed for at dele en liste af IP adresser som kan whitelistes.

Headers

Det er muligt at konfigurere op til fem HTTP headers som som vi sender med hver forespørgsel. Dette bruges typisk i forbindelse med autentificering, men kan være nyttigt såfremt det ønskes at sende ekstra værdier med forespørgsler. Et alternativ til dette kan også være URL parametre. Vi anbefaler at ikke-standard headers prefixes med X-, fx X-My-Header. Vi anbefaler så vidt muligt at der ikke benyttes standard HTTP headers (med undtagelse af de, som er relaterede til autentificering), da disse kan blive overskrevne af vores HTTP klient.

Autentificering

Af hensyn til sikkerhed, anbefaler vi at den konfigurerede adresse kræver autentificering, således at den ikke er offentligt tilgængelig. Dette kan gøres på forskellige måder. Nedenfor kan du se, hvordan autentificering kan konfigureres for webhook integrationen, afhængig af hvordan autentificeringen er opsat på din webhook adresse.

Alt data som indtastes i forbindelse med opsætningen, bliver gemt krypteret på vores servere, så eventuelt følsomme data opbevares sikkert.

Query Parameter & Custom Header

Dette er de nemmeste måder at sikre webhook adressen på. Indsæt ganske enkelt et query parameter i adressen vi skal sende forespørgsler til, fx https://api.example.com/webhook?token=abc123. Navnet på parametret er valgfrit. Når vi sender en forespørgsel til adressen, skal værdien for parametret (token i dette tilfælde) valideres til at matche den indtastede værdi (abc123 i dette eksempel). Eftersom vi kun tillader krypteret trafik fra vores servere, bliver parametret samt stien på adressen krypteret med TLS, og kan derfor ikke opsnappes af uvedkommende mellem vores og jeres server. Vi krypterer ydermere hele den konfigurerede adresse på vores servere. Alternativt kan værdien også sendes med som en custom HTTP header, fx navngivet X-API-Token.

Som nævnt er dette de nemmeste måder at autentificere forespørgsler på, men vi anbefaler at benytte en af nedenstående standard løsninger.

HTTP Basic Authentication

»HTTP basic access authentication« er en standard måde at autentificere på over HTTP, da den er indbygget direkte i HTTP specifikationen, og understøttes således af alle browsere, HTTP klienter, osv. Opsætningen består af at tilføje en Authorization HTTP header med værdien Basic <credentials>. <credentials> skal her være username:password som en base64 encoded tekst, fx Basic dXNlcm5hbWU6cGFzc3dvcmQ=. Som en hjælp, kan du under opsætningen undlade at base64 encode værdien; når opsætningen gemmes, sørger vi for at encode værdien korrekt.

Bearer Token

Ved at tilføje en Authorization HTTP header med værdien Bearer <credentials>, kan man sende en token med hver forespørgsel, som så valideres på modtagers server. <credentials> er i dette tilfælde den token som sendes med, mens Bearer indikerer typen af autentificering. En såkaldt »bearer token« bruges ofte i OAuth 2.0 API’er, eller i forbindelse med JSON Web Tokens (JWT).

Shared Secret (HMAC)

En »shared secret« er en hemmelig værdi som er delt imellem parter – helst kun to. Tilføjes en shared secret til opsætningen, benytter vi denne til at beregne en hash værdi for det JSON objekt som sendes i request body. Til at beregne denne hash værdi, benytter vi den indtastede shared secret. Resultatet er en såkaldt HMAC. Vi benytter SHA-256 hashing algoritmen til dette, og værdien tilføjes til en X-Signature header som sendes med hver forespørgsel. Det er vigtigt at understrege, at dette ikke betyder, at vi krypterer eller hasher selve det data vi sender; hash værdien har ikke til formål at skjule data for uvedkommende. Den tillader i stedet modtageren at validere både afsenderen af data, samt integriteten af det sendte data. Når en forespørgsel modtages, beregner modtageren en hash værdi ud fra det sendte data og den samme shared secret. Det er vigtigt at der benyttes den samme hashing algoritme til formålet. Hvis den beregnede hash værdi matcher den som vi har tilsendt i X-Signature headeren, så kan du stole på, at det modtagne data kommer fra os, samt at data ikke er blevet modificeret på vejen.

Da denne form for autentificering afhænger af den konfigurerede shared secret, er det ekstremt vigtigt at denne beskyttes og holdes hemmelig. Hvis andre får adgang til denne nøgle, kan de fabrikere en forespørgsel der ser ud som om den kommer fra os. Løsningen er derfor kun ligeså god som i det omfang nøglen holdes hemmelig mellem parterne (jeres og vores system). Derfor gør vi ekstra meget ud af at opbevare jeres nøgle sikkert, og vi krypterer den således med vores egen nøgle før vi lagrer den.

Timeouts & Retries

Når vi sender en forespørgsel, venter vi i op til fem sekunder på et svar. Modtager vi ikke et svar indenfor fem sekunder, betegner vi forespørgslen som fejlet. Det samme gør sig gældende hvis et eventuelt svar ikke har en 2xx status kode. For at minimere risikoen for at opkald mistes såfremt den konfigurerede adresse er utilgængelig, forsøger vi at gensende fejlede forespørgsler op til ni gange. Det vil sige, at vi i alt prøver at sende et opkald ti gange. Er adressen stadig utilgængelig efter ti forsøg, opgiver vi at sende opkaldet. Det er derfor vigtigt at minimere eventuel nedetid på den konfigurerede adresse, da det kan have indflydelse på vores evne til at levere opkald. Udfald kan dog forekomme, eksempelvist på grund af ustabile netværksforbindelser. Derfor venter vi 15 minutter mellem hvert forsøg, således at kortvarig nedetid ikke resulterer i mistede opkald.

Det kan sjældent forekomme, at vi leverer et opkald mere end én gang. Dette kan ske, hvis modtager ikke besvarer en forespørgsel indenfor fem sekunder, men faktisk behandler forespørgslen korrekt – ved eksempelvist at gemme opkaldet i en database. Fordi vores forespørgslen får timeout, betragter vi denne som fejlet, og prøver igen senere. Dette vil således kun ske hvis systemet på modtager adressen er ustabilt og svarer ekstremt langsomt (fem sekunder er lang tid). Selvom dette meget sjældent bør forekomme (forudsat at modtager systemet opererer stabilt), anbefaler vi for en sikkerheds skyld at tjekke, om et givent opkald allerede er blevet modtaget. Dette kan gøres ved hjælp af uuid feltet.