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
1tell application "System Preferences"
2 activate
3end 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
1tell application "System Preferences"
2 activate
3 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

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

index.scpt
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 1
3 set selected of r to true
4 end repeat
5end 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
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 1
3 set selected of r to true
4
5 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
6 end repeat
7end 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
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 1
3 set selected of r to true
4
5 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
6
7 if name of UI element 1 of r is "Calendar" then
8 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
9 end if
10 end repeat
11end 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
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 1
3 set selected of r to true
4
5 if name of UI element 1 of r is "Calendar" then
6 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
7 else
8 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
9 end if
10 end repeat
11end 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
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 1
3 set selected of r to true
4
5 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
6 (*...*)
7 end if
8 end repeat
9end tell

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

index.scpt
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 1
3 set selected of r to true
4
5 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
6 set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1
7 tell theCheckbox
8 if (its value as boolean) then click theCheckbox
9 end tell
10 end if
11 end repeat
12end 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
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 1
3 set selected of r to true
4
5 tell pop up button 1 of group 1 of tab group 1
6 click
7 delay 0.2
8 click menu item "when unlocked (default)" of menu 1
9 end tell
10 end repeat
11end 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
1tell application "System Preferences"
2 activate
3 set the current pane to pane id "com.apple.preference.notifications"
4end tell
5
6tell application "System Events"
7 tell front window of (first application process whose frontmost is true)
8 set uiElems to entire contents
9 end tell
10end tell
11
12tell 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 1
14 set selected of r to true
15
16 if name of UI element 1 of r is "Calendar" then
17 tell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
18 else
19 tell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then click
20 end if
21
22 if checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then
23 set theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1
24 tell theCheckbox
25 if (its value as boolean) then click theCheckbox
26 end tell
27 end if
28
29 if checkbox "Show in Notification Centre" of group 1 of tab group 1 exists then
30 set theCheckbox to checkbox "Show in Notification Centre" of group 1 of tab group 1
31 tell theCheckbox
32 if (its value as boolean) then click theCheckbox
33 end tell
34 end if
35
36 if checkbox "Play sound for notifications" of group 1 of tab group 1 exists then
37 set theCheckbox to checkbox "Play sound for notifications" of group 1 of tab group 1
38 tell theCheckbox
39 if (its value as boolean) then click theCheckbox
40 end tell
41 end if
42
43 if checkbox "Badge app icon" of group 1 of tab group 1 exists then
44 set theCheckbox to checkbox "Badge app icon" of group 1 of tab group 1
45 tell theCheckbox
46 if not (its value as boolean) then click theCheckbox
47 end tell
48 end if
49
50 if checkbox "Allow time-sensitive alerts" of group 1 of tab group 1 exists then
51 set theCheckbox to checkbox "Allow time-sensitive alerts" of group 1 of tab group 1
52 tell theCheckbox
53 if not (its value as boolean) then click theCheckbox
54 end tell
55 end if
56
57 if checkbox "Allow critical alerts" of group 1 of tab group 1 exists then
58 set theCheckbox to checkbox "Allow critical alerts" of group 1 of tab group 1
59 tell theCheckbox
60 if not (its value as boolean) then click theCheckbox
61 end tell
62 end if
63
64 tell pop up button 1 of group 1 of tab group 1
65 click
66 delay 0.2
67 click menu item "when unlocked (default)" of menu 1
68 end tell
69
70 tell pop up button 2 of group 1 of tab group 1
71 click
72 delay 0.2
73 click menu item "automatic" of menu 1
74 end tell
75
76 end repeat
77end tell

Share this post on Twitter