Skip to main content

Overview

All RSVP responses are stored in a Google Sheet identified by the SHEET_ID constant in google-apps-script.js. Within that spreadsheet, every submission is written as a new row in the RSVP_responses tab. No database, no third-party storage service — the sheet acts as the persistent store and is directly accessible from any Google account with edit access.
Each time the Apps Script is re-deployed as a Web App, Google generates a new deployment URL. After re-deploying, update the url value in script.js (the AJAX call in submitForm()) to point to the new URL, otherwise form submissions will stop working.

Sheet structure

Sheet name: RSVP_responses The sheet is created automatically by initializeSheet() if it does not already exist. Row 1 is the frozen header row; data begins at row 2.

Columns

#ColumnHeaderDescription
A1TimestampSubmission time in UTC+8, ISO format with T replaced by a space
B2nameFull name of the guest
C3relationRelationship to the couple
D4attendanceWhether the guest is attending (yes / no)
E5guestsTotal number of guests in the party
F6dietaryDietary preference ("" / 1 / 2)
G7vegetarian-mealsNumber of vegetarian meals required
H8children-seatsWhether children’s high chairs are needed (yes / no)
I9children-seats-countNumber of children’s high chairs required
J10invitationWhether a paper invitation is requested (yes / no)
K11addressMailing address for the paper invitation
L12messageMessage to the couple
M13emailGuest’s email address

Header formatting

The header row (row 1) is styled for quick visual identification:
  • Background colour: #f3701a (orange)
  • Font colour: white
  • Font weight: bold
  • Frozen: row 1 is frozen so it remains visible when scrolling
  • Borders: full borders on all header cells

Data validation rules

initializeSheet() applies dropdown validation to constrain sheet editors to expected values. The table below reflects exactly what the script configures.
ColumnHeaderAllowed valuesInvalid entries allowed?
Dattendanceyes, noNo — strictly enforced
Eguests1, 2, 3, 4, 5Yes
Crelationfriends-groom, friends-bride, otherYes
Fdietary"", 1, 2Yes
Gvegetarian-meals"", 1, 2, 3, 4, 5Yes
Hchildren-seatsyes, noYes
Ichildren-seats-count"", 1, 2, 3, 4, 5Yes
Jinvitationyes, noYes
Only the attendance column uses setAllowInvalid(false). All other validated columns use setAllowInvalid(true), meaning the dropdown is a guide but does not block non-list values (which can be submitted programmatically by the form).

Timestamps

Every row receives a Timestamp value generated at write time:
var utc8Time = new Date(new Date().getTime() + 8 * 60 * 60 * 1000);
row.push(utc8Time.toISOString().replace('T', ' ').replace('Z', ' UTC+8'));
  • Timezone: UTC+8 (Taiwan Standard Time), applied by adding the offset in milliseconds
  • Format: ISO 8601 with the T separator replaced by a space and Z replaced by UTC+8
  • Example value: 2025-10-25 17:30:00.000 UTC+8

Getting RSVP statistics

The getRSVPStats() function reads all data rows and returns a summary object:
function getRSVPStats() {
  // returns:
  return {
    total: data.length,    // total number of RSVP responses
    attending: 0,          // count where attendance === 'yes'
    notAttending: 0,       // count where attendance === 'no'
    totalGuests: 0         // sum of guests for all attending responses
  };
}
To use it:
1

Open the Apps Script editor

In your Google Sheet, go to Extensions → Apps Script.
2

Select getRSVPStats

Choose getRSVPStats from the function dropdown at the top of the editor.
3

Run the function

Click Run and open the Execution log panel at the bottom of the page.
4

Read the result

The returned object is printed to the log: total responses, attending count, not-attending count, and total guest headcount.

Working with the sheet

Use Google Sheets’ built-in Filter feature to slice responses by attendance, relation, or date:
  1. Click any cell in the header row.
  2. Go to Data → Create a filter.
  3. Use the filter dropdowns on column D (attendance), C (relation), or A (timestamp) to narrow the view.
You can also use Data → Filter views to save named filters (e.g. “Attending”, “Friends of groom”) without affecting the view for other collaborators.

Build docs developers (and LLMs) love