Analityka: eventy i GTM
OctaForms sam wysyła eventy analityczne do dataLayer. Nie wklejasz żadnego snippetu
i niczego nie włączasz: jeśli na stronie działa Google Tag Manager, eventy już tam są.
Twoja rola sprowadza się do zbudowania w GTM triggera i tagu GA4.
Strona opisuje kontrakt eventów w wersji 1 (octaFormsSchema: 1). Ten sam kontrakt,
z tymi samymi nazwami i kluczami, obowiązuje we wszystkich produktach OctaForms, więc
jeden kontener GTM obsługuje je wszystkie bez podwójnego liczenia.
Jak to działa
Dział zatytułowany „Jak to działa”Mechanizm ma dwie warstwy:
- Eventy DOM. Widget emituje zdarzenia
CustomEventw przestrzeni nazwoctaforms:. Eventy formularza odpalają się na elemencie<form>, eventy widgetu kontaktowego nadocument. Wszystkie bąbelkują, więc nasłuch podpinasz zawsze nadocument, ae.targetmówi, skąd event przyszedł. - Mostek GTM. Wbudowany moduł nasłuchuje eventów DOM i tłumaczy je na
dataLayer.push(). TworzydataLayer, jeśli go nie ma: to z definicji kolejka, więc pushe sprzed załadowania kontenera GTM zostaną przetworzone przy jego starcie. Działa to też przy kontenerach ładowanych z opóźnieniem (zgoda w CMP, optymalizacje szybkości strony).
Sam push jest bezczynny: to dopisanie obiektu do tablicy w pamięci przeglądarki. Nic
nigdzie nie jest wysyłane, dopóki nie zbudujesz triggera w GTM. Payload nie zawiera
żadnych danych osoby odwiedzającej: slug i location to Twoje etykiety, status
to kod HTTP, a phone to numer telefonu właściciela strony pokazywany w widgecie.
Szybki start w GTM
Dział zatytułowany „Szybki start w GTM”Najwygodniejszy setup to jeden generyczny tag GA4, który przenosi nazwę eventu 1:1:
- Zmienne. Utwórz zmienne typu „Zmienna warstwy danych“ dla kluczy, których
potrzebujesz, np.
octaFormSlug,octaFormLocation,octaFormStatus. - Trigger. Utwórz trigger typu „Zdarzenie niestandardowe“, nazwa zdarzenia
octaforms_.*, z zaznaczoną opcją „Użyj dopasowania do wyrażeń regularnych“. - Tag. Utwórz tag „Google Analytics: zdarzenie GA4“. W polu „Nazwa zdarzenia“
wstaw wbudowaną zmienną
{{Event}}, w parametrach zdarzenia podepnij zmienne z kroku 1. Przypnij trigger z kroku 2. - Konwersje. W GA4 (Administracja, „Kluczowe zdarzenia“) oznacz jako kluczowe
np.
octaforms_form_successioctaforms_phone_call.
Po publikacji kontenera każdy event z katalogu poniżej pojawi się w GA4 pod swoją nazwą, bez dalszej konfiguracji per event.
Jeśli Twój kontener GTM używa przemianowanej warstwy danych (inaczej niż standardowe
dataLayer), podaj jej nazwę na skrypcie widgetu, inaczej eventy trafią do tablicy,
której nikt nie czyta:
<script src="https://app.octaforms.pl/widget/v1/octaforms.js" data-gtm-layer="mojaWarstwa" async></script>Konwersje przy przekierowaniu na stronę podziękowania
Dział zatytułowany „Konwersje przy przekierowaniu na stronę podziękowania”Jeśli formularz ma ustawione przekierowanie po wysłaniu,
event octaforms_form_success odpala się jeszcze przed opuszczeniem strony, a tag GA4 wysyła
dane przez sendBeacon, który przeżywa przejście na kolejną stronę. W praktyce konwersja
dolatuje.
Jest jednak jedno „ale“: jeśli kontener GTM w chwili wysyłki jeszcze nie wstał (typowo przez
bramkę zgody w CMP), push czeka w kolejce dataLayer, a przekierowanie zabiera tę kolejkę
razem ze stroną. Dlatego przy przekierowaniu najpewniejszym pomiarem konwersji jest odsłona
samej strony podziękowania: trigger w GTM na jej adres nie ma z czym się ścigać. Event
octaforms_form_success traktuj wtedy jako sygnał pomocniczy.
Żeby odróżnić prawdziwą konwersję od wejścia prosto na adres strony podziękowania, dopisz do
adresu przekierowania własny znacznik, np. ?f={form_id}: dodajemy go tylko przy realnym
przekierowaniu po zgłoszeniu, a mówi on, który formularz zadziałał, nie kto go wypełnił.
Do triggera nie bierz dopisywanego id, bo to identyfikator konkretnego zgłoszenia (powody
niżej, „Dlaczego eventy nie niosą identyfikatora zgłoszenia“).
Adres strony podziękowania trafia do GA4 jako page_location, więc obowiązuje na nim to samo
ostrzeżenie, co w Osadzaniu:
żadnych danych osobowych.
Katalog eventów
Dział zatytułowany „Katalog eventów”| Event w dataLayer | Event DOM | Kiedy się odpala |
|---|---|---|
octaforms_form_start |
octaforms:form-start |
Pierwsza interakcja z formularzem (focus w polu), raz na zamontowaną instancję. |
octaforms_form_submit |
octaforms:form-submit |
Kliknięcie „Wyślij“, po przejściu walidacji po stronie przeglądarki, przed wysyłką. Raz na gest wysłania. |
octaforms_form_success |
octaforms:form-success |
Serwer przyjął zgłoszenie (odpowiedź 2xx). Emitowany przed przekierowaniem na stronę podziękowania, więc nie ginie. |
octaforms_form_error |
octaforms:form-error |
Wysyłka zakończyła się ostatecznym błędem. octaFormStatus niesie kod HTTP, a przy błędzie sieci 0 z octaFormReason: "network". |
octaforms_widget_open |
octaforms:widget-open |
Otwarcie okna pływającego widgetu kontaktowego (klik w przycisk lub dymek). |
octaforms_tab_switch |
octaforms:tab-switch |
Zmiana zakładki w widgecie kontaktowym (telefon, oddzwonienie, wiadomość). |
octaforms_phone_call |
octaforms:phone-call |
Klik w numer telefonu (link tel:) w widgecie kontaktowym. |
octaforms_phone_copy |
octaforms:phone-copy |
Klik w „Kopiuj numer“; octaFormSuccess mówi, czy kopiowanie się udało. |
Lejek formularza
Dział zatytułowany „Lejek formularza”Cztery eventy formularza układają się w lejek: form_start (ktoś zaczął wypełniać),
form_submit (kliknął wyślij i przeszedł walidację), form_success albo form_error
(rozstrzygnięcie). Różnica między form_start a form_submit to porzucenia w trakcie
wypełniania, a między form_submit a form_success to problemy techniczne
i odrzucenia serwera.
Czego eventy celowo nie zgłaszają
Dział zatytułowany „Czego eventy celowo nie zgłaszają”Te sytuacje nie emitują nic. To decyzje projektowe, dzięki którym dane w lejku są czyste:
- Błędna walidacja w przeglądarce. Jeśli formularz nie przeszedł walidacji
lokalnie i nic nie poleciało do serwera, nie ma ani
form_submit, aniform_error. Gest, który nie wyszedł poza przeglądarkę, nie jest próbą wysyłki. - Ciche ponowienia. Widget potrafi sam ponowić wysyłkę (np. gdy zabezpieczenie
antybotowe każe chwilę odczekać). Ponowienie nie emituje drugiego
form_submitani fantomowegoform_errorprzed sukcesem. - Programowe ustawianie focusu. Zarządzanie focusem wewnątrz widgetu (np. pułapka
focusu w oknie modalnym) nie odpala
form_start. Event wymaga realnej interakcji w polu formularza.
Klucze w dataLayer
Dział zatytułowany „Klucze w dataLayer”Każdy push niesie komplet kluczy. Klucze nieużywane przez dany event mają jawnie
wartość null: model danych GTM pamięta wartości między pushami, więc bez zerowania
octaFormStatus z błędu przykleiłby się do następnego sukcesu.
| Klucz | Typ | Znaczenie |
|---|---|---|
octaFormSlug |
string | null | Identyfikator formularza (ten sam, którego używasz w data-octa-form). |
octaFormLocation |
string | null | Twoja etykieta miejsca osadzenia (patrz niżej). null, gdy jej nie nadasz. |
octaFormStatus |
number | null | Kod HTTP błędu przy form_error (422, 429, 403…), 0 przy błędzie sieci. |
octaFormReason |
string | null | Doprecyzowanie błędu o statusie 0. W widgecie osadzanym zawsze "network". |
octaFormTab |
string | null | Zakładka widgetu kontaktowego (phone, callback, message). Przy widget_open to zakładka startowa. |
octaFormPhone |
string | null | Numer telefonu pokazywany w widgecie (numer właściciela strony, nie gościa). |
octaFormTrigger |
string | null | Skąd padł klik w numer. W widgecie osadzanym: "widget". |
octaFormSuccess |
boolean | null | Wynik kopiowania numeru przy phone_copy. |
octaFormsSchema |
number | Wersja kształtu danych. Obecnie 1. Rośnie tylko przy zmianie łamiącej. |
Etykieta miejsca: data-octa-location
Dział zatytułowany „Etykieta miejsca: data-octa-location”Ten sam formularz często stoi w kilku miejscach: w stopce, na stronie kontaktu, w wyskakującym oknie. Żeby rozróżnić je w raportach, nadaj każdemu miejscu własną etykietę:
<div data-octa-form="ID_FORMULARZA" data-octa-location="stopka"></div>
<a href="#" data-octa-trigger="ID_FORMULARZA" data-octa-location="baner-glowna">Napisz do nas</a>
<script src="https://app.octaforms.pl/widget/v1/octaforms.js" data-octa-widget="ID_WIDGETU" data-octa-location="sluchawka" async></script>Etykieta trafia do każdego eventu z tego miejsca jako octaFormLocation (w DOM:
detail.location). Przy montowaniu programowym przekaż ją w opcjach:
OctaForms.render('#kontakt', 'ID_FORMULARZA', { location: 'strona-kontakt' });Formularze wewnątrz pływającego widgetu kontaktowego dziedziczą etykietę z elementu
data-octa-widget.
Eventy DOM dla developerów
Dział zatytułowany „Eventy DOM dla developerów”Jeśli nie używasz GTM albo chcesz zareagować na event własnym kodem, słuchaj
bezpośrednio na document. Eventy to standardowe CustomEvent z danymi w e.detail:
document.addEventListener('octaforms:form-success', (e) => { console.log('Lead wysłany', e.detail.slug, e.detail.location);});Nasłuch możesz podpiąć w dowolnym momencie, także przed załadowaniem skryptu widgetu:
listener na document nie zależy od kolejności ładowania.
Payloady (e.detail)
Dział zatytułowany „Payloady (e.detail)”| Event | Pola w detail |
|---|---|
octaforms:form-start |
slug, location |
octaforms:form-submit |
slug, location |
octaforms:form-success |
slug, location |
octaforms:form-error |
slug, location, status (number), reason? ("network") |
octaforms:widget-open |
location, mode (zakładka startowa), widgetId |
octaforms:tab-switch |
location, tab, widgetId |
octaforms:phone-call |
location, phone, trigger, widgetId |
octaforms:phone-copy |
location, phone, success (boolean), widgetId |
widgetId to pole dodatkowe widgetu osadzanego (identyfikator z data-octa-widget).
Mostek GTM go nie przenosi; jest dostępne tylko w nasłuchu DOM.
Zasady dispatchu
Dział zatytułowany „Zasady dispatchu”- Eventy formularza odpalają się na elemencie
<form class="octa-forms">i bąbelkują. Dzięki temu w nasłuchu nadocumentodróżnisz instancje poe.target, np. gdy dwa formularze stoją na jednej stronie. - Eventy widgetu kontaktowego odpalają się na
document(dotyczą elementu pływającego, nie fragmentu treści strony). - Formularz otwierany w oknie modalnym renderuje się w
<body>, ale jego eventy również bąbelkują dodocument. Nic nie renderuje się w shadow DOM.
Ręczny mostek do dataLayer jest zbędny
Dział zatytułowany „Ręczny mostek do dataLayer jest zbędny”Jeżeli na Twojej stronie działa jeszcze ręcznie wklejony snippet przepisujący eventy
OctaForms do dataLayer (starsza wersja tej instrukcji), usuń go. Wbudowany mostek
robi to samo automatycznie, a dwa mostki naraz oznaczają podwójne liczenie konwersji.
Wbudowany mostek zabezpiecza się flagą window.octaFormsGtmBridge: pierwszy mostek na
stronie ustawia flagę, każdy kolejny widzi ją i nie podpina nasłuchu. Chroni to przed
duplikatami, gdy na jednej stronie działa kilka produktów OctaForms. Stare ręczne
snippety nie znają tej flagi, dlatego trzeba je usunąć ręcznie.
Wyłączanie
Dział zatytułowany „Wyłączanie”Push do dataLayer jest domyślnie włączony i nie ma przełącznika w panelu (nie ma
czego wyłączać: bez triggera w GTM dane nigdzie nie płyną). Jeśli mimo to chcesz go
wyłączyć, masz dwie równoważne drogi:
<!-- 1. Atrybut na skrypcie widgetu --><script src="https://app.octaforms.pl/widget/v1/octaforms.js" data-gtm="off" async></script>
<!-- 2. Zmienna globalna ustawiona PRZED załadowaniem skryptu --><script>window.octaFormsGtm = false;</script><script src="https://app.octaforms.pl/widget/v1/octaforms.js" async></script>Wyłączenie dotyczy tylko mostka GTM. Eventy DOM (octaforms:*) emitowane są zawsze,
więc własny nasłuch dalej działa.
Dlaczego eventy nie niosą identyfikatora zgłoszenia
Dział zatytułowany „Dlaczego eventy nie niosą identyfikatora zgłoszenia”W payloadach celowo nie ma identyfikatora leada i prosimy, żeby go nie dodawać po swojej stronie:
- Warstwa analityczna opisuje interakcję, nie rekord. Do pracy na rekordach służą webhooki i API.
- Zgłoszenia odfiltrowane jako spam dostają odpowiedź nieodróżnialną od sukcesu (patrz wyżej). Identyfikator w takiej odpowiedzi byłby częściowo szumem, którego nie da się odróżnić od prawdziwych identyfikatorów, a próba jego pominięcia zdradzałaby botom, że zostały wykryte.
- Dzięki temu payload nie zawiera żadnego klucza łączącego dane analityczne z konkretnym zgłoszeniem osoby, co upraszcza Ci analizę zgodności (RODO).
Ta sama zasada dotyczy adresu strony podziękowania. Do przekierowania dopisujemy id
zgłoszenia z myślą o Twoim własnym kodzie na tej stronie (np. dociągnięciu zgłoszenia przez
API), a nie o analityce. Jeśli mierzysz konwersje odsłoną strony podziękowania, jej adres
trafia do GA4 razem z tym parametrem, więc rozważ przyjęcie zgłoszenia pod adresem bez id
albo usunięcie parametru z adresu po odczytaniu go w JavaScripcie.
Prywatność i zgody
Dział zatytułowany „Prywatność i zgody”Push do dataLayer nie zapisuje niczego na urządzeniu gościa, nie wysyła żadnego
żądania sieciowego i nie niesie danych odwiedzającego. To, czy i kiedy dane trafią
do GA4 lub innych narzędzi, kontrolujesz w GTM: tam działa Consent Mode i tam
podpinasz swój CMP. OctaForms nie obchodzi tych mechanizmów, bo niczego nie wysyła
samodzielnie.
Wersjonowanie kontraktu
Dział zatytułowany „Wersjonowanie kontraktu”Nazwy eventów, nazwy kluczy i ich typy to stabilny kontrakt (wersja 1). Zmiany
łamiące podniosą wartość octaFormsSchema, więc możesz zbudować w GTM trigger
blokujący nieznaną wersję, jeśli Twoje tagi są wrażliwe na kształt danych. Nowe
eventy i nowe klucze mogą dochodzić w ramach tej samej wersji.