Syncing Delegated Free/Busy Google Calendars to iOS and iPadOS

This post explains how you can sync Free/Busy events from delegated Google calendars to the Apple Calendar app in iOS and iPadOS.

The Problem

I use Apple’s Calendar app to view and manage my calendars in iCloud and Google. Generally, this works well, and all of my directly connected accounts sync fine across the Calendar on macOS, iOS, and iPadOS. There’s one set of calendars, however, that do not sync to all devices, and that’s delegated availability-only (Free/Busy) calendars from Google. This can be problematic if your work calendars can only be shared with Free/Busy information, and you are not participating in a Bring Your Own Device (BYOD) program with your company.

On macOS, this is not an issue, as you can share your work calendar with a personal Gmail account and see the busy events in the Delegates section in the Calendar app.

Delegated Free/Busy calendars appear in macOS

On iOS and iPadOS, however, the delegated calendar is nowhere to be found. This is because iOS and iPadOS do not support delegated Free/Busy calendars from Google. If you go to the Google Calendar Sync Settings page, you’ll see the delegated calendar under the “Not available for syncing” section.

No native delegate Free/Busy calendar support in iOS or iPadOS.
The delegated calendar is not available for syncing from the Google Sync Settings page.

The Solution

So, how do you get Calendar on your iPhone and iPad to see the Free/Busy calendar from work? I searched the internet far and wide for a solution to this problem, but came up with nothing. So I rolled up my sleeves and hacked together this AppleScript. The general workflow is as follows:

  • Retrieve all events from the delegate calendar that are scheduled to occur today.
  • For each event, check to see if there is an event with the busy title (Step 3).
  • If no event exists, create a new event in the target calendar (Step 2) with the title (Step 3).
  • Return the number of events changed.

Updated March 1, 2022: Added Try block to catch errors when retrieving the start or end date of events.

global delegateCalendarName
global busyCalendarName
global busyTitle

set delegateCalendarName to ""
set busyCalendarName to ""
set busyTitle to "Busy"

on GetPreferences()
	if delegateCalendarName is "" then
		error "No delegate calendar name defined."
	end if
	
	if busyCalendarName is "" then
		error "No target calendar name defined."
	end if
	
	if busyTitle is "" then
		set busyTitle to "Busy"
	else
		set busyTitle to do shell script "echo " & (quoted form of (busyTitle)) & " | xargs"
	end if
	
end GetPreferences

on AddBusyEventsFromDelegatedCalendar()
	set now to current date
	set today to date ("" & (month of now as string) & " " & (day of now as string) & ", " & (year of now as string) & " 00:00:00")
	set tomorrow to today + 60 * 60 * 24
	set num to 0
	
	tell application "Calendar"
		try
			set delegateCal to first calendar whose name is delegateCalendarName
		on error errStr number errorNumber
			error "Could not find delegate calendar."
		end try
		
		try
			set workCal to first calendar whose name is busyCalendarName
		on error errStr number errorNumber
			error "Could not find target calendar."
		end try
		
		tell delegateCal
			set calEvents to (every event whose start date is greater than or equal to today and start date is less than or equal to tomorrow)
		end tell
		
		repeat with e in calEvents
			try
				set startDate to start date of e
				set endDate to end date of e
				
				tell workCal
					set workEvents to (every event whose start date is equal to startDate and end date is equal to endDate and summary is equal to busyTitle)
					
					if (count of workEvents) is 0 then
						
						make new event with properties {start date:startDate, end date:endDate, summary:busyTitle}
						set num to num + 1
						
					end if
				end tell
			on error errStr number errorNumber
				log "" & errorNumber & ": " & errStr
			end try
		end repeat
		
		set theResult to "Number of events created: " & num
	end tell
	
	return theResult
end AddBusyEventsFromDelegatedCalendar

GetPreferences()

AddBusyEventsFromDelegatedCalendar()

NOTE: If you want to change the script to process events for a whole week, change the line:

set tomorrow to today + 60 * 60 * 24

to

set tomorrow to today + 60 * 60 * 60 * 24 * 7

Copy and paste the code above into the Script Editor application on macOS. Then, do the following:

  • Enter the name for the delegate calendar
  • Enter the name for the target calendar
  • Enter the busy event title
  • Save the script

Run the script and see events in your delegated work calendar be added to the target calendar for the current day.

The busy events are added to the target calendar.

TIP: You can hide delegated calendar in macOS Calendar so you don’t see double events at the same time.

Since the target calendar exists on iOS and iPadOS, you’ll see the busy events appear. Huzzah!

Delegate busy events now appear on your iPad and iPhone!

Automating the Script

We will now want to automate the script so it runs periodically throughout the day. Here’s where we run into an annoying oddity with AppleScript. On macOS Monterey, we have a number of native tools to run the script:

  • Script Editor
  • Script Application
  • osascript shell command
  • Shortcuts
  • Automator

Additionally, there are several third party applications that can run AppleScripts:

Check out the execution time to run the script using these methods:

  • Run the script from Script Editor: 4 seconds
  • Run the Script Application: 16 seconds
  • Run the Automator Application: 16 seconds
  • Run the script using osascript from the command-line: 95 seconds
  • Run the script from a shortcut: 75 seconds
  • Run the Script Application from Keyboard Maestro: 18 seconds
  • Run the Script Application using Fast Scripts: 18 seconds
  • Run the script using Fast Scripts: Times out

Method 1: Application

I have no idea why AppleScripts compiled into an application or run through osascript or a shortcut are so slow. We don’t want to manually open the script in Script Editor and run it every time we add a new calendar event, so we will convert it into an application and just accept the slowness. There are two ways to make an application out of a script, and while it’s easier to do it using the Export command in Script Editor, I found problems where I would constantly get infinite permission prompts to grant calendar access to the app.

To avoid this, let’s use the osacompile command line tool to create an application from a script. Suppose the script exists on the desktop with the filename BusyDelegate.scpt.

  • Open Terminal
  • Navigate to the directory where your script is
  • Enter osascompile -o ~/Desktop/BusyDelegate.app ~/Desktop/BusyDelegate.scpt
  • Press Return

The Script Application will be placed on your desktop with the filename BusyDelegate.app. Double-click it to run, and you will see it takes about 4 times as long as running the exact same script from Script Editor. While the application is running, the Calendar app will appear frozen. Once the application has completed the script, control will return to the Calendar app.

Method 2: Script

In testing, I noticed several AppleScript errors when running the application, so perhaps launching Script Editor, opening the file, and pressing Command-R to run the script is a better approach.

Setting up a Cron Job

Next, let’s add a cron Job to run the application on an interval that you choose. I ended up using Keyboard Maestro to create the job, since I’m lazy and didn’t want to muck with my crontab. This KM macro runs the application once every hour on weekdays using the schedule: 0 * * * 1-5.

Keyboard Maestro macro to open the Busy Delegate Calendar application.

If you wanted to go with Method 2, this is the Keyboard Maestro macro you would need to create:

In both cases, the macro opens the last active application. I do this because I don’t want to lose my application focus when the script runs at the top of every hour.

Conclusion

Now I have an automated way to populate my personal calendar with Free/Busy events from my work calendar on my iPhone and iPad. It would be a whole lot better if iOS and iPadOS Calendar just supported displaying availability-only calendars from Google. Maybe it will come in iOS 16 and iPadOS 16. But if it doesn’t, at least I have a workaround. If this tutorial helped you, please leave a comment down below!

20 responses to “Syncing Delegated Free/Busy Google Calendars to iOS and iPadOS”

  1. Felix Wong Avatar

    Wow, this is much more complex than the Shortcuts I’ve been trying out or trying to create. Good job on that! I’m glad I don’t have any Free/Busy Google Calendars; I didn’t even know there was such a thing.

  2. Mel Obst Avatar
    Mel Obst

    Hello! Can you have two iPads logged onto the same ATEM switcher at the same time with one going between Supersource presets and the other doing other things on the same switcher?

    1. Adam Tow Avatar

      Yes, you can do this. You can also have one iPad with MixEffect running in Split View (i.e. two apps side-by-side) and have them both talking with the same (or different) ATEMs. There is generally a limit of 5 connected clients to an ATEM switcher, so keep this in mind if you are also running ATEM Software Control on a Mac/PC, Companion, etc.

      1. Mel Obst Avatar
        Mel Obst

        Thanks so much! This makes it easy when using one Supersource with a box over slides to have the slidedeck operator running that and keeping the other Supersource for side by side intro boxes. One thing that would be great, but I think it is a Blackmagic thing is putting drop shadow on the boxes. Thanks so much for the great work you are doing! All the Best! Mel Obst

    2. Adam Tow Avatar

      Box Borders and Shadows are only available on the 2 M/E, 4 M/E, and Constellation 8K switchers. The ATEM Mini Extreme and Extreme ISO don’t have those features enabled unfortunately. You can put borders and shadows on the two USK DVEs, however.

  3. David Avatar
    David

    Hi Adam, I couldn’t find your contact so I’m reaching out here. I was hoping to discuss some integrations.

    1. Adam Tow Avatar

      Find me on LinkedIn and send me a message there!

  4. MarkT Avatar

    It’s a respectable start. It doesn’t look like it can handle meetings that move or are canceled (a frequent occurrence for me) or recurring events. That’s when things get interesting.

  5. Tiff Avatar
    Tiff

    Hi, How are you getting the calendar to appear in the Mac Calendar?

    My husband has shared a work calendar with me from gmail to gmail. That calendar is “availability only”, but is nice so I can see when he has a late appointment.

    As you mention above, that calendar doesn’t show up on my iPhone.. but it is also not showing up on my Mac either. Could you tell me how you got it to show up there? This script would save me from having to check two calendars (or transfer everything to google calendar, which I don’t want to do).

    Thanks

    1. Adam Tow Avatar

      Look in Calendar Settings > Accounts. Click on the account where you husband has shared the calendar with you and click on Delegation. Does the calendar appear there unchecked? If so, check it and see if it now appears in your calendar sidebar.

  6. bryan7230a793a1 Avatar
    bryan7230a793a1

    You don’t explain how to:

    Enter the name for the delegate calendar

    2. Enter the name for the target calendar

    3. Enter the busy event title

    I’ve tried various things, but I get error messages.

    1. Adam Tow Avatar

      You modify the AppleScript that I have in the post. See the lines here:

      set delegateCalendarName to “”
      set busyCalendarName to “”
      set busyTitle to “Busy”

      1. bryan7230a793a1 Avatar
        bryan7230a793a1

        So inside the “”‘s I put in the name of the calendar?

  7. Adam Tow Avatar

    That’s correct. Make sure the quotes aren’t smart quotes if you have copied and pasted into Script Editor.

    Also, it’s been awhile since I used this method since I no longer work at the company that required me to use this busy/delegate fix. So, if there’s problems, I’ll be unable to assist you further. Sorry!

  8. bryan7230a793a1 Avatar
    bryan7230a793a1

    Ok. Well, all it does is create apt’s that are titled “Busy” at the same time as the apt’s it was trying to copy. So I guess it no longer works.

  9. Adam Tow Avatar

    If your Mac has access to both calendars natively, you don’t need this solution. I created it because I was unable to access my work calendar on my personal computers, and I needed a way to see when I was busy at work. Is this your use-case too? If not, what are you trying to accomplish?

    1. bryan7230a793a1 Avatar
      bryan7230a793a1

      Well, I can see the delegated calendars on the mac, but I’m unable to see them in iOS unless I use my Google Calendar instead of the iOS calendar. In iOS it allows you to see the delegated calendars, and it asks you to put in a name of someone you want to share this with, but if I put in my own name or my own email(s), nothing pulls up and I can’t proceed further. I just wanted to view google delegated calendars on my iOS without having to switch to Google Calendar.

      1. Adam Tow Avatar

        And if you go to this Google link: https://calendar.google.com/calendar/u/0/iphoneselect

        are you able to select the delegated calendars to view? If the calendars don’t have checkboxes next to them, check them and see what happens on iOS. This post is for free/busy calendars, but your use-case is different.

  10. bryan7230a793a1 Avatar
    bryan7230a793a1

    That link did fix it for both email addresses. Thank you!

    1. Adam Tow Avatar

      Great! Glad it worked for you.

Leave a reply to Mel Obst Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Adam, here

Welcome to tow.com, my home on the internet since 1995. I’m an indie software artist and creator of apps such as MixEffect, MsgFiler, AlbumFiler, Wipe My Screen, and more. I’m also the producer and co-director of Autumn Gem. Enjoy your visit here!

Let’s connect