The battle between native mobile apps and progressive web apps continues. One of the most regularly mentioned advantages of native web apps was the ability to receive push notifications even on iOS. Everything changed in 2023 when Apple announced supporting push notifications for PWAs. We’ve tested it in one of our projects and here’s how you can do it too.
The arrival of PWA push notifications on iOS convinced our client to broaden the scope of communication they send to their customers and add this feature to the system we developed. To be honest, it “pushed” us to challenge ourselves in quite an unusual territory. Thus, we started with some quick research based on our technical situation (used technologies, first scratches of requirements from the client), and then we created a PoC (Proof of Concept) with an estimation of the time it would take to implement push notifications in the progressive web app we developed.
Here are some questions we knew we had to answer:
- Is it really possible to send and receive push notifications on mobile devices with different operating systems (i.e., Android and iOS)?
- Can we track and gather information about the push we sent?
- How easily can one customize push notifications?
Read on to find out what we learned.
Our goal
First, it was necessary to determine which platforms (devices/operating systems) are most commonly used by customers who are visiting our platform. Notifications were supposed to be sent only to mobile users, so we had to list the types of users that had to be verified during the PoC.
Our user groups were as follows:
- iOS users
- Android web users
- Android native app users
Finally, we started preparing our PoC in the scope of:
- The usage of PWA (Progressive Web Application) on Android and iOS
- The decision of which push server we will use and why
Requirements
Progressive web app
Thanks to the preliminary research, which gave us basic knowledge about the needs in iOS, we quickly pointed out that usage of PWA is a must-have in this project. It was also quite good news for our client because they were happy about releasing a “pilot deployment” on production, only with PWA artifacts.
The basic thing iOS requires to use push communication is for the phone user to add a home screen shortcut to the app (pin it to the desktop, if you will). However, similarly to Android, not all home screen shortcuts on iOS work the same. Web developers can give the user a “native application-like” experience in their web applications after fulfilling a few requirements:
- Providing a manifest file with necessary attributes
- Serving page via a HTTPS protocol
The second requirement was fulfilled a long ago because, nowadays, almost all seriously developed web applications are served securely. So, we were only one step away from giving our users PWA.
At this point, the most noticeable difference for end-users was the disappearance of browser UI elements while using the pinned version of our portal. However, for developers, PWA is opening some powerful possibilities to use in the JavaScript layer, like service workers, which make background processes for our applications closer to native mobile apps but with the same codebase as the standard browser version.
Push notifications
The main objective of our PoC was to find out the best way to send push notifications to all groups of mobile users. The first research revealed two main approaches:
- Using a default browser Push API
- Using a dedicated push server from a cloud provider
At this point, we had a general outlook of requirements from our client, so we knew that the main use case of notifications would be broadcast to users, not direct messaging. We also needed a unified way to send pushes to handle their reception simultaneously within the JavaScript client and the native Android app.
Our infrastructure was based on AWS, so it was necessary to verify if it is possible to stay on this platform fully and not use any third-party services. All in all, verifying the usage of AWS SNS (Simple Notification Service) and ADM (Amazon Device Messaging) made us realize that none of the AWS elements would fit our needs. Underneath, SNS needs a connection to Google Firebase Cloud Messaging (FCM), and this approach would force us to have elements in our infrastructure that work only as a proxy to FCM. ADM only has SDK for native apps, so we also needed the possibility to connect via JavaScript to receive notifications on iOS.
Finally, our last decision was to choose between Push API and usage of Google Firebase Cloud Messaging. Each had their pros and cons (outlined in the table below)
Approach | Pros | Cons |
Push API |
|
|
Google Firebase Cloud Messaging |
|
|
Ultimately, our summary revealed two factors that made us choose GCP FCM as our push server: the ease of connecting to the native Android app, and the topics feature.
UX/UI
After we decided to use FCM and implemented the first working receiver on three platforms (iOS PWA, Android PWA, and Android native), we started testing the visual capabilities of the push messages. The key was to find the optimal length of the title and message to make them look good on all devices. The biggest difference in the presentation was the fact that, on a native Android app, there is a possibility to send text in an “expandable” model – in other words, the user can only see a small part of the message and can expand it by tapping. However, with a PWA implementation, there is no way to expand text. Tapping results in an onClick action and redirects the user to a given URL.
Implementation of PWA push notifications
Due to the previously mentioned need to broadcast messages to all users in our system, we decided that we need to use the topic feature in FCM. The base of our flow relied on getting a user token (a unique identifier given by FCM after subscription) and sending a subscribe request to the push server to attach the subscriber to our generic topic.
The main flow of a subscription:
- The user has to click the dedicated “Subscribe” button
- We check whether the user gave permission to receive push notifications on this device (if not, we require it)
- After receiving the permission, we send a subscription request to FCM and receive a token
- We pass the token to our backend – now we have saved both a userId and an FCM token
- We request FCM to attach a token to our main topic
- Now, the user will receive all messages sent to this topic
Using the topics feature in FCM gave us backend control over which users will receive notifications and which won’t. This control is necessary in cases when a business process requires us to stop or renew sending messages to users. Without it, we wouldn’t be able to disconnect users from push notifications until they, at the very least, open our application (and then we can call the deleteToken function in the SDK).
In our approach, we have saved all tokens and their owners in the database. If a business process in the application requires us to stop sending messages to users, we can send a request to FCM and unsubscribe all user tokens from our topics (even if some of them have already been deleted on the push server side).
FCM also supports use cases like sending messages to one (or more) specific tokens or sending messages to all subscribed users. For now, this function has no use in our system, but maybe it’s something we will add one day.
Tracking the notifications
One of our requirements was to track notifications on the user side. It is quite important because it allows us to see whether the user reacts to a message they get and also how many users received this content. The tricky part here is using PWA and handling it in JavaScript. In the Android native app, this part is simple – we receive a notification in the handler in Java code, and after this, we can send a request to the server without any problems using one of the common HTTP client frameworks.
But in a PWA, there are some surprises. Our backend process is the Service Worker, but the rules it operates on differ from those of the main browser process. SW doesn’t know about things like AJAX requests or LocalStorage, so you need to use limited functionalities.
In our case, requests are sent from SW to our server backend via Fetch API. This part of the SW domain is mostly used (as the name suggests) to fetch data from the server and keep it for the main process – for example, to use when the user is offline or to refresh data in the background. For us, it was the only way to make HTTP calls outside of the running PWA. Service Worker and PWA work in tandem, but separately – SW receives the push notification but, when calling the server, it cannot rely on what the main browser thread (which operates the PWA) can do.
Testing PWA push notifications
Testing this kind of feature requires a different mindset from other types of communication. In most systems, one user has only one email address and only one phone number. It makes testing communication channels – like SMS or email – a lot simpler than testing push messages.
For example, with SMS messages, we always expect that one phone will receive a message depending on user consent, etc. Testing push messages is more complicated:
- The user might have more than one device, and they can also turn notifications on/off on some of them. This is something we can’t control
- The user can also log into another account on the same device, and this account may not have granted permission to receive push notifications.
- The user may have enabled push notifications on many devices and then suddenly revokes consent on his account – after which all devices must be disconnected from notifications
- And this is just the tip of the iceberg – remember that we must ensure that everything works fine on all three platforms
That’s why the biggest challenges while testing PWA push notifications are:
- Being 100% sure that user consents are always respected – it’s better if one user won’t receive push messages due to a bug than if another one receives a message they don’t want
- Checking if everything looks good on all devices (and there’s also the fact that users may also display notifications on their smartwatches)
- Android is not always “the same” – a lot depends on the phone manufacturer, Android launchers, etc. (iOS is easier because it’s not so customizable)
Conclusion
In the process of creating this feature, from the first research till the last tests and production release, our team members learned a lot about the technology that is commonly used by many of us privately (I think every smartphone user likes it when applications notify them about something new). Some parts of this project were full of surprises and tricky decisions.
If we had to mention the biggest of them, they would be:
- Limitations and features of iOS
- Developers are forced to use PWA
- iOS is not controlling how many of the same PWAs users will pin to their screen
- The similarity of iOS devices is very valuable for developers
- Android has a very wide range of different devices
- Every manufacturer has its own quirks, and it might be hard to reconcile them all, even in trivial cases like different desktop icon shapes
- Default browsers Push API is useful
- When there’s no need to broadcast messages to large groups of users, it might be a very useful feature in most modern browsers
- It is very simple to work with – we receive the endpoint, and we perform HTTP POST to this endpoint
- Testing and UX mindset
- This way of communication requires a substantially different approach than conventional ones like SMS or email
Ultimately, being a part of this project was a very pleasant experience, mainly due to its uniqueness and the number of surprises and challenges. We’ve learned a lot and crafted something we’re very proud of. If you have any questions regarding this project, reach out to us at alegowski@pretius.com or adolowa@pretius.com. If you need a team experienced in solving complex IT problems, write us at hello@pretius.com – we’ll be happy to help you with your project! You can also check some of the other informative content on the Pretius Blog:
- Camunda 7 vs Camunda 8: Migration and other possible scenarios
- Oracle SQLcl Project: The only CI/CD tool for APEX you need?
- Mendix tutorial: Start making apps using a powerful low-code platform
- Mendix React Client: Introduction and main changes compared to Dojo
- GitHub Copilot tutorial: We’ve tested it with Java and here’s how you can do it too
PWA push notifications FAQ
Here are answers to some common questions regarding Progressive Web Applications and push notifications.
Can a PWA send push notifications on iOS?
Yes, with the release of iOS 16.4 in 2023, you finally can.
Are PWAs still relevant in 2023?
Yes, in fact, more than ever – support for PWAs has only expanded in 2023 and 2024.
Can you send push notifications to all browsers?
You can send them to most of the popular browsers, such as Chrome, Edge, Firefox and Safari.