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:
tell application "System Preferences"activateend tell
In the example below, you can see how you can compile and run the script.
Next, we need to open a notification pane:
tell application "System Preferences"activateset 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
- 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:
tell application "System Events"tell front window of (first application process whose frontmost is true)set uiElems to entire contentsend tellend 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.
{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.
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 1set selected of r to trueend repeatend 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.
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 1set selected of r to truetell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickend repeatend 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:
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 1set selected of r to truetell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickif name of UI element 1 of r is "Calendar" thentell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickend ifend repeatend 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.
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 1set selected of r to trueif name of UI element 1 of r is "Calendar" thentell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickelsetell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickend ifend repeatend 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.
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 1set selected of r to trueif checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists then(*...*)end ifend repeatend tell
If so, we will assign a checkbox to the temporary variable theCheckbox
and tell if we want to click on it.
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 1set selected of r to trueif checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1tell theCheckboxif (its value as boolean) then click theCheckboxend tellend ifend repeatend 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.
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 1set selected of r to truetell pop up button 1 of group 1 of tab group 1clickdelay 0.2click menu item "when unlocked (default)" of menu 1end tellend repeatend 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
tell application "System Preferences"activateset the current pane to pane id "com.apple.preference.notifications"end telltell application "System Events"tell front window of (first application process whose frontmost is true)set uiElems to entire contentsend tellend telltell 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 1set selected of r to trueif name of UI element 1 of r is "Calendar" thentell radio button "Alerts" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickelsetell radio button "Banners" of radio group 1 of group 1 of tab group 1 to if value is 0 then clickend ifif checkbox "Show notifications on lock screen" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Show notifications on lock screen" of group 1 of tab group 1tell theCheckboxif (its value as boolean) then click theCheckboxend tellend ifif checkbox "Show in Notification Centre" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Show in Notification Centre" of group 1 of tab group 1tell theCheckboxif (its value as boolean) then click theCheckboxend tellend ifif checkbox "Play sound for notifications" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Play sound for notifications" of group 1 of tab group 1tell theCheckboxif (its value as boolean) then click theCheckboxend tellend ifif checkbox "Badge app icon" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Badge app icon" of group 1 of tab group 1tell theCheckboxif not (its value as boolean) then click theCheckboxend tellend ifif checkbox "Allow time-sensitive alerts" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Allow time-sensitive alerts" of group 1 of tab group 1tell theCheckboxif not (its value as boolean) then click theCheckboxend tellend ifif checkbox "Allow critical alerts" of group 1 of tab group 1 exists thenset theCheckbox to checkbox "Allow critical alerts" of group 1 of tab group 1tell theCheckboxif not (its value as boolean) then click theCheckboxend tellend iftell pop up button 1 of group 1 of tab group 1clickdelay 0.2click menu item "when unlocked (default)" of menu 1end telltell pop up button 2 of group 1 of tab group 1clickdelay 0.2click menu item "automatic" of menu 1end tellend repeatend tell