Форма заявки, которая действительно доходит: разбираю свою
Большинство форм показывают «спасибо» независимо от того, дошла заявка или нет. Разбираю по шагам форму этого сайта: работа без JavaScript, отсев ботов без капчи и честное поведение при сбое доставки.
Форма на сайте выглядит простой задачей, пока не задашь один вопрос: что происходит, когда отправка не удалась.
Большинство форм отвечают «спасибо, скоро свяжемся» в любом случае. Человек уходит довольным, заявка не дошла никуда, и узнаёте вы об этом через месяц, когда кто-то напишет «я вам писал, вы не ответили». Это не редкая авария, это обычное поведение по умолчанию.
Разберу форму этого сайта целиком: она открыта в репозитории, так что всё ниже можно проверить.
Она работает без JavaScript
Форма — обычный <form method="post" action="/api/lead">. Никакого перехвата отправки ради красоты.
Это не про принципиальность, а про доставку. JavaScript не выполняется чаще, чем кажется: экономия трафика в мобильном браузере, блокировщик, который зацепил лишнее, медленная сеть, где человек успел нажать кнопку до загрузки скриптов, режим чтения. Если отправка держится на скрипте, все эти заявки просто исчезают, причём бесшумно: в аналитике их не будет, потому что аналитика тоже на скрипте.
Браузер умеет отправлять формы сам, тридцать лет как. Сервер принимает FormData и отвечает редиректом на страницу «спасибо». Скрипт на странице нужен только для мелочей: подставить UTM-метки и отправить фоном, чтобы страница не перезагружалась. Выключите его — всё продолжит работать, только с перезагрузкой.
Боты отсеиваются без капчи
Капчи на сайте нет намеренно. Она перекладывает работу на человека, который и так уже решил вам написать, и это худший момент, чтобы просить его разгадывать светофоры.
Вместо неё два незаметных фильтра.
Первый — скрытое поле website, спрятанное от глаз и помеченное aria-hidden, чтобы его не увидел и скринридер. Человек его не заполнит, потому что не видит. Боты заполняют формы по именам полей и в поле с именем «website» охотно пишут адрес.
Второй — время. Страница проставляет скрытую метку момента загрузки, и отправка быстрее трёх секунд считается машинной. Живой человек физически не успевает прочитать три поля и написать осмысленную задачу за это время.
Важная деталь в том, что происходит дальше. Пойманная отправка получает ровно такой же ответ, как успешная: тот же редирект на «спасибо», тот же {"ok": true}. Бот не узнаёт, что его отсекли, и не начинает подбирать обход. Отличить снаружи нельзя, в логе остаётся строчка.
Длинный текст обрезается, а не отклоняется
У каждого поля есть предел: сто символов на имя, двести на контакт, три тысячи на описание задачи. Но превышение не отклоняет заявку, а подрезает значение.
Разница существенная. Человек, который написал подробное описание на четыре тысячи знаков, — это хороший человек, он уже вложился. Ответить ему «слишком длинно, перепишите» означает потерять его на ровном месте. Пусть лучше придёт укороченным, остальное спросите в переписке.
Два получателя с разной важностью
Заявка уходит в два места, и они неравноправны.
Телеграм — обязательный канал. Не дошло туда — значит, не дошло вообще.
Таблица — копия. Если вебхук таблицы отвалился или отвечает ошибкой, в лог падает строка, а доставка продолжается как ни в чём не бывало. Копия для истории не должна иметь права уронить основной канал. Это общее правило для любой такой связки: решите заранее, что именно обязательно, и не позволяйте необязательному блокировать обязательное.
У обоих вызовов стоит таймаут в восемь секунд. Без него зависший провайдер держал бы человека на белом экране до таймаута самой функции.
Самое главное: что видно при сбое
Если телеграм не принял сообщение, человек не увидит «спасибо». Он увидит страницу, где написано, что отправить не получилось, и стоит кнопка написать на почту напрямую.
Это неприятно показывать и правильно показывать. Заявка не теряется: человек в этот момент максимально мотивирован, он уже всё написал, и один клик уводит его в почту. Ложное «спасибо» в той же ситуации теряет его целиком, и тихо.
То же решение я заложил в голосового администратора: когда агент дважды не смог записать email, он не делает вид, что всё в порядке, а помечает запись и отдаёт человеку. Принцип один — сбой нужно показывать тому, кто может на него среагировать.
Что забрать себе
Четыре правила, не зависящие от стека.
Пусть форма отправляется браузером, а скрипт только улучшает. Фильтруйте ботов тихо и отвечайте им как при успехе. Решите, какой канал обязательный, и не давайте необязательным его ронять. И покажите честную ошибку с запасным способом связи вместо ложного «спасибо».
Код формы и серверной функции открыт в репозитории сайта. Нужна такая же связка под ваш сайт и вашу CRM — опишите задачу.