A PowerShell script that uses GAM7 to automatically subscribe Google Group members to one or more Google Calendars. Group membership is resolved recursively, so users in nested child groups are included. Each group can be mapped to its own set of calendars.
- PowerShell 5.x
- GAM7 installed and configured with appropriate Google Workspace admin credentials
- Windows (uses Windows Event Log for logging)
Ensure GAM7 is installed and authorized for your Google Workspace domain before using this script. GAM7 must be accessible on the PATH of whichever account runs the script (including the service account used by Task Scheduler, if applicable).
See the GAM7 installation guide for details.
Run the script with the -Config flag to launch the interactive configuration menu:
.\Deploy-GroupCalendars.ps1 -ConfigUse the menu to add one or more Google Groups and Calendars, or to manage the State. The config is saved as config.json in the same directory as the script.
{
"DeployDays": "7",
"Groups": [
{
"Email": "[email protected]",
"Label": "Group 1",
"CalendarIds": [
"[email protected]"
]
},
{
"Email": "[email protected]",
"Label": "Group 2",
"CalendarIds": [
"[email protected]",
"[email protected]"
]
}
],
"Calendars": [
{
"Id": "[email protected]",
"Label": "Events"
},
{
"Id": "[email protected]",
"Label": "Conference Room"
},
{
"Id": "[email protected]",
"Label": "Party Planning Committee"
}
]
}Each group maps to its own list of calendars via CalendarIds. A calendar can be linked to multiple groups. The top-level Calendars array is the shared pool that groups reference from by ID.
DeployDays are also set in the config.json, this refers to how many days should be deferred for deployment. More about DeployDays and State below, in How It Works.
.\Deploy-GroupCalendars.ps1.\Deploy-GroupCalendars.ps1 -Config.\Deploy-GroupCalendars.ps1 -ConfigPath "C:\Scripts\my-config.json"| Parameter | Type | Default | Description |
|---|---|---|---|
-Config |
Switch | — | Launches the interactive config menu |
-ConfigPath |
String | .\config.json |
Path to the config file |
-AppTitle |
String | Deploy-CalendarSubscriptions |
Used as the Windows Event Log source name and in the Config Menu |
-StateDir |
String | .\state |
Directory to store state files per group. These files are used to filter out users and calendars recently deployed |
For each Group defined in config.json, the script:
- Resolves which calendars are linked to that group via
CalendarIds - Calls GAM7 to fetch all user members of the group, recursively resolving any nested child groups (
recursive types user) - Validates that at least one user was returned
- Compares the list of users and calendars against that group's state file (stored in
.\stateby default), filtering out users below the SyncDays threshold - For each linked calendar, calls GAM7 to add the calendar to each user's account with
selected true(visible by default)
State allows admin to configure a set number of days to defer deployment for all users. This can help cut down on GAM calls, especially with large groups with relatively stable membership. The deployment process will save a list (a state file) of users and calendar relationships for each group, along with a timestamp. When it pulls down the latest group members into a temp CSV, it will compare that membership against that state file. Deployment will run for any new members or members outside of the DeployDays threshold. Other members will be skipped. If needed, the state file can be deleted and rebuilt on the next deployment run. If GAM hits a snag, the state file will save where it had left off, and will catch up the deployment on the next scheduled run.
FYI
- If a user is a member of multiple nested child groups within the same parent, they may appear more than once in the member list. This does not cause problems but will be reflected in the logged user count.
- Groups with no linked calendars are skipped, logging a warning.
- If a user is already subscribed to a calendar, GAM7's
add calendaris idempotent — it will not create duplicates or throw an error.
All activity is written to the Windows Event Log under Application with the source Deploy-GroupCalendars (or whatever -AppTitle is set to).
| Event | Level |
|---|---|
| Deploy started for a group | Information |
| User count found | Information |
| Calendar being processed | Information |
| Deploy complete for a group | Information |
| No members found / group missing | Error |
| Any unhandled exception | Error |
To view logs:
Event Viewer → Windows Logs → Application → Source: Deploy-GroupCalendars
First run: Creating a new Event Log source requires administrator privileges. If the script is not run as an administrator on first use, it will fall back to
Write-Outputfor that session. Run once as administrator (or pre-register the source) to initialize it permanently.
New-EventLog -LogName Application -Source "Deploy-GroupCalendars"To run on a schedule, create a Task Scheduler job that calls:
Program: powershell.exe
Arguments: -NonInteractive -ExecutionPolicy Bypass -Command "& 'C:\Scripts\Deploy-CalendarSubscriptions\Deploy-CalendarSubscriptions.ps1'"
Make sure this points to the script on your own system!
Ensure the task runs under an account that has:
- GAM7 on its
PATH - GAM7 credentials configured for that user profile
- Permission to write to the Windows Event Log (or the source pre-registered by an admin)
Deploy-CalendarSubscriptions/
├── Deploy-CalendarSubscriptions.ps1
├── config.json
├── README.md
└── state/
├── state-group1-domain-tld.json
└── state-group2-domain-tld.json