How to Set Notifications for macOS Consistently in an Automatic Way
November 5, 2021This approach is designed for macOS Monterey; different versions would have different references of UI Elements!
I always wanted to have my notification consistently set, but I didn't want to do it every time manually. You may think that it is not so bad to set notification settings for around 30 apps, and you might be correct, but what if I change my mind about some choice and I need to go through every app. Uhm, I do not want to do monkey work, and I like automation, so let's find a solution.
First, let begin with research; How can we automatize things in macOS? Well, we can use Automator, AppleScript, zsh, or Shortcuts. Because I had some experience with AppleScript in the past and I haven't found a way how to do it with Shortcuts, I decided to do it with AppleScript.
But wait! What is an AppleScript?
AppleScript is a scripting language created by Apple Inc. that facilitates automated control over scriptable Mac applications.
So that looks like something we are looking for! Let's get started. We need to open a Script Editor app and create a new file. Our first step should be to open a "System Preferences", and we can achieve this by running this script:
1tell application "System Preferences"2 activate3end tell
In the example below, you can see how you can compile and run the script.
Next, we need to open a notification pane:
1tell application "System Preferences"2 activate3 set the current pane to pane id "com.apple.preference.notifications"4end tell
That was relatively easy, but trickier things are in front of us. Let's write the steps we need to do.
Requirements
- We needs to be in the first tab (Notifications)
- We needs to be in the first scrollable area (Left list of apps)
- We needs to go for each of the table rows and select it
- We want to select "alert style" to "Banner" (or whatever option you prefer)
- We want to uncheck the "Show notifications on lock screen" checkbox
- We want to uncheck the "Show in Notification Centre" checkbox
- We want to uncheck the "Play sound for notifications" checkbox
- We want to check the "Badge app icon" checkbox
- We want to check the "Allow time-sensitive alerts" checkbox
- We want to check the "Allow critical alerts" checkbox
- We want to select "Show preview" to "when unlocked (default)"
- We want to select "Notification grouping" to "automatic"
You may see that my options are highly opinionated; I'm not saying these are the best options for you, so feel free to change them.
In the process of debugging and finding a better approach, I've found a great script that makes your automation a lot easier:
1tell application "System Events"2 tell front window of (first application process whose frontmost is true)3 set uiElems to entire contents4 end tell5end tell
What this script does, is that it will return an array of references to UI Elements which can be used within a tell
statement. In the output.txt
example below, you can see a small portion of the output. For better readability, I've put every reference on the new line.
1{2 tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",3 radio button "Notifications" of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",4 radio button "Focus" of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",5 scroll area 1 of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events"6}
Traversing an apps
Let's traverse our apps and select each of the apps, so we will be able to change the individual preferences later.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true4 end repeat5end tell
You may notice when you run the script, every app will be selected for a short time. It runs pretty fast, but you will definitely notice it because the preferences window shows at the top.
Setting an alert style
We can select an alert style to "None", "Banners", or "Alert". I've picked "Banners" because most notifications are not so important to keep them in my sight.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click6 end repeat7end tell
We are clicking the "Banners" radio button only when it is not active, but what if we want a different alert style for some app? We can override our previous statement with the if
statement:
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click67 if name of UI element 1 of r is "Calendar" then8 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click9 end if10 end repeat11end tell
Of course, we are doing duplicate work here. Currently, only for the Calendar app, but it is definitely a duplication. So let's use the if else
statement.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 if name of UI element 1 of r is "Calendar" then6 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click7 else8 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click9 end if10 end repeat11end tell
That looks better now; even we can use the else if
statement to cover more edge-cases!
Clicking on the checkbox
Now, let's deal with checkboxes. First, we need to check if the checkbox exists.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then6 (*...*)7 end if8 end repeat9end tell
If so, we will assign a checkbox to the temporary variable theCheckbox
and tell if we want to click on it.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then6 set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 17 tell theCheckbox8 if (its value as boolean) then click theCheckbox9 end tell10 end if11 end repeat12end tell
Alternatively, we can invert the logic and use if not (its value as boolean) then click theCheckbox
to check the checkbox. This logic can be applied to: "Show notifications on lock screen", "Show in Notification Centre", "Play sound for notifications", "Badge app icon", "Allow time-sensitive alerts", and "Allow critical alerts".
Picking a value from pop-up buttons
Now we can implement the logic for the "Show previews" and "Notification grouping" pop-up buttons. Now we do not need to check if a button exists because it is present for every app. We need to use some delay to ensure our menu is already visible and we can click on one menu item.
1tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"2 repeat with r in rows of table 1 of scroll area 1 of tab group 13 set selected of r to true45 tell pop up button 1 of group 1 of tab group 16 click7 delay 0.28 click menu item "when unlocked (default)" of menu 19 end tell10 end repeat11end tell
Conclusion
Now we can join the examples we have tried. We have an automatic solution for setting a notification to our desired state! In the last section of this article, you can find a complete example of the working code.
Two things that are still missing are verifying if notification is enabled and the functionality of enabling/disabling notification. That was not a problem in my scenario, but it would be nice to have this covered.
If you have older or newer macOS, reach out, and I will try to find/update the script!
Complete code example
1tell application "System Preferences"2 activate3 set the current pane to pane id "com.apple.preference.notifications"4end tell56tell application "System Events"7 tell front window of (first application process whose frontmost is true)8 set uiElems to entire contents9 end tell10end tell1112tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"13 repeat with r in rows of table 1 of scroll area 1 of tab group 114 set selected of r to true1516 if name of UI element 1 of r is "Calendar" then17 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click18 else19 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click20 end if2122 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then23 set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 124 tell theCheckbox25 if (its value as boolean) then click theCheckbox26 end tell27 end if2829 if checkbox "Show in Notification Centre" of group 1 of tab group 1 exists then30 set theCheckbox to checkbox "Show in Notification Centre" of group 1 of tab group 131 tell theCheckbox32 if (its value as boolean) then click theCheckbox33 end tell34 end if3536 if checkbox "Play sound for notifications" of group 1 of tab group 1 exists then37 set theCheckbox to checkbox "Play sound for notifications" of group 1 of tab group 138 tell theCheckbox39 if (its value as boolean) then click theCheckbox40 end tell41 end if4243 if checkbox "Badge app icon" of group 1 of tab group 1 exists then44 set theCheckbox to checkbox "Badge app icon" of group 1 of tab group 145 tell theCheckbox46 if not (its value as boolean) then click theCheckbox47 end tell48 end if4950 if checkbox "Allow time-sensitive alerts" of group 1 of tab group 1 exists then51 set theCheckbox to checkbox "Allow time-sensitive alerts" of group 1 of tab group 152 tell theCheckbox53 if not (its value as boolean) then click theCheckbox54 end tell55 end if5657 if checkbox "Allow critical alerts" of group 1 of tab group 1 exists then58 set theCheckbox to checkbox "Allow critical alerts" of group 1 of tab group 159 tell theCheckbox60 if not (its value as boolean) then click theCheckbox61 end tell62 end if6364 tell pop up button 1 of group 1 of tab group 165 click66 delay 0.267 click menu item "when unlocked (default)" of menu 168 end tell6970 tell pop up button 2 of group 1 of tab group 171 click72 delay 0.273 click menu item "automatic" of menu 174 end tell7576 end repeat77end tell