Along with the many other features for web apps on iOS and iPadOS 16.4, WebKit now includes support for the W3C’s Badging API.
This straightforward API allows web developers to badge the icon of a web app. This article explores the various features of the Badging API and how to use it, and our ongoing collaboration with W3C’s Web Applications Working Group to improve the specification.
Home Screen Web App Availability
In iOS and iPadOS 16.4, the Badging API is available exclusively for web apps the user has added to their home screen. You won’t find the API exposed to websites in Safari or other browsers, or in any app that uses WKWebView.
You can easily check for the availability of the API using feature detection for the setAppBadge
function:
if ('setAppBadge' in navigator) {
}
Badges and Notifications
On iOS and iPadOS, badging has always been closely tied to notifications.
Apps built for macOS, iOS, and iPadOS are free to set their badge counts through platform specific APIs whenever they like. The user must grant the app permission to display notifications before the badge will appear.
Similarly, web apps are free to call setAppBadge()
whenever they like, but the badge will only appear if the user has granted notifications permission.
To request notification permission, call Notification.requestPermission()
as part of a user activation (such as a button click):
<button onclick="requestNotificationPermission()">
Request notifications permission
button>
<script>
async function requestNotificationPermission() {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
// You can now use the Badging API
}
}
script>
iOS and iPadOS will show this system prompt to the user for permission:
You can also check if a user has previously granted notifications permission by using the Permissions API:
async function checkNotificationPermission() {
const permissionStatus = await navigator
.permissions
.query({ name: 'notifications' });
switch (permissionStatus.state) {
case 'granted':
break;
case 'denied':
break;
default:
await requestNotificationPermission();
break;
}
}
checkNotificationPermission();
Note that e