Concept
Setup
- Create a Google Form, e.g. Repair Request with questions: Name, Email, Phone, Item, Problem.
- In the form: Responses → Link to Sheets → create a new spreadsheet.
- Open that spreadsheet → Extensions → Apps Script (a bound script on the response sheet).
Each submission adds a row to the Form Responses 1 tab: Timestamp first, then answers in question order.
The form-submit event
Create an installable trigger:
function setupFormTrigger() {
ScriptApp.newTrigger('onFormSubmitHandler')
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
When a response arrives, the handler receives e:
function onFormSubmitHandler(e) {
console.log(e.values); // ['10/10/2026 14:05:11', 'Rahul', 'rahul@example.com', ...]
console.log(e.namedValues); // { 'Name': ['Rahul'], 'Email': ['rahul@example.com'], ... }
console.log(e.range.getRow()); // the row just added
}
Prefer e.namedValues — it uses question titles, so reordering questions in the form doesn't break your code. Note each value is inside an array: e.namedValues['Name'][0].
Auto-reply email
function onFormSubmitHandler(e) {
const get = q => (e.namedValues[q] ? e.namedValues[q][0] : '').trim();
const name = get('Name');
const email = get('Email');
const item = get('Item');
if (!email) return;
const body =
`Dear ${name},\n\n` +
`We have received your repair request for: ${item}.\n` +
`Our team will contact you within 24 hours.\n\n` +
`Thank you,\nService Desk`;
MailApp.sendEmail(email, 'We received your request', body);
}
Add a ticket ID and status
Write extra columns to the right of the form's columns. Form columns: A Timestamp, B Name, C Email, D Phone, E Item, F Problem → we use G (Ticket ID) and H (Status).
function onFormSubmitHandler(e) {
const sheet = e.range.getSheet();
const row = e.range.getRow();
const ticketId = 'REP-' + String(row - 1).padStart(4, '0'); // REP-0001, REP-0002 ...
sheet.getRange(row, 7, 1, 2).setValues([[ticketId, 'New']]);
const email = (e.namedValues['Email'] || [''])[0];
if (email) {
MailApp.sendEmail(email, `Request ${ticketId} received`,
`Your ticket number is ${ticketId}. Please quote it when you call us.`);
}
// Alert the shop
MailApp.sendEmail('service@example.com', `New request ${ticketId}`,
Object.entries(e.namedValues).map(([q, a]) => `${q}: ${a[0]}`).join('\n'));
}
Tip: don't insert columns between the form's columns — Google Forms writes by position and new questions get added at the end. Keep your own columns to the right, or keep the raw responses tab untouched and copy rows to a separate working tab.
Handling duplicate triggers
Occasionally the same submission can fire the trigger twice. If that matters (e.g. you send SMS or create invoices), check before acting:
if (sheet.getRange(row, 7).getValue()) return; // ticket already assigned
Key points
- Use an installable onFormSubmit trigger on the response spreadsheet.
e.namedValues['Question'][0]is the safest way to read answers.- Add your own columns to the right of the form's columns.