9 min read

How to Sync Multiple Google Calendars with Apps Script [Clasp Version]

Google Apps Script Calendar Automation Clasp npm
khides/calender-sync-gas

Sync multiple Google Calendars with Google Apps Script

View on GitHub →

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 setting up Calendar Sync using Clasp for a modern development workflow.

Prefer a browser-only setup? Check out the Manual Setup Guide.


Who This Guide Is For

  • Users who want to understand what’s happening behind the scenes while syncing calendars
  • Developers familiar with Node.js/npm
  • Those comfortable with command-line operations

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:

ModeSynced InformationUse Case
busyTime slots only (shows “Busy”)Work calendar to personal account
title-onlyTitle + timeTeam calendar to manager
fullAll informationBetween 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

Prerequisites

  • Node.js >= 22.0.0
  • npm

Step 1: Share Your Calendars

For each source account (B, C, D…), do the following:

  1. Log in to Google Calendar
  2. Hover over the calendar name in the left sidebar, click Settings and sharing
  3. In “Share with specific people or groups,” click + Add people and groups
  4. Enter Account A’s email address
  5. Set permission to “See all event details”
  6. Click Send

Step 2: Initial Setup (Account A, one time only)

  1. Enable the Apps Script API

  2. Clone the repository and install dependencies:

git clone https://github.com/khides/calender-sync-gas.git
cd calender-sync-gas
npm install
  1. Log in with your Google account:
npm run login

Step 3: Deploy

# Create GAS project
npm run create

# Push code & enable Calendar API
npm run deploy

# Open project in browser
npm run open

Step 4: Configure and Initial Sync

npm run open opens the Apps Script editor in your browser.

4-1. Configure Source Calendars

  1. Click Config.gs in the left sidebar
  2. Change calendarId in the sourceCalendars array to actual email addresses:
calendarId: 'your-actual-account@gmail.com',  // ← Change to actual email
  1. For multiple accounts: Add entries following the commented samples
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: 'busy',
    enabled: true,
    colorId: '2'
  }
]

4-2. How to Run Functions

To run functions in the Apps Script editor:

  1. Click the function dropdown at the top (shows “Select function”)
  2. Select the function name you want to run
  3. Click the Run button (▶)
┌─────────────────────────────────────────────────────────┐
│  [Select function ▼]  [▶ Run]  [🐛 Debug]              │
│                                                         │
│  ↑ Select function here and click Run                  │
└─────────────────────────────────────────────────────────┘

4-3. Run Initial Setup

Execute these functions in order:

  1. Select validateSetup from Code.gs and run

    • First run will show authorization prompt
    • Click “Review Permissions” → Select account → “Advanced” → “Go to [Project Name] (unsafe)” → “Allow”
    • Check execution log (bottom panel) shows “Accessible” for all calendars
  2. Select setupTriggers and run

    • Sets up automatic sync triggers
  3. Select manualSync and run

    • Runs the initial sync
    • Verify events appear in Account A’s calendar

Configuration Options

Privacy Modes

ModeDisplay
busyShows “[Label] Busy” only
title-onlyTitle and time only (no description/location)
fullCopies all information

Color IDs

IDColor
1Lavender
2Sage
3Grape
4Flamingo
5Banana
6Tangerine
7Peacock
8Graphite
9Blueberry
10Basil
11Tomato

npm Scripts

CommandDescription
npm run loginLog in with Google account
npm run createCreate GAS project
npm run pushPush code
npm run deployPush + enable API
npm run openOpen editor in browser
npm run watchWatch files and auto-push changes

Operations & Maintenance

Available Functions

FunctionDescription
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

  1. Verify the calendar is properly shared from the source account
  2. Check if Account A has subscribed to the calendar (Calendar > Other calendars > Subscribe)
  3. Verify the calendar ID in Config.gs is correct

Sync Not Working

  1. Run showStatus() to check status
  2. Verify triggers are configured
  3. 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

ItemLimitMitigation
Event creation/day5,000Minimized with incremental sync
Script execution time6 minHandled with pagination
Trigger time/day90 minEfficient 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:

TriggerAdvantageDisadvantage
Calendar triggerFires immediately (<1 min)May fail due to permissions
15-minute timerReliable executionUp 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.

  1. Share calendars from source accounts
  2. Deploy with Clasp
  3. Configure source calendars in Config.gs
  4. Run initial sync

Once set up, sync runs automatically. If you’re struggling to manage too many calendars, give it a try.


Source Code

khides/calender-sync-gas

Sync multiple Google Calendars with Google Apps Script

View on GitHub →