Gotowy workflow: formularz, arkusz i powiadomienie
Zgłoszenia z formularza - zapisy na webinar, leady, ankiety - rozjeżdżają się po skrzynce mailowej i giną, aż ktoś przypomni sobie, że trzeba było na nie odpowiedzieć. Ten gotowiec zamyka je w jednym miejscu: arkuszu Google, z natychmiastowym powiadomieniem na Telegramie. Zamiast osobnego narzędzia formularzowego (Typeform, Google Forms, JotForm) korzystasz z node'a, który n8n ma już wbudowany - n8n Form Trigger (dokumentacja) sam hostuje formularz pod adresem Twojej instancji, bez zakładania konta w kolejnym serwisie.
To konkretny wariant przepisu "Lead z formularza → CRM → powiadomienie" z Modułu 8: Wzorce i wdrożenia - tu zamiast CRM masz najprostszy możliwy magazyn danych, arkusz Google, a walidację i normalizację danych ćwiczysz w praktyce w node'cie Code z Modułu 5: Kod i sub-workflow, zamiast tylko czytać o nim w teorii.
Czego potrzebujesz
Dział zatytułowany „Czego potrzebujesz”- Moduł 5 ukończony - wystarczy znajomość Code Node (tryby uruchamiania, zwracany format danych) i obsługi błędów. Jeśli czegoś z tego brakuje, wróć do Modułu 5: Kod i sub-workflow.
- Podstawy OAuth2 z Modułu 4 - do podłączenia credentials Google Sheets. Patrz Moduł 4: Integracje i API, jeśli jeszcze nie zakładałeś takich credentials.
- Działająca instancja n8n - Cloud, Docker albo dowolny hosting z Modułu 1: Instalacja i hosting.
- Konto Google z arkuszem i skonfigurowanymi credentials OAuth2 - procedurę zakładania opisuję w sekcji "Credentials Google" niżej, odsyłając do gotowca Faktury z Gmaila na Google Drive, gdzie już to wyjaśniłem.
- Bota Telegram i jego token - jeśli jeszcze go nie masz, załóż go przez BotFather dokładnie tak, jak w gotowcu Poranny brief na Telegram. Tutaj tej instrukcji nie powtarzam.
Jak to działa
Dział zatytułowany „Jak to działa”Cztery node'y od formularza po powiadomienie - żadnego zewnętrznego narzędzia formularzowego.
Pobierz gotowy workflow
Dział zatytułowany „Pobierz gotowy workflow”Cały workflow w formacie JSON, gotowy do zaimportowania: formularz-arkusz-powiadomienie.json.
- Pobierz plik
formularz-arkusz-powiadomienie.json(link wyżej). - W n8n otwórz listę workflow i wybierz Import from File (albo przeciągnij plik na kanwę nowego, pustego workflow).
- W arkuszu Google Sheets, który chcesz podpiąć, utwórz kartę (tab) o nazwie Zgłoszenia z
nagłówkami w pierwszym wierszu dokładnie:
Imię,Email,Wiadomość,Data zgłoszenia. - Uzupełnij dwa placeholdery, zanim uruchomisz workflow - patrz tabela niżej.
| Placeholder | Gdzie | Co wpisać |
|---|---|---|
ID_ARKUSZA |
node Zapisz zgłoszenie (Google Sheets, pole Document, tryb By ID) | ID arkusza Google Sheets - fragment adresu URL między /d/ a /edit |
TWOJ_CHAT_ID |
node Wyślij powiadomienie Telegram (pole Chat ID) | ID czatu, na który ma trafić powiadomienie |
Na koniec podepnij pod node'em Google Sheets swoje credentials OAuth2 i pod node'em Telegram swoje credentials bota - bez tego oba node'y zgłoszą błąd uwierzytelniania przy pierwszym uruchomieniu.
Budowa krok po kroku
Dział zatytułowany „Budowa krok po kroku”1. n8n Form Trigger - formularz zgłoszeń
Dział zatytułowany „1. n8n Form Trigger - formularz zgłoszeń”Dodaj node n8n Form Trigger - w przeciwieństwie do zwykłego Webhooka, ten node sam generuje i hostuje stronę formularza pod adresem Twojej instancji n8n, więc nie potrzebujesz Typeform, Google Forms ani JotForm (dokumentacja node'a n8n Form Trigger). W polu Form Title wpisz tytuł widoczny na stronie formularza (np. "Zapisz się"), a w Form Elements dodaj trzy pola:
| Pole (Field Name) | Element Type | Required Field |
|---|---|---|
Imię |
Text Input | tak |
Email |
tak | |
Wiadomość |
Textarea | nie |
W sekcji Options dodaj opcję Form Path, żeby ustawić czytelny fragment adresu - w
gotowcu to formularz-zgloszenia. Tak jak przy webhookach, formularz ma dwa adresy: Test
URL (aktywny po kliknięciu Execute step albo Execute workflow na nieaktywnym workflow -
dokładnie ten sam mechanizm, który znasz z
Modułu 2: Interfejs i 1. workflow i
Modułu 4: Integracje i API) i Production URL (działa dopiero po
aktywacji workflow). Zanim wyślesz link do prawdziwych odbiorców, przełącz Active.
W polu Respond When zostaw domyślne "Form Is Submitted", a w Options → Form Response wpisz krótkie podziękowanie (np. "Dziękujemy! Zgłoszenie zostało zapisane.") - to jedyne, co zobaczy osoba wypełniająca formularz.
2. Code - walidacja i normalizacja danych
Dział zatytułowany „2. Code - walidacja i normalizacja danych”Dodaj node Code w trybie Run Once for Each Item (tu zawsze jeden item na uruchomienie - jedno zgłoszenie), język JavaScript (dokumentacja node'a Code):
const imie = ($json['Imię'] || '').trim();const email = ($json['Email'] || '').trim().toLowerCase();const wiadomosc = ($json['Wiadomość'] || '').trim();
// Guard - formularz ma Required Field, ale nie ufaj wyłącznie walidacji przeglądarkiif (!imie || !email) { throw new Error('Brak wymaganych danych: pole "Imię" i "Email" są obowiązkowe.');}
return { json: { imie, email, wiadomosc, data_zgloszenia: $json.submittedAt }};Czytając po linijce:
$json['Imię'],$json['Email'],$json['Wiadomość']- to dokładnie te klucze, które Form Trigger nadał polom formularza (patrz notatka w kroku 1). Nawias kwadratowy zamiast kropki dlatego, że klucz z polskim znakiem bywa niewygodny do czytania w notacji$json.pole..trim()- usuwa białe znaki z brzegów; dlaImięiEmailto podwójne zabezpieczenie (Form Trigger i tak już to robi automatycznie), dlaWiadomośćto jedyne miejsce, w którym się to dzieje..toLowerCase()na e-mailu - normalizacja, żeby ten sam adres wpisany raz wielkimi, raz małymi literami nie wyglądał w arkuszu jak dwa różne zgłoszenia.if (!imie || !email) throw new Error(...)- formularz ma wprawdzie Required Field włączone na obu polach, ale nie ufaj wyłącznie walidacji po stronie przeglądarki.throw new Error(...)w Code Node przerywa workflow dokładnie tak samo, jak dedykowany node Stop And Error z Modułu 5, tylko że wewnątrz kodu.data_zgloszenia: $json.submittedAt- Form Trigger sam dokłada do każdego zgłoszenia polesubmittedAt(znacznik czasu ISO 8601 momentu wysłania) - nie musisz liczyć go osobnym wyrażeniem$now.- Zwrócony pojedynczy obiekt (nie tablica) - to konwencja trybu Run Once for Each Item, który poznałeś w Moduł 5: Kod i sub-workflow: n8n sam opakowuje wynik w listę itemów.
3. Google Sheets - dopisz wiersz (Append)
Dział zatytułowany „3. Google Sheets - dopisz wiersz (Append)”Dodaj node Google Sheets, ustaw Resource: Sheet Within Document i Operation: Append
Row - ten sam wzorzec Resource/Operation, co w każdym innym node'cie aplikacji w n8n (patrz
Moduł 4: Integracje i API). W polu Document (tryb By ID) wskaż
arkusz przez jego ID (placeholder ID_ARKUSZA), a w polu Sheet (tryb By Name) wpisz nazwę
karty - w gotowcu to Zgłoszenia. W sekcji mapowania kolumn wybierz Map Each Column Below i
przypisz cztery kolumny do pól z poprzedniego kroku:
| Kolumna w arkuszu | Wartość |
|---|---|
Imię |
{{ $json.imie }} |
Email |
{{ $json.email }} |
Wiadomość |
{{ $json.wiadomosc }} |
Data zgłoszenia |
{{ $json.data_zgloszenia }} |
Nagłówki kolumn w arkuszu (pierwszy wiersz karty) muszą się zgadzać z nazwami po lewej stronie dokładnie - wielkość liter i polskie znaki też się liczą. Jeśli je zmienisz, zmień też mapowanie w node'cie. Zweryfikowane pola: dokumentacja node'a Google Sheets.
Credentials OAuth2 dla Google Sheets zakładasz dokładnie tak samo, jak opisuję w sekcji "Credentials Google (Gmail + Drive)" gotowca Faktury z Gmaila na Google Drive - to ten sam mechanizm (Managed OAuth2 na n8n Cloud, własny projekt w Google Cloud Console na self-hostingu), tylko dla innego produktu Google. Pełna procedura: Google OAuth2 single service w dokumentacji n8n oraz Moduł 4: Integracje i API.
4. Telegram - wyślij powiadomienie
Dział zatytułowany „4. Telegram - wyślij powiadomienie”Dodaj node Telegram w operacji Send Message, podłącz credentials bota (dokładnie tak, jak
zakładasz go w gotowcu Poranny brief na Telegram - stamtąd
weźmiesz też swój Chat ID, jeśli jeszcze go nie znasz), wpisz Chat ID (placeholder
TWOJ_CHAT_ID) i treść wiadomości wyrażeniem łączącym pola ze zgłoszenia:
Nowe zgłoszenie z formularza!
Imię: {{ $json.imie }}E-mail: {{ $json.email }}Wiadomość: {{ $json.wiadomosc || '(brak)' }}Zweryfikowane pola: dokumentacja node'a Telegram.
Co może pójść nie tak
Dział zatytułowany „Co może pójść nie tak”Formularz nie przyjmuje zgłoszeń na produkcji
Dział zatytułowany „Formularz nie przyjmuje zgłoszeń na produkcji”- Objaw: link do formularza, który wysyłasz realnym odbiorcom, zwraca błąd albo w ogóle się nie otwiera, mimo że w edytorze n8n wszystko działało.
- Przyczyna: tak jak webhook, formularz ma dwa różne adresy - Test URL (aktywny tylko po kliknięciu Execute step/Execute workflow na nieaktywnym workflow) i Production URL (działa stale, ale dopiero gdy workflow jest aktywny) - dokładnie ten sam mechanizm, co przy zwykłym Webhooku, opisany w Moduł 2 i Moduł 4.
- Naprawa: skopiuj Production URL z node'a Form Trigger (nie Test URL) i włącz przełącznik Active w prawym górnym rogu edytora, zanim wyślesz link dalej.
Krzywe nazwy kolumn w arkuszu - dane trafiają w złe miejsce
Dział zatytułowany „Krzywe nazwy kolumn w arkuszu - dane trafiają w złe miejsce”- Objaw: wiersz w arkuszu zapisuje się, ale wartości są przesunięte względem nagłówków albo w ogóle brakuje którejś kolumny.
- Przyczyna: node Google Sheets w trybie Map Each Column Below dopasowuje dane po dokładnej nazwie nagłówka w pierwszym wierszu karty - jeśli zmienisz nazwę kolumny w arkuszu (albo literówka wkradnie się przy tworzeniu karty) już po skonfigurowaniu node'a, mapowanie przestaje się zgadzać. To udokumentowany, częsty problem - opisuje go wprost sekcja Common Issues node'a Google Sheets.
- Naprawa: otwórz node Google Sheets i ponownie wybierz tryb mapowania kolumn, żeby n8n pobrał aktualne nagłówki z arkusza na nowo. Najprościej: trzymaj nagłówki w arkuszu w brzmieniu z tabeli w sekcji "Budowa krok po kroku" i nie zmieniaj ich bez poprawienia node'a.
Code Node zatrzymuje się z błędem "Cannot read properties of undefined"
Dział zatytułowany „Code Node zatrzymuje się z błędem "Cannot read properties of undefined"”- Objaw: node Waliduj i oczyść dane kończy pracę na czerwono, workflow się zatrzymuje.
- Przyczyna: najczęściej odwołanie do pola, którego dany item nie ma - np. literówka w nazwie
klucza (
$json['Imie']zamiast$json['Imię']) albo zmiana etykiety pola w Form Trigger bez poprawienia kodu. Pełne rozpoznawanie tego błędu opisuję w Coś nie działa? Typowe problemy z n8n. - Naprawa: sprawdź w panelu danych node'a Formularz zgłoszeniowy dokładne nazwy kluczy (dokładnie takie, jak Field Name w formularzu) i porównaj z tym, czego szuka kod.
Google Sheets zwraca błąd limitu zapytań przy nagłym ruchu
Dział zatytułowany „Google Sheets zwraca błąd limitu zapytań przy nagłym ruchu”- Objaw: node Zapisz zgłoszenie kończy się błędem
429/ "Too many requests" przy większej liczbie zgłoszeń w krótkim czasie. - Przyczyna: Google Sheets API domyślnie ogranicza zapisy do 300 żądań na minutę na projekt i 60 żądań na minutę na użytkownika - przy nagłym skoku zgłoszeń (np. link do formularza trafił do dużej grupy naraz) ten limit da się przekroczyć, zgodnie z oficjalną dokumentacją limitów Google Sheets API.
- Naprawa: w ustawieniach node'a Google Sheets włącz Retry On Fail z odstępem między próbami (patrz Moduł 5: obsługa błędów) - Google zaleca wprost strategię exponential backoff. Realny ruch z jednego formularza rzadko faktycznie przekracza ten limit, więc w praktyce to zabezpieczenie "na wszelki wypadek", a nie codzienna awaria.
Jak to rozbudować
Dział zatytułowany „Jak to rozbudować”- CRM zamiast arkusza - zamiast Google Sheets podepnij node CRM, którego już używasz (HubSpot, Pipedrive i inne mają dedykowane node'y aplikacji w n8n) - reszta workflow (formularz, Code, Telegram) zostaje bez zmian. To już pełna wersja przepisu "Lead z formularza → CRM → powiadomienie" z Modułu 8: Wzorce i wdrożenia.
- Autoresponder mailowy - dodaj za node'em Code node wysyłający e-mail powitalny do
zgłaszającego (Gmail albo SMTP) - masz już oczyszczony, poprawny adres w polu
email. - Obsługa błędów jako standard - podepnij dedykowany error workflow z node'em Error Trigger, żeby o nieudanym zapisie do arkusza czy błędzie Telegrama dowiedzieć się od razu, a nie przy najbliższej kontroli arkusza - mechanizm opisuję w Moduł 5: obsługa błędów.
- Deduplikacja po e-mailu - zanim dopiszesz wiersz, sprawdź node'em Google Sheets (operacja odczytu) albo prostym IF, czy dany e-mail już jest w arkuszu, i pomiń zapis albo zaktualizuj istniejący wiersz zamiast dublować zgłoszenie - to ten sam mechanizm idempotentności, co w Moduł 8.
Co warto zapamiętać
- n8n Form Trigger sam hostuje formularz pod adresem instancji - bez zewnętrznego narzędzia formularzowego, z tymi samymi zasadami Test URL/Production URL co przy webhookach.
- Klucz pola w danych to dokładnie Field Name z formularza - trzymaj się jednej pisowni w Form Trigger, Code Node i mapowaniu kolumn arkusza.
- Walidacja w Code Node (
throw new Error(...)) to ta sama zasada co dedykowany node Stop And Error z Modułu 5 - nie ufaj wyłącznie wymaganym polom w interfejsie formularza. - Google Sheets w trybie Map Each Column Below dopasowuje dane po dokładnej nazwie nagłówka - literówka albo zmiana nagłówka po skonfigurowaniu node'a psuje mapowanie po cichu.
- Google Sheets API ma limit zapytań (300/min na projekt, 60/min na użytkownika) - Retry On Fail z odstępem wystarcza na normalny ruch z jednego formularza.
Szukasz kolejnego gotowca do wdrożenia od razu? Zobacz wszystkie gotowe workflow.
Częste pytania
Czy do zbierania zgłoszeń potrzebuję osobnego narzędzia formularzowego, np. Typeform albo Google Forms?
Nie - n8n ma własny n8n Form Trigger, który sam generuje i hostuje stronę formularza pod adresem Twojej instancji, bez rejestracji w kolejnym serwisie. Ten gotowiec korzysta wyłącznie z niego.
Dlaczego mój formularz nie przyjmuje zgłoszeń, mimo że w edytorze n8n działał bez zarzutu?
Najczęściej dlatego, że ktoś dostał Test URL zamiast Production URL, albo workflow nie jest aktywny. Formularz - podobnie jak webhook - ma dwa różne adresy, a produkcyjny działa dopiero po włączeniu przełącznika Active.
Co się stanie, jeśli ktoś spróbuje wysłać formularz bez wypełnienia imienia albo e-maila?
Formularz ma oba pola oznaczone jako Required Field, więc przeglądarka nie pozwoli wysłać pustego formularza. Dodatkowo Code Node ma własny guard ("throw new Error"), który zatrzyma workflow, gdyby mimo to dotarły puste dane - np. przy ręcznym wywołaniu adresu formularza z pominięciem przeglądarki.
Czy mogę zamiast Google Sheets zapisywać zgłoszenia bezpośrednio do CRM?
Tak - to pełna wersja przepisu "Lead z formularza → CRM → powiadomienie" z Modułu 8: Wzorce i wdrożenia. Wystarczy zamienić node Google Sheets na dedykowany node aplikacji Twojego CRM (np. HubSpot czy Pipedrive) - reszta workflow zostaje bez zmian.
Co zrobić, gdy przy nagłym ruchu Google Sheets zwraca błąd limitu zapytań?
Google Sheets API domyślnie ogranicza zapisy do 300 żądań na minutę na projekt i 60 na minutę na użytkownika. Włącz w node'cie Google Sheets Retry On Fail z odstępem między próbami - dla ruchu z jednego formularza to zwykle w zupełności wystarcza.
Czy mogę dodać do formularza więcej pól, niż jest w gotowcu?
Tak - dodaj kolejne pole w Form Elements node'a n8n Form Trigger, obsłuż je w Code Node tak samo jak pozostałe (odwołanie po dokładnej nazwie Field Name) i dodaj odpowiadającą kolumnę w arkuszu oraz w mapowaniu node'a Google Sheets.
made with ❤️ by aitomate.pl - Łukasz Podgórski