How to Set Notifications for macOS Consistently in an Automatic Way

November 5, 2021

This 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:

index.scpt
tell application "System Preferences"
activate
end tell

In the example below, you can see how you can compile and run the script.

Next, we need to open a notification pane:

index.scpt
tell application "System Preferences"
activate
set the current pane to pane id "com.apple.preference.notifications"
end tell

That was relatively easy, but trickier things are in front of us. Let's write the steps we need to do.

Requirements

  1. We needs to be in the first tab (Notifications)
  2. We needs to be in the first scrollable area (Left list of apps)
  3. We needs to go for each of the table rows and select it
  4. We want to select "alert style" to "Banner" (or whatever option you prefer)
  5. We want to uncheck the "Show notifications on lock screen" checkbox
  6. We want to uncheck the "Show in Notification Centre" checkbox
  7. We want to uncheck the "Play sound for notifications" checkbox
  8. We want to check the "Badge app icon" checkbox
  9. We want to check the "Allow time-sensitive alerts" checkbox
  10. We want to check the "Allow critical alerts" checkbox
  11. We want to select "Show preview" to "when unlocked (default)"
  12. 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:

index.scpt
tell application "System Events"
tell front window of (first application process whose frontmost is true)
set uiElems to entire contents
end tell
end 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.

output.txt
{
tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",
radio button "Notifications" of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",
radio button "Focus" of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events",
scroll area 1 of tab group 1 of window "Notifications & Focus" of application process "System Preferences" of application "System Events"
}

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.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
end repeat
end 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.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
end repeat
end 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:

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
if name of UI element 1 of r is "Calendar" then
tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
end if
end repeat
end 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.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
if name of UI element 1 of r is "Calendar" then
tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
else
tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
end if
end repeat
end 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.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
(*...*)
end if
end repeat
end tell

If so, we will assign a checkbox to the temporary variable theCheckbox and tell if we want to click on it.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1
tell theCheckbox
if (its value as boolean) then click theCheckbox
end tell
end if
end repeat
end 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.

index.scpt
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
tell pop up button 1 of group 1 of tab group 1
click
delay 0.2
click menu item "when unlocked (default)" of menu 1
end tell
end repeat
end 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

index.scpt
tell application "System Preferences"
activate
set the current pane to pane id "com.apple.preference.notifications"
end tell
tell application "System Events"
tell front window of (first application process whose frontmost is true)
set uiElems to entire contents
end tell
end tell
tell application "System Events" to tell window "Notifications & Focus" of process "System Preferences"
repeat with r in rows of table 1 of scroll area 1 of tab group 1
set selected of r to true
if name of UI element 1 of r is "Calendar" then
tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
else
tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
end if
if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1
tell theCheckbox
if (its value as boolean) then click theCheckbox
end tell
end if
if checkbox "Show in Notification Centre" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Show in Notification Centre" of group 1 of tab group 1
tell theCheckbox
if (its value as boolean) then click theCheckbox
end tell
end if
if checkbox "Play sound for notifications" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Play sound for notifications" of group 1 of tab group 1
tell theCheckbox
if (its value as boolean) then click theCheckbox
end tell
end if
if checkbox "Badge app icon" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Badge app icon" of group 1 of tab group 1
tell theCheckbox
if not (its value as boolean) then click theCheckbox
end tell
end if
if checkbox "Allow time-sensitive alerts" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Allow time-sensitive alerts" of group 1 of tab group 1
tell theCheckbox
if not (its value as boolean) then click theCheckbox
end tell
end if
if checkbox "Allow critical alerts" of group 1 of tab group 1 exists then
set theCheckbox to checkbox "Allow critical alerts" of group 1 of tab group 1
tell theCheckbox
if not (its value as boolean) then click theCheckbox
end tell
end if
tell pop up button 1 of group 1 of tab group 1
click
delay 0.2
click menu item "when unlocked (default)" of menu 1
end tell
tell pop up button 2 of group 1 of tab group 1
click
delay 0.2
click menu item "automatic" of menu 1
end tell
end repeat
end tell

Share this post on Twitter