Как отправить данные из формы на сайте в Гугл таблицу

Привет, друзья. Сегодня поговорим о том, как отправить данные из формы обратной связи на сайте в Google Sheets. Долго я искал подобное решение в русскоязычном интернете, который бы меня полностью устраивал, но так и не нашел. Говорю как есть, информацию брал отсюда. Если кому-то удобнее читать оригинал - милости прошу. А это вольная адаптация материала на русский язык со своими вставками. Если кто-то знает решение получше, буду рад увидеть ссылку в комментариях. Вот, что получилось у меня. После отправки переходите по ссылке на таблицу и увидите свои данные.

Самостоятельные разбираться в API Google Sheets и делать готовое решение совсем не было времени, так как нужно было быстро решать задачу но, если вам, как и мне, подойдет "черный ящик", которой просто выполняет свою работу, а именно, отправляет данные из формы обратной связи в Гугл таблицу, то давайте разбираться.

При этом под черным ящиком я подразумеваю код, который нужно вставить непосредственно в "Редактор скриптов", который можно открыть в редакторе таблиц, а не код, который будет у нас на сайте.

Но давайте обо все по порядку.

Кроме того, тут предусмотрена возможность отправлять сообщение и на почту. То есть без всяких обработчиков на сайте. Все будет происходить средствами сервиса Google таблиц.

Скопируйте исходный файл таблиц

Первым делом войдите в свой аккаунт Гугл и скопируйте этот файл. Перейдите по ссылке и нажмите "сделать копию".

Копия гугл таблицы

Это позволит сохранить правильный, готовый к работе документ, который в последствии можно будет подправить под свои нужды.

Пример таблицы с отправленными данными из формы

Надеюсь, с этим вы легко справились. Теперь можно поменять названии документа и вместо "Таблица с лидами" дать любое другое имя.

Теперь перейдите во вкладку "Инструменты" и выберите "Редактор скриптов".

Как открыть редактор скриптов в таблицах гугл

Перед вами откроется файл с уже добавленным js-кодом. То самый "черный ящик" о котором я говорил. Если принять некоторые условия, то не вижу особого смысла разбираться во всем этом. В данном случае нас интересует только 8 строка, в которой нужно указать свой email.

Настройка почты в редакторе скриптов

Далее жмем на вкладку "Опубликовать" и выбираем "Развернуть как веб приложение".

Выставляем настройки как на скрине и жмем "Обновить". После этого появится новое окно и жмем "Предоставить разрешение", выбираем свой аккаунт и должно появиться такое предупреждение.

Предоставление доступа приложению

Не пугайтесь. Все в порядке. Так и должно быть. Жмём "дополнительные настройки", а далее кликаем по ссылке "Перейти на страницу "html contact form sendEmail" (небезопасно)"

После этого откроется новое модальное окно, в котором разрешаем доступ.

Если все сделали правильно, то появится модальное окно со ссылкой, ради которой все затевалось. Скопируйте ее себе в текстовый файл, она нам скоро пригодится и нажмите "OK".

По таблице есть одно условие. Первое поле обязательно должно быть отведено под дату и время. Вы можете изменять его название, но туда обязательно будет писаться дата и время. Это реализовано в том скрипте, который мы добавили в редакторе скриптов.

Следующее условие, которое нужно принять это то, что столбцы должны называться также, как и у вас будет заполнен атрибут name у поля в формы. При этом важен регистр. Например, если вы сделает столбец под название "ФИО", то в форме должно быть такое поле:

<input namе="ФИО" type="text" class="some-input" placeholder="Введите ваше ФИО">

У меня в таблице такие поля:

  • Первое - автоматическое "Дата и время заявки". Можете назвать как угодно.
  • Второе - "Имя".
  • Третье - "Телефон".
  • Четвертое - "Email".
  • Пятое - "Произвольное поле". Создал для примера, чтобы показать, что можно дать любое название. Главное не забывать, что название должно соответствовать параметру атрибута name у поля.
  • Шестое - "Сообщение".

Создаем форму обратной связи на сайте

В соответствии с таблицей, которую я создал сделаем форму обратной связи, которая и будет отправлять данные в таблицу.

	<form class="g-form" id="g-form-1" method="POST" action="" autocomplete="off">
		<h2 class="g-form__title g-form__title_main">Оставьте заявку прямо сейчас и получите скидку 10%</h2>
		<h2 class="g-form__title g-form__title_respond"></h2>
		<div class="g-form__preloader"></div>
		<div class="g-form__inputs">
			<fieldset class="g-form__input-wrapper">
				<input class="g-form__input g-form__input_name" id="name" name="Имя" placeholder="Введите ваше имя" required>
			</fieldset>

			<fieldset class="g-form__input-wrapper">
				<input class="g-form__input g-form__input_tel" id="tel" name="Телефон" placeholder="Введите ваш телефон">
			</fieldset>

			<fieldset class="g-form__input-wrapper">
				<input id="email" name="Email" type="email" value=""
				required placeholder="Введите ваш email"/>
			</fieldset>

			<fieldset class="g-form__input-wrapper">
				<input id="arbitrary-field" name="Произвольное поле" placeholder="Произвольное поле для теста">
			</fieldset>

			<fieldset class="g-form__input-wrapper">
				<textarea id="message" name="Сообщение" rows="10"
				placeholder="Введите сообщение"></textarea>
			</fieldset>

			<fieldset class="g-form__input-wrapper g-form__input-wrapper_hidden">
				<label for="honeypot">Помогает бороться со спамом. Должно быть пустым!</label>
				<input id="honeypot" type="text" name="honeypot" value="">
			</fieldset>

			<div class="g-form__button-wrapper">
				<button class="g-form__button">Получить скидку</button>
			</div>
		</div>
	</form>

Немного поясню.

Это заголовок, в который будем выводить ответ формы. Успешно ли отправлена она или нет.

<h2 class="g-form__title g-form__title_respond"></h2>

Это прелоадер, которым скрасим время и убережём нервы пользователя во время ожидания отправки письма в случае, если будет небольшая задержка.

<div class="g-form__preloader"></div>

Следующий блок скрытый. Это небольшая приманка для спама. Она была и в оригинальной статье и мне понравилось название "мешочек/горшочек мёда". Решил оставить. Суть в том, что это поле должно оставаться пустым. Если спам-бот заполнить его, то письмо не будет отправлено. Обычный же пользователь его просто не видит.

<fieldset class="g-form__input-wrapper g-form__input-wrapper_hidden">
   <label for="honeypot">Помогает бороться со спамом. Должно быть пустым!</label>
   <input id="honeypot" type="text" name="honeypot" value="">
</fieldset>

В остальном обычная форма. Еще раз обращаю внимание, что атрибуты name у полей заполнены точно также как название столбцов таблицы с учетом регистра.

Скрипт, отправляющий данные формы в Google Sheets

Давайте подключим скрип, который поможет отправить данные формы в Гугл таблицу и подключим jQuery.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="/g-form/g-form.js"></script>

Не буду расписывать каждую строку. Остановимся ниже лишь на основных моментах скрипта.

$(function() {
	$(".g-form").submit(function (event) {
		event.preventDefault();

		// Ссылка, которую получили на этапе публикации приложения
		let appLink = "https://script.google.com/macros/s/AKfycbx3uFo3Z3UZcwAcJrAng4vvCzDmr2YHGCGWAUkI/exec";

		// Сообщение при успешной отправке данных
		let successRespond = 'Сообщение успешно отправлено. Посмотрите результат <a target="_blank" href="https://docs.google.com/spreadsheets/d/1XcTivCQL4EZJf1x2kB4UwGj5bAi0sfpx1PwtaKgOWHo/edit?usp=sharing">тут</a>';

		// Сообщение при ошибке в отправке данных
		let errorRespond = 'Не удалось отправить сообщение. Cвяжитесь с администратором сайта по адресу <a href="mailto:smart-landing@ya.ru">smart-landing@ya.ru</a>';

		// Id текущей формы
		let form = $('#' + $(this).attr('id'))[0];

		// h2 с ответом формы
		let formRespond = $(this).find('.g-form__title_respond');

		// h2 с заголовком формы
		let formTitle = $(this).find('.g-form__title_main');

		// Блок прелоадера
		let preloader = $(this).find('.g-form__preloader');

		// Кнопка отправки формы
		let submitButton = $(this).find('.g-form__button');


		// FormData
		let fd = new FormData(form);


		$.ajax({

			url: appLink,
			type: "POST",
			data: fd,
			processData: false,
			contentType: false,
			beforeSend: function(){

				if(fd.get('honeypot').length) {
					return false;
				} else {
					fd.delete('honeypot');
				}

  		// Показываем прелоадер
  		preloader.css('opacity', '1');

  		// Делаем неактивной кнопку отправки
  		submitButton.prop('disabled', true);

  		// валидация других полей.

  	},

  }).done(function(res, textStatus, jqXHR) {

  	if(jqXHR.readyState === 4 && jqXHR.status === 200) {

		// Прячем заголовок формы
		formTitle.css({
			'display': 'none'
		});

		// Прячем прелоадер
		preloader.css('opacity', '0');

		// Выводим ответ формы.
		formRespond.html(successRespond).css('color', '#37b599');
		
		// Возвращаем активность кнопке отправки
		submitButton.prop('disabled', false);

	  	// Очищаем поля формы
	  	form.reset();

	  } else {
	  	formTitle.css({
	  		'display': 'none'
	  	});
	  	formRespond.html(errorRespond).css('color', '#c64b4b');
	  	preloader.css('opacity', '0');
	  	setTimeout( () => {
	  		formRespond.css({
	  			'display': 'none'
	  		});
	  		formTitle.css({
	  			'display': 'block'
	  		});

	  		submitButton.prop('disabled', false);
	  	}, 5000);

	  	console.log('Гугл не ответил статусом 200');
	  }
	}).fail(function(res, textStatus, jqXHR) {
		formTitle.css({
			'display': 'none'
		});
		preloader.css('opacity', '0');
		formRespond.html('Не удалось отправить сообщение. Cвяжитесь с администратором сайта другим способом').css('color', '#c64b4b');
		setTimeout( () => {
			formRespond.css({
				'display': 'none'
			});
			formTitle.css({
				'display': 'block'
			});
			submitButton.prop('disabled', false); 
		}, 5000);

		console.log('Не удалось выполнить запрос по указанному в скрипте пути');
	}); 
});
}(jQuery));

Итак, appLink — это ссылка, которую мы получили выше. Помните, я просил вас сохранить ее в текстовый файл, когда мы публиковали скрипт как веб приложение в редакторе скриптов таблиц? Сейчас она нам пригодится. Именно ее передаем в качестве значение для переменной appLink.

let appLink = "https://script.google.com/macros/s/AKfycbx3uFo3Z3UZcwAcJrAng4vvCzDmr2YHGCGWAUkI/exec";

В остальном, вроде бы достаточно подробно прокомментировал код. Вот например:

// Сообщение при успешной отправке данных
let successRespond = 'Сообщение успешно отправлено. Посмотрите результат <a target="_blank" href="https://docs.google.com/spreadsheets/d/1XcTivCQL4EZJf1x2kB4UwGj5bAi0sfpx1PwtaKgOWHo/edit?usp=sharing">тут</a>';

// Сообщение при ошибке в отправке данных
let errorRespond = 'Не удалось отправить сообщение. Cвяжитесь с администратором сайта по адресу <a href="mailto:smart-landing@ya.ru">smart-landing@ya.ru</a>';

Не забудьте подставить туда свой текст. Если будут вопросы по остальной логике скрипта, спрашивайте в комментариях. Постараюсь объяснить.

Дополнительные моменты

Если у вас свой обработчик и вы не хотите получать письма на почту дважды, то закомментируйте эту строку:

var TO_ADDRESS = "test@ya.ru";

В редакторе скриптов Гугл таблиц.

Если нужно еще какие-то пояснения или, более глубокое объяснение, то пишите в комментариях, буем разбираться, и я дополню статью.

Скрипт отправки данных формы в Гугл таблицу

Размер: 0,009 мб

Похожие публикации

75 комментариев

  1. Лёха

    Здравствуй, Дима. Спасибо за статью, действительно в русскоязычном интернете либо безбожно устарела информация и в консоли выводится ошибка, связанная с CORS, либо они не работают. Твое решение помогло.

    Знаю, что не в тему, но не мог бы ты сделать подобную интеграцию с Трелло и Слак? Заранее спасибо.

  2. Дмитрий

    Чую я, что эта статья не просто так тут появилась. Видимо, в следующей версии корзины для лендинга мы получим возможность отправлять данные не только через phpmailer, но и в Google Sheets.

    Я прав? :)

  3. Дмитрий

    Кстати, если появится интеграция с Google Sheets, то через IFTTT и Zapier можно будет интегрироваться и со Slack, Trello, Telegram и т.д.

    1. Дмитрий Давыдов

      Дмитрий, идеи внедрить связь с таблицами конечно же есть для всех скриптов, которые делаю. Корзина, колесо фортуны, smartlid и в новых, которые только в планах. Так что, да, вы правы)))

  4. Дмитрий

    Отлично! Я поддерживаю эти идеи, потому что на просторах интернета мало скриптов корзины, которые работают только на фронте, без php и т.д. в любых проявлениях.

  5. Андрей

    А как сделать чтобы поступали контакты, которые не отправили заявку, но заполнили поля формы??

    1. Дмитрий

      Андрей, скорее всего надо писать скрипт на js, который активирует нажатие кнопки, после какого-то триггера (промежуток времени, прокручивание страницы и т.д.)

  6. Андрей

    Дмитрий, здравствуйте! Вы можете реализовать ещё и дополнительно загрузку файлов на Google Drive?

  7. Ирина

    Добрый день
    статья классная!
    но!
    когда сама создаю таблицу, все отлично работает
    когда заказчик по инструкции - выходит ошибка
    Access to XMLHttpRequest at 'https://script.google.com/a/macros/s/...' from origin 'https://site.kz' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    POST https://script.google.com/a/macros/s/... net::ERR_FAILED

  8. Дмитрий

    Ирина, а клиент дал все разрешения на использования скриптов и т.д.?

    1. Ирина

      А как и где он должен дать? Где то в настройках таблицы?

    2. Дмитрий Давыдов

      Ирина, проще тогда попросить доступ и настроить все, чем объяснять заказчику далёкие для него термины.

  9. Владимир

    А можно передать в таблицу с формы картинку?

    1. Дмитрий Давыдов

      Владимир, Андрей, я же честно в статье признался, что код не мой и я не разобрался с АПИ и всеми его возможностями. Просто чуть адаптировал чужой труд под свои нужды и поделился этим в блоге. Наверняка можно и в Google диск или в таблицу передать и картинку, но как это сделать - я не вникал. В любом случае это не дело 2х строк, нужно садиться и разбираться в вопросе. Задал вопрос на qna, подписывайтесь, будем следить)

  10. Станислав

    А как поменять время регистрации.
    Нужно например Московское, а туда записывается -3 часа от Москвы

    1. Ирина

      В настройках таблицы можно менять

    2. Дмитрий Давыдов

      Ирина, совершенно верно.

  11. Андрей

    Дмитрий, здравствуйте! У Вас сложилось понимание после совета Александра Иванова?

    1. Дмитрий Давыдов

      Пока только просмотрел, но не вникал. Времени нет сейчас.

  12. Игорь

    Добрый день, помогите пожалуйста это все настроить. Свяжитесь пожалуйста со мной, это очень срочно. мой email.

    1. Дмитрий Давыдов

      Игорь, здравствуйте. Сайт не на конструкторе или CMS?

  13. Alex

    Как сменить русский текст "Заполните это поле"?

  14. Денис

    Добрый день. Спасибо большое за статью.
    Может знаете, как добавить в таблицу еще и адрес сайта с которого отправили форму. У меня есть ряд лендингов и хотелось бы не создавать под каждый таблицу, а видеть в одной таблице с какого URL пришла заявка?
    Еще раз огромное спасибо за проделанную работу.

    1. Дмитрий Давыдов

      Денис, здраствуйте. Получить адрес текущей страницы можно так:

      window.location.href 

      Потом можно просто поместить его в параметр value у поля.

  15. Денис

    Спасибо!

  16. Ирина

    Добрый день
    а чем отличается ваша таблица (которую нужно скопировать) от обычной таблицы?
    кроме кода в редакторе скриптов и заголовков в самой таблице

  17. Денис

    Добрый день ,а можно к уже имеющиеся форме на сайте привязать скрипт, что данные из формы попадали в таблицу.

    1. Дмитрий Давыдов

      Денис, конечно можно. После успешной отправки на почту, сделайте отправку в таблицу.

  18. Edward

    Видимо,лавочка прикрыта

    1. Дмитрий Давыдов

      Edward, почему? Все работает... проверил.

    2. Іван

      Edward, все працює

    3. Дмитрий Давыдов

      Іван, супер. радий допомогти. Якщо виникнуь питання - пишіть.

  19. Александр

    SQL_ADD_WORK(type_work, rayon_work, street_work, adres_work, phone_work, fio_work, work_work);

    где бы в коде не вставлял запрос он не выполняеться в чем может быть проблема??

  20. Ignat

    не работает

    1. Дмитрий Давыдов

      Ignat, в смысле? Уже после ваше комментария есть записи в таблицу. Откройте демо, отправьте форму для теста и перейдите в таблицу, чтобы убедится, что данные там.

  21. Иван

    Подскажите в чем может быть проблема, прикрутил скрипт к трем формам на сайте, когда оставляю заявку через одну форму, приходит три строки в гугл таблицы

    1. Дмитрий Давыдов

      Иван, id у форм разный?

  22. Иван

    Уже разобрался, везде одинаковый стоял, спасибо большое =) все работает !

    1. Дмитрий Давыдов

      Иван, отлично)

    2. Владимир

      Иван, добрый день!
      Подскажите как вы решили проблему? Я меняю ID у формы (то есть у двух форм разные ID), но все равно приходят столько форм на сайте?

  23. Іван

    Дуже допоміг. Дякую! Супер те що треба. Все працює.

  24. Den

    Как разместить 2 формы на странице, подскажите пожалуйста.

    1. Дмитрий Давыдов

      Здравствуйте. Укажите 2 разных id.

  25. artem

    А развес строка с переменной appLink должна размещаться в js файле, который может посмотреть любой в редакторе браузера?

    1. Ванёк

      artem, здравствуйте, а какая в этом опасность? Пусть смотрят.

  26. Den

    При 2х формах на странице как отдавать разный successRespond?

    1. Дмитрий Давыдов

      Den, разный Id у форм должен быть. Или разный, в плане разный текст выводить? Тогда все равно определять Id и в зависимости от того, какой он показывать разный текст.

  27. Андрей

    Здравствуйте! Спасибо большое за статью! Все получилось. Подскажите пожалуйста, нижнее поле от спама должно быть скрыто, у меня оно отображается, как можно его скрыть Спасибо)

    1. Дмитрий Давыдов

      Здравствуйте. Задайте ему type="hidden"

  28. Андрей

    Спасибо огромное)))

  29. Андрей

    Дмитрий, если не затруднит, подскажите пожалуйста, почему-то когда скрип установлен на popup - не работает, происходит отправка поля - время, остальные поля не отправляются и не происходит очищение формы. Спасибо)))

    1. Дмитрий Давыдов

      Я не знаю даже. Нужно смотреть ошибки в консоли браузера. По идее модальное окно никак не должно влиять на работу формы. С очищением та же ситуация. Возможно данные в окне подгружаются ajaxом и какой-то конфликт из-за этого, но нужно разбираться тогда. Так, сходу - не подскажу.

  30. Евгений

    Странно. Если скопировать гоогловский скрипт в свою новую таблицу то он перестаёт добавлять в неё данные. Если делаешь копию, как в инструкции, то всё работает. В чём фишка? Как мне подключить скрипт к произвольной таблице?

    1. Дмитрий Давыдов

      Евгений, да она и так произвольная, удалите данные, пишите свои. Если нужно совсем свою таблицу, то в "Редактор скриптов" зайдите, настройте под свои нужды все.

  31. Егор

    Дмитрий здравствуйте, классная работа! Я сделал, что бы открывалась страница благодарности после отправки формы. Но я так понимаю, что и за AJAX это происходит с задержкой в 3-5 секунд, что как бы не камильфо!
    Можно как то сделать, что бы не через AJAX срабатывало? Или же как можно в обработчике PHP прописать этот код AJAX, что бы он отрабатывал после того как клиенту покажется страница благодарности?

  32. Егор

    Все, отбой по вопросу! Нашел ответ в своем же вопросе! Вот так бывает...
    Ну все равно, Дмитрий спасибо за ваши труды, и за то, что делитись!

    1. Дмитрий Давыдов

      Егор, отлично))

  33. Дмитрий

    Дмитрий Давыдов, добрый день и спасибо за Ваш труд. Есть вопрос относительно сотрудничества. Нам нужна помощь специалиста по работе с данных в гугл таблицах и написанию скриптов к ним. Если вас заинтересует сотрудничество, напишите, пожалуйста. Я преставляю один из крупнейших ВУЗов России.

    1. Дмитрий Давыдов

      Дмитрий, здравствуйте. Ух, спасибо за предложение, но я не селен прям в написании скриптов к ним. Нужно было решить конкретную задачу и я искал подход. Не эксперт в этом совсем.

  34. WS

    А нет, извиняюсь))) заработала!
    Можно Вам вопрос, Дмитрий? А как на одной табличке несколько листов с формами сделать? Или одна табличка- один лист/форма только?

    1. Дмитрий Давыдов

      WS, Здравствуй, честно говоря я не в курсе даже как это реализовать. Делал только чтобы в несколько разных таблиц приходило, а как постранично делить - не знаю. Не смогу помочь.

  35. Роман

    Скачал ваш архив поменял ссылку на таблицу. В таблицу приходит две одинаковые строки с интервалом в 5-10 секунд

  36. WS

    Дмитрий, а не подскажете, как выбор значения в выпадающем списке сделать в этом же дизайне? ( )

    1. Дмитрий Давыдов

      Либо использовать jquery-библиотеку для этих целей, например эту, либо сделать самому, например, на div-ах аналогичный блок, а интерактивность при помощи JS. В стандартном элементе выпадающего списка (sekect) практически ничего нельзя стилизовать.

  37. Владимир

    Добрый день. При нажатии на кнопку отправки просто перезагружается страница. В чем может быть проблема?

    1. Дмитрий Давыдов

      Владимир, может js файл не подключили, может про preventDefault забыли, может let appLink неправильно задали.

  38. Майрамбек

    Здравствуйте!
    пишет: Не удалось найти функцию скрипта: doGet
    (после нажатии на кнопку "разрешить")

  39. Марат

    Не понимаю что делаю не так! let appLink указал , через лайв сервер заполняю форму и пишет что то не так свяжитес.... данные таблицы тоже поменял

  40. Владимир

    Здравствуйте!
    Заметил что если открыть сайт в режиме инкогнито, то в форму ничего не прилетает, только если сам себе отправляю заполненную на сайте форму. В чем может быть проблема?
    Заранее благодарю!

  41. Андрей

    Привет! Спасибо за статью, взял за основу и родил это

    function doGet(e){
      const sheet = SpreadsheetApp.getActiveSheet();
    let n=sheet.getLastRow()+1;
    const d = new Date();
      sheet.getRange("A"+n).setValue(e.parameter.p1);
      sheet.getRange("B"+n).setValue(e.parameter.p2);
      sheet.getRange("C"+n).setValue(e.parameter.p3);
      sheet.getRange("D"+n).setValue(d);
    }

    Скрипт написан на коленке, но для моих задач подходит, utm параметрами p1, p2, p3 передаются данные, можно расширить при необходимости
    https://script.google.com/macros/s/ИДЕНТИФИКАТОР_РАЗВЕРТЫВНИЯ/exec?p1=1&p2=An&p3=rrree@mail.ru

    1. Дмитрий Давыдов

      Привет. Спасибо, что поделился.

  42. Владимир

    Добрый день!
    Подскажите, почему приходит в таблицу с одной формы 2 одинаковых заполненных формы? ID у форм поменял

    и

    При этом когда заполняешь форму с id="22222" (она ниже на леднинге), то прив талбицу записываются данные только 1 раз.

    1. Дмитрий Давыдов

      Владимир, такого не должно быть, если id уникальный. Также, проверьте консоль браузера на наличие ошибок и предупреждений и, можете попробовать другую версию jquery.

  43. Сергей

    Всё работает отлично! Спасибо!

  44. Владимир

    Что то не работает,выдает вот такую ошибку

    Не удалось найти функцию скрипта: doGet

Добавить комментарий