/** * Apps Script — endpoint для приёма лидов с формы «Человек будущего». * * Как подключить (Маргарита): * 1. Создаёшь новый Google Sheet, называешь например «Реалити Человек Будущего — лиды». * 2. Расширения → Apps Script → вставляешь этот код в Code.gs. * 3. Развернуть → Новое развёртывание → тип «Веб-приложение». * Доступ: «У кого есть ссылка», от имени «Меня». * 4. Копируешь полученный URL вида https://script.google.com/macros/s/AKfy.../exec * 5. Подставляешь его в form.html в константу SHEET_ENDPOINT (раздел script.config). * * Структура листа (создастся автоматически при первом запросе): * timestamp | name | occupation | level | mode | country_code | phone | phone_full | * tg_user_id | tg_username | ig_psid | source | codeword | utm_source | utm_medium | * utm_campaign | user_agent | ip | segments * * Колонка "segments" — вычисляется на лету для удобной фильтрации. * Примеры значений: "hero/just-looking", "viewer/regular", "hero/advanced+expert" */ const SHEET_NAME = 'Лиды'; const HEADERS = [ 'timestamp', 'name', 'occupation', 'level', 'level_group', 'icp', 'scenario', 'mode', 'country_code', 'phone', 'phone_full', 'tg_user_id', 'tg_username', 'ig_psid', 'source', 'codeword', 'utm_source', 'utm_medium', 'utm_campaign', 'consent_pd', 'consent_marketing', 'user_agent', 'ip', 'segments' ]; function doPost(e) { try { const data = JSON.parse(e.postData.contents); const sheet = getOrCreateSheet_(); const segments = buildSegments_(data); const row = [ new Date(), data.name || '', data.occupation || '', data.level || '', data.level_group || '', data.icp || '', data.scenario || '', data.mode || '', data.country_code || '', data.phone || '', (data.country_code || '') + (data.phone || ''), data.tg_user_id || '', data.tg_username || '', data.ig_psid || '', data.source || '', data.codeword || '', data.utm_source || '', data.utm_medium || '', data.utm_campaign || '', data.consent ? 'yes' : 'no', data.consent_marketing ? 'yes' : 'no', data.user_agent || '', data.ip || '', segments ]; sheet.appendRow(row); // Дублируем в "Зеркало" (на случай повреждения основного листа) try { const mirror = getOrCreateSheet_('Зеркало'); mirror.appendRow(row); } catch (mirrorErr) { // Молча, зеркало некритично } return jsonResponse_({ ok: true, segments: segments }); } catch (err) { return jsonResponse_({ ok: false, error: String(err) }); } } function doGet() { return jsonResponse_({ ok: true, hint: 'POST JSON to this endpoint' }); } function buildSegments_(data) { const parts = []; if (data.mode) parts.push(data.mode); if (data.scenario) parts.push(data.scenario); // например viewer/novice_seller return parts.join('/'); } function getOrCreateSheet_(name) { const sheetName = name || SHEET_NAME; const ss = SpreadsheetApp.getActiveSpreadsheet(); let sheet = ss.getSheetByName(sheetName); if (!sheet) { sheet = ss.insertSheet(sheetName); sheet.appendRow(HEADERS); sheet.getRange(1, 1, 1, HEADERS.length).setFontWeight('bold'); sheet.setFrozenRows(1); } return sheet; } function jsonResponse_(obj) { return ContentService .createTextOutput(JSON.stringify(obj)) .setMimeType(ContentService.MimeType.JSON); } /** * Утилита: выгрузить сегмент в JSON для Telethon-рассылки. * Вызывается вручную из Apps Script editor. * * Допустимые значения level (8 сегментов): * novichok, seller, mama, ekspert, spets-uslug, za-rubezh, skeptik, na-volne * * Пример: exportSegment("viewer", "novichok") — все новички среди зрителей. */ function exportSegment(mode, level) { const sheet = getOrCreateSheet_(); const values = sheet.getDataRange().getValues(); const headers = values.shift(); const idxMode = headers.indexOf('mode'); const idxLevel = headers.indexOf('level'); const idxTg = headers.indexOf('tg_user_id'); const idxName = headers.indexOf('name'); const idxPhone = headers.indexOf('phone_full'); const filtered = values .filter(r => (!mode || r[idxMode] === mode) && (!level || r[idxLevel] === level)) .map(r => ({ name: r[idxName], tg_user_id: r[idxTg], phone: r[idxPhone], mode: r[idxMode], level: r[idxLevel] })); Logger.log(JSON.stringify(filtered, null, 2)); return filtered; }