Практична інструкція

HTML-форма в Google Таблиці: 2 безкоштовні шляхи

Два безкоштовні способи складати заявки з форми в Google Таблицю, з готовим кодом Apps Script. Один прямий, другий спершу додає сповіщення й фільтр спаму.

Коротка відповідь. Відкрийте таблицю й додайте Apps Script із функцією doPost, яка дописує рядок. Розгорніть його як вебзастосунок із доступом для всіх і надсилайте форму на його адресу. Потрібні ще сповіщення на пошту чи в Telegram і фільтр спаму? Надсилайте форму на бекенд для форм, а його вебхук хай викликає такий самий скрипт. Обидва способи безкоштовні.

Formgong

HTML-форма в Google Таблиці: 2 безкоштовні шляхи
HTML-форма в Google Таблиці: 2 безкоштовні шляхи

Два способи коротко

  • Спосіб 1: форма → Apps Script. Форма надсилає дані прямо в маленький скрипт у вашій таблиці. Більше нічого не потрібно. Ви отримуєте рядки, але без сповіщень, без фільтра спаму понад те, що напишете самі, і форма потребує JavaScript.
  • Спосіб 2: форма → бекенд для форм → Apps Script. Форма йде на бекенд. Він відсіює спам, надсилає вам сповіщення, а потім передає кожну справжню заявку у ваш скрипт через вебхук.

Якщо потрібен лише список, почніть зі способу 1. Якщо на заявки треба швидко відповідати, обирайте спосіб 2.

Спосіб 1: форма надсилає дані в Apps Script

Назви пунктів меню наведено, як в англійському інтерфейсі Google. В українському вони перекладені, але стоять на тих самих місцях.

  1. Створіть таблицю, назвіть аркуш Заявки і впишіть у перший рядок: Дата, Ім'я, Email, Повідомлення.
  2. Відкрийте Extensions → Apps Script, видаліть приклад і вставте скрипт нижче.
  3. Натисніть Deploy → New deployment, оберіть Web app. У полі Execute as поставте Me, у Who has access — Anyone.
  4. Підтвердьте дозволи й скопіюйте адресу вебзастосунку. Вона закінчується на /exec.
  5. Вставте цю адресу в код форми з наступного блоку й опублікуйте сторінку.

Скрипт пропускає заявки із заповненим полем-пасткою. Він також бере блокування, тож дві одночасні заявки не перезапишуть одна одну. Функція clean() не дає значенню на кшталт =IMPORTXML(…) спрацювати як формула.

Apps Script
// У таблиці: Extensions > Apps Script. У першому рядку аркуша "Заявки" — назви стовпців.
function doPost(e) {
  const p = e.parameter;
  if (p.botcheck) return json({ ok: true }); // поле-пастка: боти його заповнюють, люди не бачать
  const lock = LockService.getScriptLock();
  lock.waitLock(20000); // записуємо по одному, щоб рядки не перезаписали один одного
  try {
    SpreadsheetApp.getActive().getSheetByName("Заявки").appendRow([
      new Date(), clean(p.name), clean(p.email), clean(p.message),
    ]);
  } finally {
    lock.releaseLock();
  }
  return json({ ok: true });
}

// Значення, що починається з = + - або @, спрацювало б як формула. Апостроф лишає його текстом.
function clean(value) {
  const text = String(value || "");
  return /^[=+\-@]/.test(text) ? "'" + text : text;
}

function json(data) {
  return ContentService.createTextOutput(JSON.stringify(data))
    .setMimeType(ContentService.MimeType.JSON);
}
HTML-форма, яка надсилає дані у вебзастосунок
HTML
<form id="lead-form">
  <label>Ім'я <input type="text" name="name" required autocomplete="name"></label>
  <label>Email <input type="email" name="email" required autocomplete="email"></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%)">
    <input type="text" name="botcheck" tabindex="-1" autocomplete="off">
  </div>
  <button type="submit">Надіслати</button>
  <p id="lead-status" role="status"></p>
</form>
<script>
  const form = document.getElementById("lead-form");
  const status = document.getElementById("lead-status");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    status.textContent = "Надсилаємо…";
    try {
      // Тіло у форматі форми робить запит простим, тож браузер не надсилає preflight.
      const response = await fetch("https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec", {
        method: "POST",
        body: new URLSearchParams(new FormData(form)),
      });
      if (!response.ok) throw new Error(String(response.status));
      form.reset();
      status.textContent = "Дякуємо, заявку отримано.";
    } catch {
      status.textContent = "Не вдалося надіслати. Спробуйте ще раз або напишіть нам на пошту.";
    }
  });
</script>

Чого не вміє спосіб 1

  • Немає сповіщень. Рядки з'являються тихо. Щоб побачити нову заявку, треба відкрити таблицю.
  • Слабкий захист від спаму. Адреса публічна, тож будь-хто, хто її знайде, може щось надіслати. Поле-пастка зупиняє лише простих ботів.
  • Потрібен JavaScript. Форма використовує fetch, бо звичайне надсилання залишило б відвідувача на сторінці Google.
  • Зміни — це нова версія. Після правок у скрипті відкрийте Manage deployments, відредагуйте розгортання й оберіть нову версію. Адреса не зміниться.
  • Квоти. Google обмежує Apps Script для кожного користувача: наприклад, 30 одночасних запусків і 6 хвилин на один запуск (станом на 05.10.2026). Невеликий сайт цього не помітить.

Спосіб 2: вебхук бекенду для форм у вашу таблицю

Тут форма — звичайна HTML-форма, яка надсилає дані на Formgong. Вона працює без JavaScript і показує сторінку подяки. Formgong відсіює спам, надсилає заявку на пошту чи в Telegram, а потім передає JSON у ваш скрипт. Безкоштовний тариф включає один вебхук на форму.

  1. Створіть таблицю й аркуш Заявки зі стовпцями: ID, Дата, Ім'я, Email, Повідомлення.
  2. Вставте скрипт для вебхука нижче, змініть SECRET і розгорніть його як вебзастосунок, як у способі 1.
  3. У Formgong відкрийте налаштування форми й додайте вебхук. Вкажіть адресу вебзастосунку плюс ?key= і ваш секрет.
  4. Натисніть тест вебхука в кабінеті, а потім надішліть справжню заявку із сайту.
Apps Script для вебхука Formgong
Apps Script
// URL вебхука у Formgong: адреса вебзастосунку + "?key=" + той самий SECRET.
// Apps Script не бачить заголовків запиту, тому ключ в адресі замінює перевірку підпису.
const SECRET = "change-me";

function doPost(e) {
  if (e.parameter.key !== SECRET) return reply();
  const body = JSON.parse(e.postData.contents);
  if (body.event !== "submission.created") return reply(); // тест із кабінету надсилає подію "webhook.test"
  const lock = LockService.getScriptLock();
  lock.waitLock(20000);
  try {
    const sheet = SpreadsheetApp.getActive().getSheetByName("Заявки");
    const id = body.submission.id;
    // Повторна спроба має той самий id: пропускаємо, якщо рядок уже є.
    if (!sheet.getRange("A:A").createTextFinder(id).matchEntireCell(true).findNext()) {
      const f = body.submission.fields;
      sheet.appendRow([id, body.submission.created_at, clean(f.name), clean(f.email), clean(f.message)]);
    }
  } finally {
    lock.releaseLock();
  }
  return reply();
}

function clean(value) {
  const text = String(value || "");
  return /^[=+\-@]/.test(text) ? "'" + text : text;
}

// HtmlService, а не ContentService: ContentService відповідає редиректом,
// а відправник вебхуків, який не йде за редиректами, вважає це помилкою.
function reply() {
  return HtmlService.createHtmlOutput("ok");
}

Пастка з редиректом, через яку з'являються дублікати

Google пише, що скрипт, який відповідає через ContentService, повертає редирект на одноразову адресу на script.googleusercontent.com. Браузер іде за ним, тож для способу 1 усе гаразд. А відправник вебхуків, який не йде за редиректами, бачить помилку, хоча рядок уже записано.

Formgong з міркувань безпеки не йде за редиректами вебхуків. Він вважає редирект невдалою доставкою й пробує ще раз пізніше, до п'яти спроб. Кожна спроба запускає скрипт, тож одна заявка може з'явитися п'ять разів. Скрипт для вебхука запобігає цьому двома способами:

  • Відповідає через HtmlService. За словами розробників, така відповідь приходить одразу, без редиректу.
  • Записує ID заявки в стовпець A і пропускає ID, які вже є. Навіть якщо повтор станеться, рядок буде один.

Після налаштування відкрийте журнал вебхуків у кабінеті. Справжня заявка має показати статус 200 з першої спроби.

Без коду: Make, n8n або Zapier

Не хочете чіпати Apps Script? Спрямуйте вебхук в інструмент автоматизації й додайте там крок Google Sheets. Покрокові інструкції є для Make і n8n, який можна розгорнути на своєму сервері. Zapier теж підходить, але його тригер для вебхуків потребує платного тарифу Zapier. Тож безкоштовні варіанти — Make або n8n.

Формат JSON і перевірку підпису на власному сервері описано в документації з вебхуків.

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

Чи можна надсилати HTML-форму в Google Таблиці без коду?

Напряму — ні. Потрібен або невеликий Apps Script, або посередник, наприклад бекенд для форм із Make чи n8n. Скрипт із цієї статті — близько 20 рядків, які достатньо скопіювати.

Чому після надсилання відкривається сторінка Google?

Форма надсилає дані прямо у вебзастосунок, і браузер показує його відповідь. Надсилайте форму через fetch, як у способі 1, або через бекенд для форм, який веде на вашу сторінку подяки.

Чому вебхук створює дублікати рядків?

Відправник побачив помилку й повторив спробу. В Apps Script ContentService відповідає редиректом, і деякі відправники вважають це помилкою. Відповідайте через HtmlService і пропускайте ID заявок, які вже є в таблиці.

Чи безпечно відкривати вебзастосунок для всіх?

Надсилати дані зможе будь-хто з адресою, але прочитати таблицю через неї не можна. Тримайте скрипт простим, перевіряйте секретний ключ для вебхуків і ніколи не повертайте дані таблиці у відповіді.

Джерела та документація

Офіційні джерела для цієї інструкції: Apps Script: web apps, Apps Script: Content service redirects, Apps Script: quotas, Apps Script: Lock service, Stack Overflow: HtmlService avoids the redirect, Zapier pricing. Вебхуки Formgong, де зберігаються дані.

Завантажити текст статті (Markdown)

Оцініть цю статтю

Ваша оцінка

Ми читаємо кожну оцінку. Коментар з'явиться тут лише після нашого схвалення.

← До блогу