Apply attendee rules by event type
Auto-invite the right Northwind people from a Sheet — design reviews get design, client calls get account leads.
Published Oct 4, 2025
Whoever books a meeting at Northwind knows the topic but not always the cast. A design review needs the design team. A client call needs the account lead. The booker remembers the obvious people and forgets the rest, so reviews happen without a reviewer and someone gets pulled in at the last minute.
This script reads a small Sheet of rules — a keyword and the people that keyword should pull in — and applies them to the week ahead. Title an event “Design review: Castle rebrand” and the design team appears on the invite automatically. The booker only has to name the meeting sensibly; the right attendees follow from the title.
What you’ll need
- An
Attendee rulessheet with two columns:keyword(a word or phrase to look for in event titles) andattendees(a comma-separated list of email addresses to invite when that keyword matches). - Events created on your default Google Calendar with descriptive titles — the script matches on title text, so “Design review” works and “Meeting” does not.
The script
// The sheet of keyword -> attendees rules.
const ATTENDEE_RULES = '1abcAttendeeRulesId';
// How many days ahead to apply rules to.
const WINDOW_DAYS = 7;
// Event tag used to mark events we have already processed.
const APPLIED_TAG = 'attendees-applied';
/**
* Reads the attendee rules and applies them to upcoming events:
* any event whose title contains a rule's keyword gets that rule's
* attendees added as guests.
*/
function applyAttendeeRules() {
// 1. Load the rules from the Sheet.
const rules = readSheet(ATTENDEE_RULES);
if (!rules.length) {
Logger.log('No attendee rules defined — nothing to do.');
return;
}
// 2. Look at events from now to WINDOW_DAYS ahead.
const start = new Date();
const end = new Date(start.getTime() + WINDOW_DAYS * 86400000);
const events = CalendarApp.getDefaultCalendar().getEvents(start, end);
for (const event of events) {
// Skip events we have already handled on a previous run.
if (event.getTag(APPLIED_TAG) === 'yes') continue;
// 3. Test the event title against every rule's keyword.
for (const r of rules) {
if (event.getTitle().toLowerCase().includes(r.keyword.toLowerCase())) {
// 4. Add each attendee listed for the matching rule.
String(r.attendees).split(',').map((s) => s.trim()).filter(Boolean)
.forEach((g) => event.addGuest(g));
// 5. Tag the event so it is not processed again.
event.setTag(APPLIED_TAG, 'yes');
}
}
}
}
/**
* Reads the first tab of a spreadsheet into an array of objects,
* one per row, keyed by the header cells.
*/
function readSheet(id) {
const [h, ...rows] = SpreadsheetApp.openById(id).getSheets()[0].getDataRange().getValues();
return rows.map((r) => Object.fromEntries(h.map((k, i) => [k, r[i]])));
}
How it works
applyAttendeeRulesloads the rules sheet withreadSheet, which turns each row into an object keyed by the header —{ keyword, attendees }. If there are no rules, it stops.- It asks the default calendar for every event from now to
WINDOW_DAYSahead (a week by default). - For each event it skips any already carrying the
attendees-appliedtag, so a re-run does not re-invite people. - It tests the lower-cased event title against each rule’s lower-cased keyword. A match means the keyword appears anywhere in the title.
- On a match it splits the rule’s
attendeescell on commas, trims each address, and adds every one as a guest. - It then tags the event with
attendees-appliedso the next run leaves it alone.
Example run
Say the Attendee rules sheet holds:
| keyword | attendees |
|---|---|
| design review | [email protected], [email protected] |
| client call | [email protected] |
And the week ahead has these events:
| Event title | Guests added |
|---|---|
| Design review: Castle rebrand | maya, leo |
| Client call — Brightline | priya |
| Sprint planning | none (no keyword matches) |
After the run, the design review and the client call both have the right people on the invite, and each is tagged so the next run skips it.
Trigger it
Run this on a daily timer so events booked through the day pick up their attendees overnight:
- In the Apps Script editor open Triggers and click Add Trigger.
- Choose
applyAttendeeRules, set the event source to Time-driven, and pick a Day timer for early morning.
It will only ever touch events inside the next WINDOW_DAYS, and the tag
means each event is processed once.
Watch out for
- Adding a guest sends them a calendar invitation. Run this with care while testing — point it at a test calendar first so you do not spam real people.
- Keyword matching is a plain substring check, so a rule keyword of
reviewalso fires on “code review” and “peer review”. Make keywords specific. - An event can match more than one rule and collect every matching rule’s attendees — usually what you want, but worth knowing.
- Event tags survive on the event itself. If you change a rule and want it
re-applied to an already-tagged event, remove the
attendees-appliedtag from that event by hand. getEventsreturns recurring events as individual instances within the window — each instance is tagged separately.
Related
Schedule personal habits and routines
Block recurring habits on Awadesh's calendar — gym, walks, deep-work mornings.
Updated Nov 5, 2025
Sync birthdays and anniversaries to Calendar
Populate recurring personal dates from a Sheet — the Northwind team rituals calendar.
Updated Nov 1, 2025
Generate recurring events with custom exceptions
Handle complex recurrence rules in code — every Tuesday except UK bank holidays.
Updated Oct 28, 2025
Auto-reschedule low-priority conflicts
Move flexible Northwind events around fixed ones — focus blocks bend, client calls don't.
Updated Oct 16, 2025
Build a contract-renewal calendar
Track Northwind's recurring-revenue renewal dates as calendar events for proactive sales.
Updated Oct 8, 2025