How to Sync Multiple Google Calendars with Apps Script [Browser-Only Setup]
Sync multiple Google Calendars with Google Apps Script
Introduction
“Work account, personal account, freelance account… My calendars are scattered everywhere and I can’t keep track of my schedule.”
If you use multiple Google accounts, you’ve probably experienced this frustration. While Google Calendar lets you “view” calendars from other accounts, there’s no built-in feature to consolidate them into a single unified calendar.
Google Calendar Sync is a Google Apps Script solution that solves this problem.
Account B's Calendar ──┐
Account C's Calendar ──┼──▶ Account A's Main Calendar
Account D's Calendar ──┘
This guide walks you through a browser-only setup. No command line or Node.js required.
Have a development environment ready? Check out the Clasp Version Guide for easier deployment.
Who This Guide Is For
- Users who want to set up without npm or command-line tools
- Those who prefer a browser-only workflow
- First-time Google Apps Script users
Features Overview
Automatic Sync
Runs every 15 minutes on a schedule, plus immediately when calendar events change. Once set up, it runs automatically without intervention.
Incremental Sync (Sync Token)
Uses Google Calendar’s Sync Token to fetch only changed events. No need to retrieve all events every time, significantly reducing API quota usage.
Privacy Modes
Control how much information gets synced with three levels:
| Mode | Synced Information | Use Case |
|---|---|---|
busy | Time slots only (shows “Busy”) | Work calendar to personal account |
title-only | Title + time | Team calendar to manager |
full | All information | Between your own accounts |
Color Coding
Set different colors for each source calendar so you can tell at a glance which account an event came from.
Setup Instructions
Step 1: Share Your Calendars
For each source account (B, C, D…), do the following:
- Log in to Google Calendar
- Hover over the calendar name in the left sidebar, click ⋮ → Settings and sharing
- In “Share with specific people or groups,” click + Add people and groups
- Enter Account A’s email address
- Set permission to “See all event details”
- Click Send
Step 2: Create a GAS Project
Using Account A:
- Go to Google Apps Script
- Click New project
- Rename the project to “Calendar Sync”
Step 3: Enable Advanced Calendar API
- Click the + next to Services in the left sidebar
- Select Google Calendar API
- Click Add
Step 4: Create the Files
Create each file and copy the corresponding code from the GitHub repository:
| File Name | Description |
|---|---|
appsscript.json | Project manifest |
Config.gs | Configuration |
Code.gs | Main entry point |
SyncEngine.gs | Sync engine |
EventMapper.gs | Event transformation |
StorageManager.gs | State management |
Logger.gs | Logging utility |
Triggers.gs | Trigger management |
Utils.gs | Helper functions |
How to create files:
- In the Files section on the left, click + → Script
- Enter the file name (
.gsis added automatically) - Copy and paste the contents from the GitHub repository
To edit appsscript.json:
- Click Project Settings (gear icon)
- Check Show “appsscript.json” manifest file in editor
appsscript.jsonwill appear in the left sidebar - click to edit
Step 5: Edit Configuration
Open Config.gs and change calendarId to actual email addresses:
sourceCalendars: [
{
calendarId: 'your-actual-account@gmail.com', // ← Change to actual email
label: 'Account B',
privacyMode: 'busy',
enabled: true,
colorId: '1'
}
// Add more entries for additional accounts
]
For multiple accounts:
sourceCalendars: [
{
calendarId: 'account-b@gmail.com',
label: 'Account B',
privacyMode: 'busy',
enabled: true,
colorId: '1'
},
{ // ← Don't forget the comma
calendarId: 'account-c@gmail.com',
label: 'Account C',
privacyMode: 'title-only',
enabled: true,
colorId: '2'
}
]
Step 6: Validate and Grant Permissions
- Select
validateSetupfrom the Select function dropdown - Click the Run button
- When prompted for permissions:
- Click Review Permissions
- Select your Google account
- Click Advanced → Go to [Project Name] (unsafe)
- Click Allow
- Check the execution log to verify all calendars show “Accessible”
Step 7: Set Up Triggers
- Select
setupTriggersfrom the Select function dropdown - Click Run
- Verify triggers were created in the execution log
Step 8: Initial Sync
- Select
manualSyncfrom the Select function dropdown - Click Run
- Verify events appear in Account A’s calendar
Configuration Options
Privacy Modes
| Mode | Display |
|---|---|
busy | Shows “[Label] Busy” only |
title-only | Title and time only (no description/location) |
full | Copies all information |
Color IDs
| ID | Color |
|---|---|
| 1 | Lavender |
| 2 | Sage |
| 3 | Grape |
| 4 | Flamingo |
| 5 | Banana |
| 6 | Tangerine |
| 7 | Peacock |
| 8 | Graphite |
| 9 | Blueberry |
| 10 | Basil |
| 11 | Tomato |
Operations & Maintenance
Available Functions
| Function | Description |
|---|---|
manualSync() | Run sync manually |
validateSetup() | Validate settings and access |
setupTriggers() | Set up automatic triggers |
clearTriggers() | Remove all triggers |
showStatus() | Show sync status |
forceFullSync() | Run full sync for all calendars |
resetAllData() | Reset all sync data |
removeAllSyncedEvents() | Delete all synced events |
Troubleshooting
Cannot Access Calendar
- Verify the calendar is properly shared from the source account
- Check if Account A has subscribed to the calendar (Calendar > Other calendars > Subscribe)
- Verify the calendar ID in
Config.gsis correct
Sync Not Working
- Run
showStatus()to check status - Verify triggers are configured
- Check execution logs for errors
Sync Token Error
sync token invalidated, running full sync
This is normal behavior. It means Google reset the token, so the script fell back to a full sync.
Quotas and Limits
| Item | Limit | Mitigation |
|---|---|---|
| Event creation/day | 5,000 | Minimized with incremental sync |
| Script execution time | 6 min | Handled with pagination |
| Trigger time/day | 90 min | Efficient with sync tokens |
Technical Details
A brief explanation of what happens behind the scenes.
Incremental Sync with Sync Tokens
Google Calendar issues a Sync Token each time you fetch the event list. Pass this token on the next sync, and only events changed since the last fetch are returned.
This eliminates the need to fetch and compare all events every time, reducing API quota usage by over 90%. Tokens expire after a period (typically ~7 days), but the script automatically falls back to a full scan when this happens.
Event Mapping
Synced events include metadata linking them to their source events. This enables:
- Source event updated → Destination automatically updated
- Source event deleted → Destination automatically deleted
- Destination event accidentally deleted → Recreated on next sync
This ensures consistent state management.
Dual Trigger Strategy
Two types of triggers work together to balance real-time responsiveness with reliability:
| Trigger | Advantage | Disadvantage |
|---|---|---|
| Calendar trigger | Fires immediately (<1 min) | May fail due to permissions |
| 15-minute timer | Reliable execution | Up to 15-min delay |
Usually syncs immediately, with guaranteed recovery within 15 minutes if anything fails.
Summary
Google Calendar Sync lets you consolidate calendars scattered across multiple Google accounts into one.
- Share calendars from source accounts
- Create a GAS project
- Copy and paste the files
- Configure source calendars in Config.gs
- Run initial sync
Once set up, sync runs automatically. If you’re struggling to manage too many calendars, give it a try.
Source Code
Sync multiple Google Calendars with Google Apps Script