Dokumentacja Webchatix

Czat na żywo w duchu Telegram-first: odwiedzający pisze w widżecie na stronie, zespół odpowiada z Telegrama i panelu webowego. Po lewej sekcje, po prawej szczegóły.

W 5 minut

  1. Otwórz bota → /start — powstaje konto na planie Free i pierwsza strona.
  2. Skopiuj snippet HTML i wklej go na stronie przed </body>.
  3. /panel — jednorazowy link do panelu webowego (albo pozycja „Panel webowy” w menu).
  4. Zaproś operatora: /invite lub menu → „Zespół” → ➕.
  5. Podłącz grupę Telegram: dodaj bota do grupy (albo wpisz w niej /addgroup) i przypisz ją do strony w «Trasach».
  6. Wariant zapasowy — cała strona do jednej grupy: /bindsite site_key w grupie.

Plany i płatności

Rejestracja jest otwarta: /start w bocie tworzy konto w planie Free. Plany płatne kupuje się kartą w panelu, sekcja Faktury — płatność obsługuje Stripe.

PlanStronyKlienci / mies.OperatorzyZa miesiąc
free1301$0
basic2010005$10 ($8 przy płatności rocznej)
unlimited∞∞∞$20 ($16 przy płatności rocznej)

Ceny podajemy za miesiąc. Płatność za rok jest tańsza o 20% i pobierana jednorazowo ($96 i $192 rocznie); w panelu rok jest wybrany domyślnie.

Premium (od Basic): szablony, active invite, visibility rules, notatki, oceny.

Klient to unikalny odwiedzający, który rozpoczął rozmowę w bieżącym miesiącu kalendarzowym; licznik zeruje się 1. dnia.

Jak działa płatność

  • Panel → Faktury: bieżący plan, zużycie limitów, zmiana planu, lista płatności z linkami do PDF.
  • Dane karty nie trafiają na nasze serwery — strona płatności i portal należą do Stripe.
  • Zmianę planu w trakcie okresu Stripe rozlicza proporcjonalnie; anulowanie zostawia plan płatny do końca opłaconego okresu, potem konto wraca na Free.
  • Na adres e-mail z tej samej sekcji przychodzą potwierdzenie płatności, informacja o nieudanym obciążeniu i przypomnienie o odnowieniu.

Menu bota

Główne menu po /start / /menu. Przyciski zwykle po dwa w rzędzie.

PozycjaCo robi
🌐 StronyLista stron konta: ustawienia, Online/Offline, snippet, usuwanie.
👥 ZespółOperatorzy / uczestnicy konta.
➕ ZaprośKod i deep-link dla nowego operatora.
💬 GrupyGrupy Telegram przyjmujące zgłoszenia: podłącz, przypisz do strony, odłącz.
🔗 Panel webowyMagic-link logowania (jednorazowy, ~10 min).
🗺 TrasyKto przyjmuje rozmowy z której strony/podstrony.
🔑 Klucz APIKlucz API statystyk konta, podsumowanie dzisiejszego dnia dla wszystkich stron, wymiana klucza (owner/admin).
⚙️ PanelSzybki dostęp: ops / sites / routes.
📝 SzablonySzybkie odpowiedzi (od Basic).
💳 Plany i płatnościCeny, płatność kartą, faktury (owner).
👑 WłaścicielPrzekaż własność innemu uczestnikowi.
🗑 Usuń kontoKaskadowe usunięcie po potwierdzeniu nazwą.

Karta strony

  • Online / Offline — pauza widżetu (czat offline).
  • Ustawienia — pola brandingu, invite, GDPR itd. (po 2 przyciski w rzędzie).
  • Operator — ustaw trasowanie na osobę lub grupę.
  • Usuń — z potwierdzeniem nazwą strony.

Komendy bota

KomendaKtoZnaczenie
/start [CODE]wszyscyOnboarding / realizacja zaproszenia.
/menumemberGłówne menu konta.
/helpwszyscySpis komend dla Twojej roli.
/panelmemberMagic-link do panelu webowego.
/newsite [nazwa | origin]admin+Utwórz stronę (+ CORS origins).
/addgroupadmin+ w grupiePodłącz grupę jako operatora-grupę (bez chat_id).
/bindsite KEYadmin+ w grupiePodłącz grupę jako czat zapasowy.
/inviteadmin+Zaproszenie operatora.
/op_me CODEkażdyPrzyjmij zaproszenie.
/tplmemberLista / add / del / wysyłka reply + /tpl id.
/notememberNotatka do rozmowy (od Basic).
/releasememberZwolnij rozmowę (+ prośba o ocenę).
/langwszyscyJęzyk interfejsu bota: en / pl / de / ru / uk / be / ar.
/setrole id roleownerowner|admin|operator.
/crm on|offownerWłącz/wyłącz most CRM konta.
/deleteaccountownerUsuń konto.
/idna czaciePokaż chat_id.

Panel webowy

Logowanie tenanta: link z /panel albo token na /account/login/.

SekcjaPo co
PrzeglądLiczniki i ostatnie rozmowy; nazwa firmy; most CRM dla ownera — przełącznik i link webhooka (puste — wspólny z config).
StronyTworzenie, snippet, pełne ustawienia widżetu.
OperatorzyUczestnicy, zaproszenia, role, grupy.
TrasyAssignments: strona → operator/grupa.
RozmowyHistoria, release, notatki, ocena.
StatystykiOdwiedziny, boty, formularze i czat dla wszystkich stron lub jednej; strony; kod tylko do statystyk; klucz API konta.
SzablonyCRUD szablonów + podsumowanie ocen (od Basic).

Ustawienia strony

Dostępne w bocie („Ustawienia”) oraz w panelu: Strony → koło zębate.

PoleZnaczenie
Nazwa / tytuł / podtytułNagłówek czatu.
Powitanie / logoPierwsza wiadomość i marka.
Online od–do, TZ, pauzaStatus Online/Offline.
Eskalacja (min)Alert przy braku odpowiedzi.
Kolor / pozycja / marginesyPrzycisk widżetu.
Język / dźwięken|pl|de|ru|uk|be|ar oraz URL mp3.
Allowed originsCORS: domeny po przecinku albo *.
Invite *Zaproszenie w dymku (od Basic).
Visibility JSONGdzie pokazywać przycisk/invite (od Basic).
GDPRCheckbox zgody przed pierwszą wysyłką.
Asystent AIOdpowiada klientowi, gdy nikt nie odpisał przez N minut (domyślnie 3).

Asystent AI (Gemini)

Klient napisał, operator milczy — po ustawionej liczbie minut w rozmowie odpowiada Google Gemini. Klient widzi odpowiedź w widgecie, a operatorzy dostają w Telegramie kartę „AI odpowiedziało” z tym samym tekstem, żeby nikt nie powtarzał.

  • Włącza się osobno dla każdej strony: Strony → koło zębate → Asystent AI. Tam też opóźnienie i pole „co AI ma wiedzieć o firmie” — godziny, dostawa, czego nie wolno obiecywać.
  • Odpowiedź człowieka zeruje licznik; rozmowy przejętej przez operatora (claim) AI nie rusza.
  • Odpowiedź AI nie kasuje eskalacji: administrator i tak dostanie alert, że człowiek nie odpisał.
  • Model odpowiada krótko, nie wymyśla cen ani terminów, a zapytany wprost przyznaje, że jest automatycznym asystentem.
  • Klucz API ustawia się raz dla całej instalacji: gemini_api_key w config/config.php (klucz z Google AI Studio ma darmowy limit). Bez klucza checkbox nic nie daje.

Przykład visibility

{"include":["/pricing","/contacts"],"exclude":["/admin"],"desktop":true,"mobile":true}

Widżet na stronie

<script async src="https://webchatix.online/widget/webchatix.js"
  data-site-key="SITE_KEY"></script>

Sterowanie ze strony:

webchatix("show");   // pokaż przycisk
webchatix("hide");   // ukryj
webchatix("open");   // otwórz czat
webchatix("close");  // zamknij panel
webchatix("form", "report"); // zalicz wysłanie formularza (statystyki)

Język widżetu bierze się z data-lang, potem z <html lang> strony, a na końcu z przeglądarki; obsługiwane są en / pl / de / ru / uk / be / ar, zapasowy to angielski. Po zmianie ustawień odśwież stronę klienta (wersja widżetu w query ?v=).

Jeśli strona ma ustawioną Content-Security-Policy, dopuść domenę widżetu w trzech dyrektywach: script-src, style-src i connect-src. Wygląd widżet ładuje z osobnego pliku webchatix.css, więc nie trzeba dla niego trzymać 'unsafe-inline' w style-src.

Statystyki odwiedzin i API

Widżet liczy odwiedziny strony, na której jest zainstalowany. Statystyki są przechowywane bez limitu czasu jako liczniki dzienne (doby wg UTC); raport można pobrać za dowolny okres. Dane udostępnia API po tajnym kluczu konta — jeden klucz otwiera wszystkie strony konta.

PoleCo jest liczone
unique_visitorsUnikalni odwiedzający — po cookie widżetu (bez cookie — po IP + przeglądarce w ciągu doby). W okresie bez powtórzeń: jedna osoba w tygodniu liczy się raz.
visitsWejścia — pierwsza strona po 30 minutach bezczynności oraz pierwsza strona odwiedzającego w danej dobie.
page_viewsWyświetlenia stron przez ludzi, w tym przejścia w SPA (history.pushState).
bot_hitsOdwiedziny stron przez boty: wyszukiwarki (Googlebot, Bingbot, YandexBot…), crawlery AI (GPTBot, ClaudeBot, PerplexityBot…), sieci społecznościowe, narzędzia SEO, przeglądarki headless. Nie wliczają się do wyświetleń ani unikalnych.
form_submitsWysłania formularzy na stronach witryny (zdarzenie submit, także formularze wysyłane przez fetch). Wartości pól nie są przesyłane — tylko nazwa formularza: #id, name lub ścieżka action. Wysłania przez boty nie są liczone.
chat_messagesWiadomości odwiedzających w czacie Webchatix (tekst i zdjęcia).
chat_visitorsIlu odwiedzających napisało w czacie — wg rozmów, w okresie bez powtórzeń.
ads_googlePrzejścia z Google Ads: w adresie strony wejścia jest gclid, gbraid, wbraid lub gad_source, albo utm_source=google z płatnym utm_medium (cpc, ppc, paid…). Liczone raz na wejście: odświeżenie strony nie podwaja kliknięcia.
ads_yandexPrzejścia z Yandex Direct: w adresie jest yclid albo utm_source=yandex z płatnym utm_medium. Też raz na wejście.

Zwykły snippet czatu już zbiera statystyki — nic nie trzeba dodawać.

Instalacja tylko do statystyk (bez interfejsu)

Atrybut data-mode="stats" instaluje widżet bez przycisku, okna czatu i stylów: skrypt wysyła tylko jeden lekki hit na stronę. Piksel w <noscript> jest opcjonalny — łapie boty, które nie wykonują JavaScriptu, ale pobierają obrazki.

<script async src="https://webchatix.online/widget/webchatix.js"
  data-site-key="SITE_KEY" data-mode="stats"></script>
<noscript><img src="https://webchatix.online/wx-api.php?action=track&site_key=SITE_KEY"
  width="1" height="1" alt="" style="position:absolute"></noscript>

SITE_KEY to publiczny klucz strony — ten sam co w snippecie czatu (bot: „📋 Kod instalacji”, panel: „Strony”). To nie jest klucz API wxs_…: ten jest tajny i nie trafia do kodu stron.

Jeśli strona ma ustawione Allowed origins, hity ze stron innych domen nie są liczone.

Formularze bez tagu <form>

Wysłanie zwykłego <form> widżet łapie sam — po zdarzeniu submit, także gdy strona wysyła go przez fetch. Często jednak formularz to pola i przycisk <button type="button">, a dane wysyła JavaScript strony; zdarzenia submit wtedy nie ma i wysłanie nie jest liczone. Dla takich formularzy są dwa sposoby.

1. Atrybut data-wx-form na przycisku wysyłania: kliknięcie liczy się jako wysłanie formularza o tej nazwie. Nieaktywny przycisk (disabled) nie jest liczony, podwójne kliknięcie daje jedno wysłanie.

<button type="button" class="get_report" data-wx-form="report">…</button>

2. Wywołanie z kodu strony — gdy wysłanie ma się liczyć np. dopiero po poprawnej walidacji pól. Działa ze zwykłym widżetem i z data-mode="stats". Jeśli Twój kod może wykonać się przed załadowaniem widżetu, dodaj wyżej zaślepkę — wywołania trafią do kolejki i nie zginą.

// po poprawnej walidacji pól
webchatix("form", "report");

// zaślepka — nad wywołaniami, jeśli kod może zadziałać przed widżetem
window.webchatix = window.webchatix || function () {
  (webchatix.q = webchatix.q || []).push(arguments);
};

Atrybut data-wx-form na <form> lub na jej przycisku submit ustawia nazwę formularza w raporcie zamiast #id / name / action.

Klucz API

Klucz wxs_… jest jeden na całe konto. Gdzie go wziąć i wymienić: w bocie Telegram — przycisk 🔑 Klucz API w menu głównym (tam też podsumowanie wszystkich stron), w panelu — Strony → koło zębate. „Wymień klucz” wydaje nowy, stary przestaje działać od razu. Widzą i wymieniają go owner i admini konta.

Klucz jest tajny: publiczny site_key nie nadaje się do odczytu, a samego klucza nie wstawiaj do kodu stron — pobieraj statystyki ze swojego serwera. Statystyki jednej strony są też w bocie: 🌐 Strony → strona → 📊 Statystyki.

Klucz przekazuje się na jeden ze sposobów: nagłówek X-Stats-Key: wxs_…, nagłówek Authorization: Bearer wxs_… lub parametr ?key=wxs_….

Dwa klucze

KluczGdzie używanyPubliczny?
SITE_KEY — klucz stronysnippet czatu, data-mode="stats", piksel wx-api.php?action=track — wszystko, co jest w kodzie stron i tylko zapisuje hitytak
wxs_… — klucz API kontastats-api.php: odczyt statystyk (action=stats) i hity z serwera (action=hit) — tylko z Twojego serwera. Jeden dla wszystkich stron konta.nie, tajny

Klucz API w pikselu lub w kodzie strony zobaczy każdy odwiedzający przez „Pokaż źródło” — i będzie mógł czytać i zawyżać statystyki. Jeśli klucz wyciekł, wymień go.

GET /stats-api.php?action=stats

Parametry: site_key — tylko ta strona konta (bez niego — wszystkie strony); okres — days (ostatnie N dni do dziś, 1–366, domyślnie 7) albo from i to (daty RRRR-MM-DD włącznie, nie dłużej niż 366 dni; jeśli podano jedną datę, druga jest liczona o days dni); limit — ile stron w rankingu każdej witryny (1–1000, domyślnie 50).

curl -H "X-Stats-Key: wxs_…" "https://webchatix.online/stats-api.php?action=stats&days=7&limit=20"
curl -H "X-Stats-Key: wxs_…" "https://webchatix.online/stats-api.php?action=stats&site_key=SITE_KEY"
curl -H "X-Stats-Key: wxs_…" "https://webchatix.online/stats-api.php?action=stats&from=2026-01-01&to=2026-03-31"
{
  "ok": true,
  "account": {"id": 42, "name": "My company"},
  "timezone": "UTC",
  "from": "2026-10-12",
  "to": "2026-10-18",
  "totals": {"unique_visitors": 412, "visits": 530, "page_views": 1874, "bot_hits": 961,
             "form_submits": 23, "chat_messages": 57, "chat_visitors": 14,
             "ads_google": 48, "ads_yandex": 31},
  "days": [
    {"date": "2026-10-18", "unique_visitors": 61, "visits": 74, "page_views": 255, "bot_hits": 140,
     "form_submits": 4, "chat_messages": 9, "chat_visitors": 3,
     "ads_google": 6, "ads_yandex": 4}
  ],
  "sites": [
    {
      "site_key": "SITE_KEY",
      "name": "My site",
      "totals": {"unique_visitors": 300, "visits": 391, "page_views": 1402, "bot_hits": 700,
                 "form_submits": 15, "chat_messages": 40, "chat_visitors": 9,
                 "ads_google": 35, "ads_yandex": 20},
      "days": [ … ],
      "pages": [{"path": "/pricing/", "page_views": 310, "bot_hits": 88, "form_submits": 6}],
      "bots": [{"bot": "Googlebot", "hits": 402}, {"bot": "GPTBot", "hits": 97}],
      "forms": [{"form": "#contact", "submits": 15}]
    }
  ]
}

totals i days to suma po stronach w odpowiedzi; odwiedzający liczeni są osobno dla każdej strony. W sites jest raport każdej strony: days — wpis na każdą datę (dni bez odwiedzin mają zera), pages — ranking stron (ścieżka bez query) wg wyświetleń i odwiedzin botów, bots — odwiedziny wg nazw botów, forms — wysłania wg nazw formularzy.

POST /stats-api.php?action=hit — hity z serwera

Większość botów wyszukiwarek nie wykonuje JavaScriptu, więc widżet ich nie widzi. Aby je też liczyć, backend strony może sam zgłaszać przyjęte żądania: pola site_key (która strona konta; wymagane), url (lub ścieżka), ua — User-Agent, opcjonalne ip, referrer, visitor_id. Paczką — {"site_key": "…", "hits": [ … ]}, do 500 hitów na żądanie; site_key pojedynczego hitu zastępuje wspólny. Bot czy człowiek — rozstrzyga ua.

curl -X POST "https://webchatix.online/stats-api.php?action=hit" \
  -H "X-Stats-Key: wxs_…" -H "Content-Type: application/json" \
  -d '{"site_key": "SITE_KEY", "url": "https://example.com/pricing/", "ua": "Mozilla/5.0 (compatible; bingbot/2.0)", "ip": "203.0.113.7"}'
# → {"ok": true, "views": 0, "bots": 1, "skipped": 0}

Błędy

HTTPerrorPrzyczyna
401key_requiredNie przekazano klucza.
403invalid_keyKlucz jest błędny lub został wymieniony.
403plan_requiredKlucz API działa w planach Basic i Unlimited.
403disabledKonto jest zawieszone.
400too_many_hitsPonad 500 hitów w jednym żądaniu.
400unknown_siteBrak site_key albo to strona innego konta.
400bad_periodZły okres: data nie w formacie RRRR-MM-DD, from później niż to lub okres dłuższy niż 366 dni.

Przechowywane są tylko liczniki i zanonimizowane hashe odwiedzających — bez IP, adresów i User-Agentów w jawnej postaci.

Operatorzy i role

  • owner — pełna kontrola, prośby o plan, usunięcie konta, CRM, przekazanie własności.
  • admin — strony, zaproszenia, trasy, ustawienia.
  • operator — odpowiedzi w rozmowach, notatki/szablony zależnie od planu.

Jeden użytkownik Telegrama = jedno własne konto. W cudzych kontach można być operatorem na zaproszenie.

Grupy

Operatorem może być nie tylko osoba, ale i grupa Telegram: zgłoszenie trafia kartą na czat, odpowiada dowolny uczestnik przez Reply. Podłączenie: dodaj bota do grupy (menu → 💬 Grupy → „Podłącz grupę”) albo wpisz w niej /addgroup — chat_id nie trzeba wpisywać, bot pobiera go sam. Grupy nie zajmują limitu operatorów w planie.

Rozmowy

  • Wiadomość klienta idzie do Telegrama (grupa/operator według trasy).
  • Przyjmij — claim; wiadomość systemowa w historii.
  • Przekaż — tylko do aktywnego uczestnika tego samego konta.
  • Zwolnij / release — można poprosić odwiedzającego o ocenę.
  • Notatki — widoczne dla zespołu, nie dla klienta (od Basic).
  • Szablony — reply na rozmowę + /tpl id albo przycisk szablonu → Reply.

Bezpieczeństwo i GDPR

  • Konta są izolowane po account_id.
  • Magic-link jest jednorazowy; liczba wydawanych linków jest limitowana.
  • Suspend wyłącza widżet, bota i panel tenanta.
  • CORS: ustaw allowed_origins (nie zostawiaj * na produkcji bez potrzeby).
  • Checkbox GDPR — przed pierwszą wiadomością klienta.
  • Limit uploadu zależny od planu (max_upload_mb).
  • Nie więcej niż 10 nowych stron na godzinę na konto.