API czatu na stronie
Połącz własny formularz z widżetem czatu lub zbuduj własny interfejs czatu za pomocą widget SDK, REST, wskaźnika pisania, SSE i aktywności odwiedzającego.
Ostatnio zaktualizowano
Oficjalny widżet instalujesz w aplikacji: zobacz Dodanie czatu na swojej stronie. Opcje fragmentu kodu znajdziesz w Ustawieniach czatu na stronie. Ta strona jest dla deweloperów: widget SDK dla własnego formularza i warstwa REST dla własnego interfejsu czatu. Zobacz OpenAPI, tag inbox.
Widget SDK
Po załadowaniu skryptu widżetu dostępny jest window.TillorInbox. Za jego pomocą przekazujesz dane kontaktowe z własnego formularza (strona kontaktowa, szczegóły ogłoszenia sprzedaży, zapytanie o ofertę). Wszystkie metody czekają, aż konfiguracja widżetu zostanie załadowana.
| Metoda | Opis |
|---|---|
ready() | Promise, który kończy się, gdy widżet jest załadowany |
getVisitor() | Odczytuje zapisane dane kontaktowe z localStorage i wypełnione pola widżetu; synchronicznie, bez sieci |
setVisitor({ name?, firstName?, lastName?, email?, phone?, message?, customFields? }, options?) | Wypełnia pola czatu bez wysyłania |
open() | Otwiera okno czatu |
close() | Zamyka okno czatu |
toggle() | Otwiera lub zamyka okno czatu |
send({ body, name?, firstName?, lastName?, email?, phone?, message?, customFields?, open?, silent?, markSubmitted?, metadata? }) | Wysyła wiadomość z danymi kontaktowymi |
getVisitor() zwraca ten obiekt:
| Pole | Opis |
|---|---|
visitorId | ID tego odwiedzającego w tej przeglądarce (localStorage) |
name | Pełne imię i nazwisko (jedno pole w widżecie) |
firstName / lastName | Wyprowadzone z name (pierwsze słowo / reszta) |
email, phone | Dane kontaktowe |
customFields | Dodatkowe pola z ustawień widżetu |
message | Szkic w polu wiadomości |
detailsSubmitted | Czy formularz odwiedzającego uchodzi za wypełniony |
Użyj getVisitor(), aby wstępnie wypełnić własny formularz z localStorage (ta sama przeglądarka, także po odświeżeniu strony).
Opcje dla setVisitor (drugi argument):
| Opcja | Domyślnie | Wyjaśnienie |
|---|---|---|
open | false | Od razu otwiera okno czatu |
markSubmitted | false | Ukrywa formularz odwiedzającego, gdy wszystkie wymagane pola są wypełnione |
onlyEmpty | false | Nadpisuje tylko puste pola |
persist | false | Zachowuje dane w localStorage (ta sama przeglądarka, także w nowej karcie) |
Opcje dla send:
| Opcja | Domyślnie | Wyjaśnienie |
|---|---|---|
open | false | Otwiera okno czatu przed wysłaniem |
silent | true, gdy open ma wartość false | Bez dźwięku i bez komunikatu o błędzie w widżecie; do sukcesu lub błędu użyj Promise |
markSubmitted | true | Dane kontaktowe nie muszą być potem ponownie podawane w widżecie |
metadata | - | Opcjonalne wskazówki dla Tillie (niewidoczne w oknie czatu); zobacz metadata |
Przy open: false (domyślnie) przycisk czatu pozostaje zamknięty. Wiadomość mimo to trafia do Tillor; Twój własny formularz może podziękować lub pokazać błąd. Przy open: true okno czatu się otwiera, a odwiedzający widzi normalne zachowanie wysyłania (dźwięk, znaczniki, ewentualne błędy widżetu).
Chcesz użyć własnego przycisku zamiast pływającego przycisku czatu? Ustaw data-launcher="false" we fragmencie kodu i wywołaj TillorInbox.open().
metadata (formularz rezerwacji)
Użyj metadata, gdy masz na stronie własny formularz, a Tillie ma wysłać wyłącznie potwierdzenie, bez pytań uzupełniających (na przykład dlatego, że karta się potem zamyka).
| Klucz | Typ | Wyjaśnienie |
|---|---|---|
forceHandover | boolean | Wiadomość z potwierdzeniem i przekazanie koledze, bez pytań wstępnych. Pomija też pauzę AI po wiadomości zespołu (zobacz ignoreAiPause) |
ignoreAiPause | boolean | Tillie odpowiada także wtedy, gdy w trybie Automatyczny jest wstrzymana po wiadomości zespołu (30 minut). Przydatne przy cichym wysyłaniu formularza; połącz z forceHandover albo pozwól Tillie normalnie zbierać informacje |
handoverIntent | "reservation" | "caravan_rental" | "sale" | "other" | Opcjonalnie: przebieg przekazania (domyślnie wyprowadzany automatycznie z wiadomości) |
source | string | Opcjonalna etykieta integracji dla Twojego zespołu (małe litery, cyfry, -, _; maks. 64 znaki) |
await TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: structuredBookingMessage,
silent: true,
metadata: {
forceHandover: true,
handoverIntent: "reservation",
source: "website_booking_form",
},
});Zastąpienie formularza kontaktowego (ciche wysyłanie)
Użyj tego, gdy chcesz zachować istniejący formularz kontaktowy, ale kierować wiadomości przez Tillor bez otwierania okna czatu.
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Verstuur</button>
<p id="contact-status" hidden></p>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", async (event) => {
event.preventDefault();
const form = event.currentTarget;
const status = document.getElementById("contact-status");
const data = new FormData(form);
try {
await TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
});
status.textContent = "Bedankt, we nemen snel contact op.";
status.hidden = false;
form.reset();
} catch (error) {
status.textContent = error instanceof Error ? error.message : "Versturen mislukt.";
status.hidden = false;
}
});
</script>Nie musisz ustawiać open ani silent: bez open: true okno pozostaje zamknięte, a Tillor traktuje wywołanie jako ciche wysłanie.
Połączenie formularza kontaktowego (otwarcie czatu)
Przekaż pola i otwórz okno czatu, aby odwiedzający zobaczył rozmowę:
<form id="site-contact-form">
<input name="name" type="text" required />
<input name="email" type="email" required />
<input name="phone" type="tel" />
<textarea name="message" required></textarea>
<button type="submit">Verstuur</button>
</form>
<script>
document.getElementById("site-contact-form").addEventListener("submit", (event) => {
event.preventDefault();
const form = event.currentTarget;
const data = new FormData(form);
void TillorInbox.send({
name: String(data.get("name") ?? ""),
email: String(data.get("email") ?? ""),
phone: String(data.get("phone") ?? ""),
body: String(data.get("message") ?? ""),
open: true,
});
});
</script>Albo tylko wypełnij pola i otwórz okno, bez natychmiastowego wysyłania:
void TillorInbox.setVisitor(
{
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
message: "Ik heb een vraag over de stacaravan te koop.",
},
{ markSubmitted: true, open: true },
);Strona sprzedaży z natychmiastowym wysłaniem i otwarciem czatu:
void TillorInbox.send({
name: "Jan Janssens",
email: "jan@voorbeeld.be",
phone: "+32 3 779 81 64",
body: "Ik heb interesse in deze stacaravan.",
open: true,
});Synchronizacja na żywo, gdy ktoś pisze:
const form = document.getElementById("site-contact-form");
form.addEventListener("input", () => {
void TillorInbox.setVisitor({
name: form.name.value,
email: form.email.value,
phone: form.phone.value,
message: form.message.value,
});
});Wczesne wywołanie (przed skryptem widżetu)
Jeśli wywołujesz metodę, zanim skrypt się załaduje, dodaj wywołanie do kolejki:
<script>
window.TillorInbox = window.TillorInbox || { q: [] };
window.TillorInbox.q.push([
"setVisitor",
{ name: "Jan", email: "jan@voorbeeld.be" },
{ open: true },
]);
</script>
<script src="https://tillor.eu/inbox-widget.js" data-org-id="org_abc123" data-widget-key="iwk_xxx" async defer></script>Własny interfejs czatu
Jeśli zamiast widżetu budujesz własny interfejs czatu, użyj warstwy REST poniżej.
Uwierzytelnianie: nagłówek X-Tillor-Inbox-Widget-Key (wartość z Ustawienia > Integracje > Czat na stronie).
Wskaźnik pisania
POST /api/orgs/{orgId}/inbox/website/typing
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/json
{
"visitorId": "vis_…",
"active": true,
"visitorName": "Jan",
"visitorEmail": "jan@voorbeeld.nl",
"visitorPhone": "+32470123456"
}active: true, gdy odwiedzający pisze;false, gdy pole jest puste lub odwiedzający przestaje pisać (widżet wysyłafalsepo około 4 sekundach bez wprowadzania)visitorName/visitorEmail/visitorPhonesą opcjonalne- Używaj tego samego
visitorIdco przyPOST …/inbox/website/messagesiGET …/inbox/website/messages
Czas rzeczywisty (SSE)
GET /api/orgs/{orgId}/inbox/website/subscribe?visitorId=vis_…
X-Tillor-Inbox-Widget-Key: iwk_xxx
Accept: text/event-stream| Zdarzenie | Kiedy |
|---|---|
inbox:website:message-created | Nowa wiadomość zespołu lub AI |
inbox:website:message-updated | Wiadomość zespołu lub AI zmieniona albo usunięta |
inbox:website:typing-changed | Zmienia się data.staffTyping lub data.staffOutboundSenderType |
Kształt payloadu jest taki sam jak w SSE organizacji (event, data, timestamp). Połącz się ponownie po przerwaniu; wznawianie nie jest obsługiwane.
Oficjalny widżet używa SSE jako głównej warstwy i pobiera GET …/messages ponownie co 5 sekund jako rozwiązanie awaryjne (co 1 sekundę przy otwartym panelu, gdy SSE na chwilę zniknie). Dzięki temu odpowiedzi są oznaczane jako dostarczone, dopóki odwiedzający jest na stronie.
Aktywność odwiedzającego
POST /api/orgs/{orgId}/inbox/website/events
X-Tillor-Inbox-Widget-Key: iwk_xxx
Content-Type: application/jsonevent: chat_closed, tab_hidden lub navigation (przy nawigacji także url). Twój zespół widzi te zdarzenia jako szary tekst informacyjny w rozmowie, zobacz Rozmowy przez czat na stronie.
Limity
POST …/inbox/website/messages i POST …/inbox/website/attachments/upload odpowiadają 429, gdy odwiedzający lub sieć wysyła za dużo. Treść zawiera data.reason = INBOX_WIDGET_RATE_LIMITED i data.retryAfterSeconds. Limity na organizację:
| Ścieżka | Na odwiedzającego (visitorId) | Na sieć (adres IP) |
|---|---|---|
messages | 10 na minutę, 200 dziennie | 30 na minutę, 600 dziennie |
attachments/upload | 10 na godzinę | 50 na godzinę |
Odczekaj retryAfterSeconds przed ponowną próbą i pokaż odwiedzającemu komunikat zamiast ponawiać automatycznie.