AJAX-форма контакту

Ті самі поля контакту, надіслані через fetch як JSON. Відвідувач лишається на сторінці й бачить короткий статус.

Що ви копіюєте

Цей шаблон надсилає ті самі поля контакту через fetch, тож відвідувач лишається на сторінці і читає короткий статус.

У форми все одно є action і метод POST. Якщо JavaScript не виконується, браузер робить звичайне надсилання.

Цей запасний шлях важливий для старіших браузерів і для людей, які блокують скрипти. Дві форми підтримувати не треба.

Основний сніпет надсилає JSON. Він ставить Content-Type у application/json і Accept у application/json.

Успіх — це логічне поле success у JSON. Коли воно true, сніпет показує повідомлення відповіді або коротку подяку і очищає форму.

Коли воно false, сніпет показує повідомлення відповіді. Formgong пише це повідомлення мовою _lang.

JSON і FormData

Тіло JSON має перелічити поля, які ви хочете надіслати. Сніпет включає access_key, _lang, name, email, phone, message і botcheck.

Якщо пізніше розкоментуєте Turnstile, шлях JSON також копіює cf-turnstile-response, коли в цьому полі є значення.

Додатковий сніпет використовує FormData замість JSON. Тип вмісту, разом із межею, ставить браузер. Самі Content-Type не задавайте.

FormData бере кожне поле форми, включно з токеном Turnstile, якщо віджет стоїть усередині форми.

Обидва шляхи надсилають Accept: application/json. Без цього заголовка звичайне надсилання з браузера отримує сторінку подяки, а не JSON.

Не надсилайте водночас тіло JSON і тіло multipart. Оберіть одне. Два сніпети — це альтернативи, а не шари.

Спам, Telegram і межі

Лишайте пастку з назвою botcheck порожньою і поза екраном, з tabindex -1. Заповнену пастку зберігають як спам і не доставляють.

Назви полів лишайте короткими, щоб Telegram міг надрукувати їх жирним. Не перейменовуйте email на довге речення.

Ключ доступу лишається на сторінці. Перенесення його в серверний секрет форму не робить безпечнішою, а в цього сніпета сервера немає.

На безкоштовному плані Telegram надходить одразу, а пошта — денним дайджестом. Вхідні зберігають заявки 30 днів.

Безкоштовний план включає 300 заявок на місяць. Спам одну з них не витрачає.

Цей перегляд нічого не надсилає. Підключіть сніпет на своєму сайті, а потім надішліть тест із тієї сторінки.

Сервіс веде Formgong. Щодо продукту пишіть на support@formgong.com.

Перегляд

Код форми

HTML
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
  <input type="hidden" name="access_key" value="fk_your_access_key">
  <input type="hidden" name="_lang" value="uk">
  <label>Ім’я <input type="text" name="name" autocomplete="name" required></label>
  <label>Email <input type="email" name="email" autocomplete="email" required></label>
  <label>Телефон <input type="tel" name="phone" autocomplete="tel"></label>
  <label>Повідомлення <textarea name="message" required></textarea></label>
  <div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
  <label>Залиште це поле порожнім <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
  <!--
Необов’язково. Увімкніть Turnstile для цієї форми, приберіть ці позначки коментаря і вставте ключ сайту.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="uk"></div>
-->
  <button type="submit">Надіслати</button>
  <p data-status role="status"></p>
</form>
<script>
(function () {
  var form = document.getElementById("fg-ajax");
  if (!form) return;
  var status = form.querySelector("[data-status]");
  form.addEventListener("submit", function (event) {
    event.preventDefault();
    var data = {
      access_key: form.access_key.value,
      _lang: form._lang.value,
      name: form.name.value,
      email: form.email.value,
      phone: form.phone.value,
      message: form.message.value,
      botcheck: form.botcheck.value
    };
    var token = form.querySelector('[name="cf-turnstile-response"]');
    if (token && token.value) data["cf-turnstile-response"] = token.value;
    var body = JSON.stringify(data);
    fetch("https://formgong.com/submit", {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: body
    }).then(function (res) { return res.json(); }).then(function (result) {
      if (status) status.textContent = result && result.success ? (result.message || "Надіслано. Дякуємо!") : ((result && result.message) || "Не вдалося надіслати. Спробуйте ще раз.");
      if (result && result.success) form.reset();
    }).catch(function () {
      if (status) status.textContent = "Не вдалося надіслати. Спробуйте ще раз.";
    });
  });
})();
</script>
Та сама форма з FormData замість JSON
Та сама форма з FormData замість JSON
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
  <input type="hidden" name="access_key" value="fk_your_access_key">
  <input type="hidden" name="_lang" value="uk">
  <label>Ім’я <input type="text" name="name" autocomplete="name" required></label>
  <label>Email <input type="email" name="email" autocomplete="email" required></label>
  <label>Телефон <input type="tel" name="phone" autocomplete="tel"></label>
  <label>Повідомлення <textarea name="message" required></textarea></label>
  <div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
  <label>Залиште це поле порожнім <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
  <!--
Необов’язково. Увімкніть Turnstile для цієї форми, приберіть ці позначки коментаря і вставте ключ сайту.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="uk"></div>
-->
  <button type="submit">Надіслати</button>
  <p data-status role="status"></p>
</form>
<script>
(function () {
  var form = document.getElementById("fg-ajax");
  if (!form) return;
  var status = form.querySelector("[data-status]");
  form.addEventListener("submit", function (event) {
    event.preventDefault();
    var body = new FormData(form);
    fetch("https://formgong.com/submit", {
      method: "POST",
      headers: { Accept: "application/json" },
      body: body
    }).then(function (res) { return res.json(); }).then(function (result) {
      if (status) status.textContent = result && result.success ? (result.message || "Надіслано. Дякуємо!") : ((result && result.message) || "Не вдалося надіслати. Спробуйте ще раз.");
      if (result && result.success) form.reset();
    }).catch(function () {
      if (status) status.textContent = "Не вдалося надіслати. Спробуйте ще раз.";
    });
  });
})();
</script>

Питання та відповіді

Чому у форми все ще є URL дії?

Щоб надсилання працювало, коли JavaScript вимкнено. Скрипт викликає preventDefault лише тоді, коли він виконується.

Надсилати JSON чи FormData?

Обидва варіанти прийнятні. JSON явно називає кожне поле. FormData коротший, коли ви пізніше додаєте поля, бо він читає форму.

Рядок статусу лишається порожнім. Що не так?

Перевірте, що Accept дорівнює application/json, що ключ доступу належить вашій формі, і що сторінку віддають через http або https, а не як локальний файл.

Чи може ця форма завантажити файл?

У цьому шаблоні ні. Полям файлів потрібні ввімкнені вкладення і дійсний токен Turnstile. Це налаштування описане в документації кабінету.