Build a form-based help-desk ticket system
Convert Northwind support submissions into tracked tickets with an ID and status.
Published Jul 25, 2025
A support request that arrives as a plain email is easy to lose. There is no reference number, no status, and no quick way to see what is still open — so something always slips through, and the customer is left wondering if anyone saw it. Northwind wants every request to become a proper ticket the moment it lands.
This automation turns a Google Form into a lightweight help desk. When someone submits the form, a trigger mints a ticket ID, logs the request to a tracking sheet with a status, and emails the submitter a confirmation. No ticketing software, no licence — just a form, a sheet, and one function.
What you’ll need
- A Google Form for support requests, with fields for the submitter’s Email and a Subject (the field names must match the keys used below).
- A
Ticketssheet with the columnsid,submitter,subject,status,createdAtin row 1. - The tracking spreadsheet’s ID, set in
TICKETS_SHEET_IDbelow. - A Gmail account to send confirmations from — the script uses
GmailAppunder your authorisation.
The trigger
// The spreadsheet that holds the ticket log.
const TICKETS_SHEET_ID = '1abcTicketsId';
// Studio name used to sign the confirmation email.
const STUDIO_NAME = 'Northwind';
/**
* Runs on every form submission. Mints a ticket ID, logs the
* request to the Tickets sheet, and emails a confirmation.
*
* Wire this to the form's "On form submit" trigger.
*
* @param {Object} e The form-submit event, with namedValues.
*/
function onFormSubmit(e) {
// 1. Guard: make sure the submission has the fields we need.
if (!e || !e.namedValues || !e.namedValues.Email) {
Logger.log('Submission missing an Email field — skipped.');
return;
}
// 2. Mint a short, unique ticket ID from the current timestamp.
const id = `NW-${Date.now().toString(36).toUpperCase()}`;
// 3. Pull the submitter's email and subject from the response.
const submitter = e.namedValues.Email[0];
const subject = e.namedValues.Subject ? e.namedValues.Subject[0] : '(no subject)';
// 4. Log the new ticket as an open row.
SpreadsheetApp.openById(TICKETS_SHEET_ID).getSheets()[0]
.appendRow([id, submitter, subject, 'open', new Date()]);
// 5. Confirm receipt to the submitter.
GmailApp.sendEmail(
submitter,
`Ticket ${id} received`,
`We've logged your ticket. We'll reply within 4 working hours.\n\n` +
`— ${STUDIO_NAME}`
);
Logger.log('Logged ticket ' + id + ' for ' + submitter);
}
How it works
onFormSubmitruns automatically whenever the form is submitted, receiving an event objectewith the response innamedValues.- It first checks the submission actually has an
Emailfield — without one there is nobody to confirm to, so it logs a note and stops. - It mints a ticket ID by taking the current timestamp, converting it to base-36, and upper-casing it — short, human-readable, and unique because no two submissions share a millisecond.
- It reads the submitter’s email and the subject from
namedValues, falling back to(no subject)if the subject field is empty. - It appends a row to the
Ticketssheet with the ID, submitter, subject, a status ofopen, and the current time. - It emails the submitter a confirmation that quotes the ticket ID and sets a response expectation, signed with the studio name.
Example run
A customer submits the form with email [email protected] and subject
“Invoice PDF won’t open”. A new row appears in the Tickets sheet:
| id | submitter | subject | status | createdAt |
|---|---|---|---|---|
| NW-LZP4K9QX | [email protected] | Invoice PDF won’t open | open | 2025-07-25 09:14 |
And the customer receives:
Subject: Ticket NW-LZP4K9QX received
We’ve logged your ticket. We’ll reply within 4 working hours.
— Northwind
Support then works the sheet, changing status from open to closed as
tickets are resolved.
Trigger it
The function must be wired to the form’s submit event:
- Paste the script into the Apps Script project bound to the form (or a standalone project with access to the form).
- Open the Triggers panel (the clock icon) and click Add Trigger.
- Choose
onFormSubmit, event source From form, event type On form submit. - Save, and approve the authorisation prompt the first time.
- Submit a test response and confirm a new row appears and the email arrives.
Watch out for
- Field names must match exactly. The script reads
namedValues.EmailandnamedValues.Subject— if the form questions are named differently, those lookups returnundefined. Rename the questions or update the keys. - The ID is unique per millisecond, not globally. Two genuinely simultaneous submissions are extremely unlikely to collide, but if absolute uniqueness matters, append a short random suffix.
GmailApp.sendEmailcounts against a daily quota — 100 messages on a consumer account, more on Workspace. A sudden flood of submissions can hit it.- A confirmation goes to whatever address was typed into the form. A mistyped email simply bounces; the ticket is still logged, so support can follow up.
- This logs and acknowledges tickets but does not assign or escalate them. Add an assignee column and a follow-up script if you need routing or SLA chasing.
Related
Trigger an onboarding sequence on form submit
Kick off tasks when a new Northwind hire submits their starter form.
Updated Oct 17, 2025
Build a content-submission queue
Collect Northwind guest posts or ideas for review through a Form.
Updated Oct 9, 2025
Score sentiment in open-text feedback
Rate Northwind feedback comments without manual review — using the in-Sheet sentiment function.
Updated Oct 5, 2025
Build a peer-nomination and voting system
Collect and tally Northwind nominations for awards or initiatives — one ballot, anonymous.
Updated Oct 1, 2025
Roll a form over each cycle
Archive old responses and reset for the next Northwind cycle — quarterly OKR check-ins.
Updated Sep 27, 2025