/** * MoreminiMore lead form endpoint. * * Recommended setup: * 1. Create a Google Sheet for leads. * 2. Open Extensions > Apps Script. * 3. Paste this entire file into Code.gs. * 4. Update CONFIG.RECIPIENT_EMAIL. * 5. Deploy as Web app. */ const CONFIG = { RECIPIENT_EMAIL: 'contact@moreminimore.com', SHEET_NAME: 'Leads', TIMEZONE: 'Asia/Bangkok', EMAIL_SUBJECT: 'มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore', }; const PROBLEM_LABELS = { website_no_leads: 'เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก', ads_not_worth_it: 'ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม', wrong_leads: 'มีคนทักมา แต่ไม่ใช่ลูกค้าที่ใช่', slow_or_error_work: 'ทีมงานทำงานเดิม ๆ แต่ทำงานช้า หรือผิดพลาดบ่อย', ai_not_sure: 'อยากใช้ AI แต่ไม่รู้เริ่มตรงไหน', not_sure: 'ยังไม่แน่ใจว่าควรแก้อะไรก่อน', }; function doGet() { return jsonResponse({ ok: true, service: 'MoreminiMore lead form', }); } function doPost(e) { try { const data = parseRequest(e); if (isSpam(data)) { return jsonResponse({ ok: true, skipped: true }); } const lead = normalizeLead(data); const validation = validateLead(lead); if (!validation.ok) { return jsonResponse({ ok: false, error: validation.error, }); } const lock = LockService.getScriptLock(); lock.waitLock(10000); try { appendLead(lead); } finally { lock.releaseLock(); } sendLeadEmail(lead); return jsonResponse({ ok: true, message: 'Lead received', diagnosis: buildLightDiagnosis(lead.problems), }); } catch (error) { console.error(error); return jsonResponse({ ok: false, error: 'ระบบรับข้อมูลมีปัญหา กรุณาลองใหม่อีกครั้ง', }); } } function parseRequest(e) { if (!e) return {}; const contentType = String(e.postData && e.postData.type || '').toLowerCase(); const raw = e.postData && e.postData.contents; if (raw && contentType.indexOf('application/json') !== -1) { return JSON.parse(raw); } if (raw && contentType.indexOf('text/plain') !== -1) { try { return JSON.parse(raw); } catch (error) { return e.parameter || {}; } } return e.parameter || {}; } function normalizeLead(data) { const problems = normalizeProblems(data.problems || data.problem || data.problemKeys); return { createdAt: Utilities.formatDate(new Date(), CONFIG.TIMEZONE, 'yyyy-MM-dd HH:mm:ss'), name: cleanText(data.name), phone: cleanText(data.phone), email: cleanText(data.email).toLowerCase(), message: cleanText(data.message || data.details || data.note), problems, pageUrl: cleanText(data.pageUrl || data.url), userAgent: cleanText(data.userAgent), }; } function normalizeProblems(value) { if (!value) return []; if (Array.isArray(value)) { return value.map(String).map(cleanText).filter(Boolean); } return String(value) .split(',') .map(cleanText) .filter(Boolean); } function validateLead(lead) { if (!lead.name) { return { ok: false, error: 'กรุณาใส่ชื่อ' }; } if (!lead.phone && !lead.email) { return { ok: false, error: 'ใส่เบอร์โทรหรืออีเมลอย่างใดอย่างหนึ่งก็ได้' }; } if (lead.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(lead.email)) { return { ok: false, error: 'รูปแบบอีเมลไม่ถูกต้อง' }; } if (lead.message.length > 2000) { return { ok: false, error: 'รายละเอียดโจทย์ยาวเกินไป' }; } return { ok: true }; } function appendLead(lead) { const sheet = getLeadSheet(); sheet.appendRow([ lead.createdAt, lead.name, lead.phone, lead.email, problemLabels(lead.problems).join(', '), lead.message, buildLightDiagnosis(lead.problems), lead.pageUrl, lead.userAgent, ]); } function getLeadSheet() { const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); let sheet = spreadsheet.getSheetByName(CONFIG.SHEET_NAME); if (!sheet) { sheet = spreadsheet.insertSheet(CONFIG.SHEET_NAME); } if (sheet.getLastRow() === 0) { sheet.appendRow([ 'วันที่ส่ง', 'ชื่อ', 'เบอร์โทร', 'อีเมล', 'ปัญหาที่เลือก', 'รายละเอียด', 'แนวทางเริ่มต้น', 'Page URL', 'User Agent', ]); sheet.setFrozenRows(1); } return sheet; } function sendLeadEmail(lead) { const labels = problemLabels(lead.problems); const diagnosis = buildLightDiagnosis(lead.problems); const plainBody = [ 'มีโจทย์ธุรกิจใหม่จากเว็บไซต์ MoreminiMore', '', `ชื่อ: ${lead.name}`, `เบอร์โทร: ${lead.phone || '-'}`, `อีเมล: ${lead.email || '-'}`, `ปัญหาที่เลือก: ${labels.length ? labels.join(', ') : '-'}`, '', 'รายละเอียด:', lead.message || '-', '', `แนวทางเริ่มต้น: ${diagnosis}`, '', `Page URL: ${lead.pageUrl || '-'}`, `เวลาที่ส่ง: ${lead.createdAt}`, ].join('\n'); const htmlBody = `
ชื่อ: ${escapeHtml(lead.name)}
เบอร์โทร: ${escapeHtml(lead.phone || '-')}
อีเมล: ${escapeHtml(lead.email || '-')}
ปัญหาที่เลือก: ${escapeHtml(labels.length ? labels.join(', ') : '-')}
รายละเอียด:
${escapeHtml(lead.message || '-').replace(/\n/g, '
')}
แนวทางเริ่มต้น: ${escapeHtml(diagnosis)}
Page URL: ${escapeHtml(lead.pageUrl || '-')}
เวลาที่ส่ง: ${escapeHtml(lead.createdAt)}