A PowerShell bundle 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)
Deploy-CalendarSubscriptions/
├── Modules/
│ └── CalendarEngine.psm1 # Core logic
├── State/ # Data
│ └── state-<GroupEmail>.json
├── Config.psd1 # Maps groups and calendars
├── Manage-Subscriptions.ps1 # TUI for managing data
└── Run-Deployment.ps1 # GAM wrapper, runs headless
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 TUI in PowerShell
.\Manage-Subscriptions.ps1Use the menu to add one or more Google Groups and Calendars, or to manage the State. The config is saved as config.psd1 in the same directory as the script.
@{
Calendars = @(
@{
Label = 'Example Calendar'
Id = 'c_123xyz...@group.calendar.google.com'
}
)
Groups = @(
@{
Email = 'group1@domain.tld'
Label = 'Example group'
CalendarIds = @(
'c_123xyz...@group.calendar.google.com'
)
}
)
}
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.
.\Run-Deployment.ps1.\Manage-Subscriptions.ps1For each Group defined in Config.psd1, 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)
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 the state file. Deployment will run for any new members of the group. 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.
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\Run-Deployment.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)