TL;DR: Web Push on iOS is nearing its one year anniversary. It's still mostly useless.
- Updated Jan 30, 2024: Fixed some typos and such.
- Updated Jan 31, 2024: Added a "Further reading" chapter.
- Updated Feb 9, 2024: Minor edits to improve clarity, readability.
It's been almost a year since I wrote about how iOS 16.4 beta was announced, and with it, Apple finally started supporting Web Push. With every other major browser supporting push notifications for ~6 years, Apple was late to the game, but at least they did it.
Right?
Looking back, I can't help but feel very, very disappointed.
Steep requirements
On iOS, for a website to be able to ask the user to grant the push notification permission, it needs to be installed to the home screen. I covered some of my initial thoughts regarding this topic in my previous post about Web Push on iOS, but let's just do a short version here: Requiring a website to be installed defeats one of the web's most awesome superpowers: On the web, you do not need to install anything, you just follow a link. It's what makes discovery on the web so easy and frictionless. Asking a user to add an icon on their home screen is a huge hurdle that many will not even attempt to take: In 2016, Recode (now Vox) reported that most smartphone users install zero apps per month. I think we can safely assume the same reluctance of users to install new native apps applies to web apps as well.
And just to be clear: No other browser on any of the other platforms - not even Safari on macOS! - requires you to install a website for it to be able to send push notifications.
But it gets worse: Installing a website and putting the icon on your home screen is not just a very steep requirement - it's actually something that few users know they can do on iOS:
[...] adding a website to the home screen remains such a hidden feature that even power users would be forgiven for not knowing about it.
Push, by Jeremy Keith
Mozilla reported that only 4 out of 10 iOS users knew they could "Add to Homescreen" 1. And it's not just hidden, adding a web app to the iOS home screen also involves a whole bunch of steps, which adds even more friction.
Apple is within their rights to withhold Web Push to installed apps. One could argue it's not even an unreasonable policy - if Apple made installing a web app at least moderately straightforward. As it is, they have buried it and hidden important functionality behind it. The delta between the ease and familiarity of getting a web app vs. a native app installed (particularly because Apple prevents web apps from being in the store where users often look for apps) is massive. It wouldn't be a problem if there were alternatives, if users and developers could turn to other browsers who have less hostile requirements, but on iOS, there are none 2.
To summarize, Web Push on iOS requires users to find a hidden feature and perform a bunch of steps to install a website to the home screen. Whatever the motives and whether on purpose or not, native apps still have the advantage here - and I bet Apple likes it that way.
Every step that keeps customers from experiencing what makes you great, leaves them wondering why youβre not.
What Can Bike Sharing Apps Teach Us About Mobile On-boarding Design? by Luke Wroblewski
1 The author of the blog post actually considers 4 out of 10 as good, but compared to how many people know where to get native apps, 40% looks pretty bad to me.
2 Since I started writing this post, Apple announced their plans to comply with the European Union's DMA legislation. In the EU, third-party browser engines will be allowed on iOS. That's good news but it doesn't change anything for users that live outside of the EU. Secondly, Apple's rules regarding browsers that want to ship their own engine are already deemed unworkable. So for all intents and purposes, the #AppleBrowserBan is still in effect, albeit in a slightly different form.
Limited and incomplete
Web Push is closely tied to the Notification API. Sending a push message to a device is one thing, but the Notification API is the thing that turns that message into something the user can see and act on. Unfortunately, Safari 16.4 may have shipped full support for Web Push, but the Notification API was missing a lot of features. For example:
Feature | Example / description |
---|---|
icon | Safari will always use the app icon for web apps. Showing the profile picture of the person who sent you a message or email is not possible. |
image | You can not show (a preview of ) an image, for example a media attachment. |
timestamp | You can not show a custom date/time, e.g. the time of the actual publication of an article. |
click event | The MDN table shows this as not supported, but in my testing, it seems to work as long as the web app is running. If it's not, tapping the notification will just open the web app. So... let's call this one flaky. |
actions | You can not show actions in the notification, e.g. "Snooze" or "Mark as read". |
tag | You can not update an existing notification (or control whether to renotify the user) |
getNotifications() | Used to retrieve a list of notifications that the system is currently showing. On iOS 16.4, this always returned an empty array 1 |
close() | You can not close an existing notification. It will only close when the user taps it or dismisses it manually. |
Back when iOS 16.4 launched, developers had to find out about these missing or incomplete features themselves, as the Browser Compatibility table on MDN had all but green checkboxes 1. And sure, WebKit was passing all the automated tests, but if you, for example, tried to actually get a list of notifications, you'd always get an empty list. They implemented the API as far as "the function exists" and "it returns the correct (type of) values" - but the returned value was not reflecting what was actually there or the function didn't do anything (and didn't throw an error or anything).
This makes feature detection not only pointless, but counterproductive. According to the test, the feature is supported. But in reality, if you would rely on the feature detection test and/or the MDN table, you might very well be offering a broken user experience.
So, what now?
I don't know π€·. Maybe do some user-agent detection and work around Safari issues as we've gotten used to in the past decade?
One commit to check them all
I do want to add one thing here, and that is that someone on the Safari team pushed a single commit to MDN that made all the Notification API checkmarks go green for iOS Safari 16.4. MDN relies on automated tests for these results, and sure, Safari was passing all of them. But as I explained, many of these features didn't actually, you know, do the thing. I have a really hard time believing that no one at Safari headquarters realized that their browser didn't actually really support many of these features. We're not talking about amateurs here, Safari has some very talented people working on it.
How did they miss this? How have they still not noticed? Or, if someone did notice, why are there still green checkboxes where there shouldn't be?
1 Most (or at least many?) of these checkboxes on MDN have been corrected since iOS 16.4 launched, but still, as of the writing of this post, some features show a green checkbox when, in fact, the feature is not working.
Real world example
In 2016, I started a hobby project to play with Firebase's Realtime Database and the Notification API: a web chat app.
I was curious as to how far I could take it. Would it be possible to build all the usual chat features using web technology? And would it work on mobile browsers without needing to wrap it in a Cordova app - without compromising the user experience?
The answer to all those questions is yes!
Sure, I had to work within the limits of what browsers allow me to do, but pretty much everything you'd want from a chat app is achievable. With one caveat: It was completely shit on iOS. I'm not going into all the scroll, input and layout issues here, but there were plenty. It didn't help that I don't own an iPhone or (like to) use macOS, or that Safari on the iOS simulator behaves differently than on an actual device π - but I did manage to fix (or at least work around) most of those issues.
The thing I do want to highlight is that push notifications were simply not an option on iOS because WebKit did not support it, and on iOS there are no alternatives for WebKit. A chat app without notifications is pretty much useless, so the only people I could convince to use it were friends who own Android phones (and yes, we've been using my web chat app for 6 years now!). Sure, there are issues on Android, but at least Web Push was available and very usable.
Anyway. When Apple announced support for Web Push I was super excited (if a bit wary). When it launched, it turned out that I didn't need to change a single line of code - Firebase's messaging implementation just worked!
But then I started noticing everything that did not work:
- A chat app should send a push notification whenever someone writes you a new message. Obvious, right? But on iOS, you can't update an existing message via the
tag
property, so every message for every chatroom adds a new notification. I've learned that (most?) native chat apps behave the same, but at least they have the ability to update an existing notification (or at least close one and replace it with a new one). - WebKit does not support the
icon
property, so every message has the same icon (the web app icon). As such, there's no way to easily distinguish individual chatroom messages by way of a profile or chatroom picture. You get a ton of notifications (see previous point), all with the same icon. - You can't group notifications per chatroom. iOS will collapse the notifications for all messages into a single stack, in the order they came in. In other words, you end up with a ton of notifications, with all conversations mixed together. Meanwhile, native chat app notifications do get their notifications nicely grouped per conversation, with each group collapsing into a separate stack.
- Even if the user opens a chatroom and reads the unread messages, the web chat app can't close any notifications for that chatroom. The user has to dismiss every single one manually. You guessed it: native apps can do this.
- And finally: The web chat app can not rely on feature detection to prevent any of this. You either annoy the user with a bad experience, or you use user-agent detection and do what you can to adapt (and, in the process, probably degrade the user experience compared to what the same web app can do on every other platform - and compared to native apps on the same platform).
- And don't forget: On iOS, there are no alternatives to WebKit's implementation.
In the screenshots above, notice how on Android (left), there is one notification for each chatroom (two in total), which can be updated to include new messages. Each notification shows the profile picture of the sender. On the iPhone (right), instead of updating the existing notification, it creates a new one for each push message. They all have the same icon. Messages from Chatroom #1 are mixed with #2. None of these can be closed automatically by the web app, except the ones you tap.
This stuff all works on Android, Linux, macOS and Windows (with, at most, some minor differences, as each operating system handles notifications slightly differently).
Not so long ago, the simple act of installing a web app on iOS caused so many unexpected issues, problems and broken user experiences (that only occured in the installed web app, not in a regular iOS Safari browser tab), that I simply detected iOS Safari and prevented web apps from being installed as standalone
(in other words: if the user would "Add to Homescreen", it would just create a bookmark but on the home screen). And now I feel the same about Web Push: I should probably just not offer push notifications on iOS, as it will just annoy my users if they enable the feature.
Not much progress
In the end, it turns out that Apple shipped an implementation of Web Push that was...
- ... good enough to convince anyone that didn't dig too deep (or did any digging at all) that Web Push is now available on iOS.
- ... incomplete enough to actually be unusable for anything more complex than websites that want to push "breaking news stories" - you know, the sites that have given push notification prompts such a bad name because they ask for the permission on page load.
Since the initial launch of Web Push on iOS, not much has happened. It's been a year and the list mentioned above is still pretty much accurate. Web Push on iOS is still very much incomplete and, I can't stress this enough, you can not rely on feature detection to prevent a bad user experience.
As far as I know, just one of the missing features was added (or rather: fixed): getNotifications()
now returns the actual number of notifications - but it's still useless if you only need that function to call close()
on any of them. In the case of the web chat app example I described above, they have done exactly nothing that improves the experience in any way.
I can't imagine anyone actually using Web Push in its current form on iOS. Project teams have probably decided it's not worth to do the extra work to deliver an experience that is, even with the extra work, subpar at best. The chance that a user will install the web app (and knows how to do it) is close to zero. With that in mind, I imagine the Safari team, looking at usage numbers of Web Push on iOS, reaching the conclusion that "Nobody is using it, see?! We should put our efforts into other areas! We need to have high numbers on Interop or risk embarrassment! As long as MDN and Caniuse show all these green checkmarks, we're fine!"
Maybe the Safari team feels like push notifications do not belong on the web. Maybe they only implemented the APIs because of the mounting pressure Apple is facing from developers and regulators - but they don't really want it to succeed.
It's almost as if they wanted it to fail, or they were in a hurry to ship it so they could point to it and say "look, we can keep up!"
I know I'm being a cynic and I'm putting words into the mouths of the Safari/WebKit team, but I just can't understand why anyone would ship Web Push - and then pretty much leave it as is for a year - as incomplete and useless as it is. How could they have the MDN Browser Compatibility table show all these green checkboxes when, in fact, a lot of that is just plain false? The current situation is, in the end, a decision, whether directly or indirectly, on purpose or not, whatever the motives. But before anyone comes away with the idea that I blame the Safari/WebKit team themselves: I do not. Not really. I think it's caused by decisions from higher up that end up creating this situation. I blame Apple, not the team that I'm convinced is actually trying to ship a good browser. I'm very glad that the EU is forcing Apple to allow third-party browsers to compete with their full engines, which should compel Apple to finally, actually invest in their own browser (which is making them billions upon billions, by the way).
With actual competition, I think Apple would think twice before they launched another API as incomplete and broken as Web Push.
Further reading
- Alex Russell - Why Are Tech Reporters Sleeping On The Biggest App Store Story? features a blog-length footnote on the current state of Web Push on iOS.
Thanks!
- Bruno Stasse and Stuart Langridge for proof-reading (early) drafts and feedback π
- Open Web Advocacy for their tireless work to bring browser competition to iOS (and everywhere else).