Привет, друзья. Сегодня поговорим о том, как отправить данные из формы обратной связи на сайте в 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 комментариев
Здравствуй, Дима. Спасибо за статью, действительно в русскоязычном интернете либо безбожно устарела информация и в консоли выводится ошибка, связанная с CORS, либо они не работают. Твое решение помогло.
Знаю, что не в тему, но не мог бы ты сделать подобную интеграцию с Трелло и Слак? Заранее спасибо.
Чую я, что эта статья не просто так тут появилась. Видимо, в следующей версии корзины для лендинга мы получим возможность отправлять данные не только через phpmailer, но и в Google Sheets.
Я прав? :)
Кстати, если появится интеграция с Google Sheets, то через IFTTT и Zapier можно будет интегрироваться и со Slack, Trello, Telegram и т.д.
Дмитрий, идеи внедрить связь с таблицами конечно же есть для всех скриптов, которые делаю. Корзина, колесо фортуны, smartlid и в новых, которые только в планах. Так что, да, вы правы)))
Отлично! Я поддерживаю эти идеи, потому что на просторах интернета мало скриптов корзины, которые работают только на фронте, без php и т.д. в любых проявлениях.
А как сделать чтобы поступали контакты, которые не отправили заявку, но заполнили поля формы??
Андрей, скорее всего надо писать скрипт на js, который активирует нажатие кнопки, после какого-то триггера (промежуток времени, прокручивание страницы и т.д.)
Дмитрий, здравствуйте! Вы можете реализовать ещё и дополнительно загрузку файлов на Google Drive?
Добрый день
статья классная!
но!
когда сама создаю таблицу, все отлично работает
когда заказчик по инструкции - выходит ошибка
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
Ирина, а клиент дал все разрешения на использования скриптов и т.д.?
А как и где он должен дать? Где то в настройках таблицы?
Ирина, проще тогда попросить доступ и настроить все, чем объяснять заказчику далёкие для него термины.
А можно передать в таблицу с формы картинку?
Владимир, Андрей, я же честно в статье признался, что код не мой и я не разобрался с АПИ и всеми его возможностями. Просто чуть адаптировал чужой труд под свои нужды и поделился этим в блоге. Наверняка можно и в Google диск или в таблицу передать и картинку, но как это сделать - я не вникал. В любом случае это не дело 2х строк, нужно садиться и разбираться в вопросе. Задал вопрос на qna, подписывайтесь, будем следить)
А как поменять время регистрации.
Нужно например Московское, а туда записывается -3 часа от Москвы
В настройках таблицы можно менять
Ирина, совершенно верно.
Дмитрий, здравствуйте! У Вас сложилось понимание после совета Александра Иванова?
Пока только просмотрел, но не вникал. Времени нет сейчас.
Добрый день, помогите пожалуйста это все настроить. Свяжитесь пожалуйста со мной, это очень срочно. мой email.
Игорь, здравствуйте. Сайт не на конструкторе или CMS?
Как сменить русский текст "Заполните это поле"?
Добрый день. Спасибо большое за статью.
Может знаете, как добавить в таблицу еще и адрес сайта с которого отправили форму. У меня есть ряд лендингов и хотелось бы не создавать под каждый таблицу, а видеть в одной таблице с какого URL пришла заявка?
Еще раз огромное спасибо за проделанную работу.
Денис, здраствуйте. Получить адрес текущей страницы можно так:
Потом можно просто поместить его в параметр value у поля.
Спасибо!
Добрый день
а чем отличается ваша таблица (которую нужно скопировать) от обычной таблицы?
кроме кода в редакторе скриптов и заголовков в самой таблице
Добрый день ,а можно к уже имеющиеся форме на сайте привязать скрипт, что данные из формы попадали в таблицу.
Денис, конечно можно. После успешной отправки на почту, сделайте отправку в таблицу.
Видимо,лавочка прикрыта
Edward, почему? Все работает... проверил.
Edward, все працює
Іван, супер. радий допомогти. Якщо виникнуь питання - пишіть.
SQL_ADD_WORK(type_work, rayon_work, street_work, adres_work, phone_work, fio_work, work_work);
где бы в коде не вставлял запрос он не выполняеться в чем может быть проблема??
не работает
Ignat, в смысле? Уже после ваше комментария есть записи в таблицу. Откройте демо, отправьте форму для теста и перейдите в таблицу, чтобы убедится, что данные там.
Подскажите в чем может быть проблема, прикрутил скрипт к трем формам на сайте, когда оставляю заявку через одну форму, приходит три строки в гугл таблицы
Иван, id у форм разный?
Уже разобрался, везде одинаковый стоял, спасибо большое =) все работает !
Иван, отлично)
Иван, добрый день!
Подскажите как вы решили проблему? Я меняю ID у формы (то есть у двух форм разные ID), но все равно приходят столько форм на сайте?
Дуже допоміг. Дякую! Супер те що треба. Все працює.
Как разместить 2 формы на странице, подскажите пожалуйста.
Здравствуйте. Укажите 2 разных id.
А развес строка с переменной appLink должна размещаться в js файле, который может посмотреть любой в редакторе браузера?
artem, здравствуйте, а какая в этом опасность? Пусть смотрят.
При 2х формах на странице как отдавать разный successRespond?
Den, разный Id у форм должен быть. Или разный, в плане разный текст выводить? Тогда все равно определять Id и в зависимости от того, какой он показывать разный текст.
Здравствуйте! Спасибо большое за статью! Все получилось. Подскажите пожалуйста, нижнее поле от спама должно быть скрыто, у меня оно отображается, как можно его скрыть Спасибо)
Здравствуйте. Задайте ему type="hidden"
Спасибо огромное)))
Дмитрий, если не затруднит, подскажите пожалуйста, почему-то когда скрип установлен на popup - не работает, происходит отправка поля - время, остальные поля не отправляются и не происходит очищение формы. Спасибо)))
Я не знаю даже. Нужно смотреть ошибки в консоли браузера. По идее модальное окно никак не должно влиять на работу формы. С очищением та же ситуация. Возможно данные в окне подгружаются ajaxом и какой-то конфликт из-за этого, но нужно разбираться тогда. Так, сходу - не подскажу.
Странно. Если скопировать гоогловский скрипт в свою новую таблицу то он перестаёт добавлять в неё данные. Если делаешь копию, как в инструкции, то всё работает. В чём фишка? Как мне подключить скрипт к произвольной таблице?
Евгений, да она и так произвольная, удалите данные, пишите свои. Если нужно совсем свою таблицу, то в "Редактор скриптов" зайдите, настройте под свои нужды все.
Дмитрий здравствуйте, классная работа! Я сделал, что бы открывалась страница благодарности после отправки формы. Но я так понимаю, что и за AJAX это происходит с задержкой в 3-5 секунд, что как бы не камильфо!
Можно как то сделать, что бы не через AJAX срабатывало? Или же как можно в обработчике PHP прописать этот код AJAX, что бы он отрабатывал после того как клиенту покажется страница благодарности?
Все, отбой по вопросу! Нашел ответ в своем же вопросе! Вот так бывает...
Ну все равно, Дмитрий спасибо за ваши труды, и за то, что делитись!
Егор, отлично))
Дмитрий Давыдов, добрый день и спасибо за Ваш труд. Есть вопрос относительно сотрудничества. Нам нужна помощь специалиста по работе с данных в гугл таблицах и написанию скриптов к ним. Если вас заинтересует сотрудничество, напишите, пожалуйста. Я преставляю один из крупнейших ВУЗов России.
Дмитрий, здравствуйте. Ух, спасибо за предложение, но я не селен прям в написании скриптов к ним. Нужно было решить конкретную задачу и я искал подход. Не эксперт в этом совсем.
А нет, извиняюсь))) заработала!
Можно Вам вопрос, Дмитрий? А как на одной табличке несколько листов с формами сделать? Или одна табличка- один лист/форма только?
WS, Здравствуй, честно говоря я не в курсе даже как это реализовать. Делал только чтобы в несколько разных таблиц приходило, а как постранично делить - не знаю. Не смогу помочь.
Скачал ваш архив поменял ссылку на таблицу. В таблицу приходит две одинаковые строки с интервалом в 5-10 секунд
Дмитрий, а не подскажете, как выбор значения в выпадающем списке сделать в этом же дизайне? ( )
Либо использовать jquery-библиотеку для этих целей, например эту, либо сделать самому, например, на div-ах аналогичный блок, а интерактивность при помощи JS. В стандартном элементе выпадающего списка (sekect) практически ничего нельзя стилизовать.
Добрый день. При нажатии на кнопку отправки просто перезагружается страница. В чем может быть проблема?
Владимир, может js файл не подключили, может про preventDefault забыли, может let appLink неправильно задали.
Здравствуйте!
пишет: Не удалось найти функцию скрипта: doGet
(после нажатии на кнопку "разрешить")
Не понимаю что делаю не так! let appLink указал , через лайв сервер заполняю форму и пишет что то не так свяжитес.... данные таблицы тоже поменял
Здравствуйте!
Заметил что если открыть сайт в режиме инкогнито, то в форму ничего не прилетает, только если сам себе отправляю заполненную на сайте форму. В чем может быть проблема?
Заранее благодарю!
Привет! Спасибо за статью, взял за основу и родил это
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
Привет. Спасибо, что поделился.
Добрый день!
Подскажите, почему приходит в таблицу с одной формы 2 одинаковых заполненных формы? ID у форм поменял
и
При этом когда заполняешь форму с id="22222" (она ниже на леднинге), то прив талбицу записываются данные только 1 раз.
Владимир, такого не должно быть, если id уникальный. Также, проверьте консоль браузера на наличие ошибок и предупреждений и, можете попробовать другую версию jquery.
Всё работает отлично! Спасибо!
Что то не работает,выдает вот такую ошибку
Не удалось найти функцию скрипта: doGet