Integrations

PWA Push Notifications: How to Add Them (iOS and Android)

How PWA push notifications work on iOS and Android, what changed with iOS 16.4, and how to set them up with the Web Push API or a shorter FCM-based path.

EPEnder Puentes
7 min read
Share article
An installed PWA icon sending a push notification out to several devices, drawn in deep indigo with one amber accent.

Key takeaways

  • Android handles PWA push the direct way. Chrome can ask for permission in the browser, register a subscription, and receive messages with no install step.
  • iOS adds one condition. Since iOS 16.4, web push works after the user adds your site to the Home Screen and opens it from the icon, and you can only ask for permission after a tap.
  • The web-standard stack is a service worker, an HTTPS origin with a manifest, the Web Push API for the subscription, VAPID keys for auth, and a server to send. FCM is a common way to cover the send side across browsers.
  • Pushfire runs on FCM, so one project reaches iOS, Android, and Web push, and you manage subscribers and sequences in a console instead of writing a send server. It is made by the team behind this blog.

A PWA can send push notifications on both Android and iOS. The setup differs by platform, and the iOS side has a rule that trips people up: the site has to be installed to the Home Screen before it can ask for permission.

This walks through the pieces you need, the steps for Android and for iOS, the parts that tend to break, and a shorter path for teams that would rather skip running a delivery server.

What a PWA needs to receive push

Five things have to be in place before a notification can land:

  • An HTTPS origin. Service workers and push only run over HTTPS (localhost is exempt during development).
  • A web app manifest, so the browser knows how to install the site.
  • A registered service worker. It runs in the background and receives the push event even when the page is closed.
  • A push subscription through the Web Push API. When the user grants permission, the browser creates a PushSubscription with an endpoint that points at that browser's push service.
  • VAPID keys. Your public key goes into the subscribe call, and your server signs each send with the private key so the push service accepts it.

The flow is short once those exist. The user grants permission, the browser hands you a subscription, you store it on your backend, and your server posts an authenticated message to the endpoint. The service worker wakes up on the push event and calls showNotification.

Adding push on Android

Chrome on Android supports Web Push in the browser, so there is no install requirement.

1. Serve the site over HTTPS with a manifest and register a service worker.

2. Ask for permission from a user action, such as a button, then call Notification.requestPermission().

3. Subscribe once permission is granted:

4. Send the subscription object to your backend and save it against the user.

5. From your server, send a Web Push message (or send through FCM) to the endpoint. Handle it in the service worker:

Installing the PWA to the home screen is optional on Android and improves retention, though push works without it.

Adding push on iOS

Safari has supported Web Push for Home Screen web apps since iOS 16.4 (March 2023). Three conditions apply that do not exist on Android.

The user has to add the site to the Home Screen through Share, then Add to Home Screen, then open it from the icon so it runs in standalone mode. Push does not work in a Safari tab, and it does not work in Chrome or Firefox on iOS, because every browser there runs on WebKit.

You can only request permission after a user gesture inside the installed app. A prompt on page load gets rejected. Safari also has no automatic install banner, so you present your own instructions for Add to Home Screen.

Detect standalone mode before you show the opt-in:

Once the app is installed and the user taps your button, the subscribe flow is the same pushManager.subscribe call as Android. Safari 18.4 added Declarative Web Push, a simpler model that can render a notification straight from the push payload without your service worker running custom logic. It is worth adopting for basic notifications once you have confirmed the version baseline for your audience.

Where it tends to break

  • The service worker is not served from the root scope. If it sits in a subfolder, it cannot control the whole origin and push registration fails silently. Serve it from /.
  • Permission is requested on load. iOS rejects this outright, and Android users deny it more often. Tie the request to a tap.
  • The iOS standalone check is missing, so the opt-in shows in a Safari tab where it can never work.
  • The VAPID public key in the subscribe call does not match the private key on the server, so sends are refused.
  • iOS can drop a subscription after a long stretch of disuse. Treat re-subscribing as normal and re-register on app open.
  • A visitor who never installs on iOS cannot receive push at all, so keep an email or in-app fallback for that group.

Build it yourself or use a platform

The web-standard path is a good fit when you want full control, you support a small set of browsers, and you do not need a console or scheduling. If all you want is raw delivery, FCM on its own covers the send side across browsers and is enough.

A managed platform fits when you want to store audience state, segment by tags or attributes, run timed sequences, and see delivery analytics without maintaining a send server per browser.

Pushfire is our product, so read this section with that in mind. It builds on FCM, which means one project reaches iOS PWAs, Android, and web push, and you skip the per-browser VAPID and endpoint plumbing. In the console you keep subscribers, tags, and segments, lay out sequences on a drag-and-drop canvas with Push, Wait, and Conditional nodes, and send one-off broadcasts. For Flutter or FlutterFlow PWAs, the pushfire_sdk package registers iOS, Android, and web in one install. For other stacks, you register your FCM web tokens as subscribers through the Pushfire API and fire workflows over the Execute Workflow API. The free tier runs to 5,000 subscribers with push only, and the Pro tier is $29 a month to 50,000 subscribers with email and SMS connectors and broadcasts (confirm current figures on the pricing page).

Pushfire is a weaker match when SMS is your primary marketing channel, when you need deep email-marketing tooling, or when you rely on years of retained analytics. A larger engagement platform is the closer fit there. If your backend is Supabase, the Supabase push guide covers the trigger side in more detail.

Frequently asked questions

Can a PWA send push notifications on iPhone?

Yes, from iOS 16.4 onward, after the user adds the site to the Home Screen and opens it as a standalone app. It does not work in a Safari tab or in other iOS browsers, since they all run on WebKit.

Do I need an app store to send PWA push?

No. Web push runs on the service worker and the Web Push API. On Android the browser subscribes directly. On iOS the only extra step is adding the site to the Home Screen first.

What is the difference between Web Push and FCM for a PWA?

Web Push is the browser standard: a subscription endpoint plus VAPID authentication. FCM is Google's service that wraps that protocol and gives you one API to reach Chrome, Safari PWAs, and Android from a single project. Many teams send through FCM so they do not have to manage each browser's endpoint themselves.

Why does my iOS PWA not receive notifications?

Usual causes are opening the site in a tab instead of from the Home Screen icon, requesting permission on page load instead of after a tap, a service worker that is not served from the root scope, or a VAPID key mismatch. iOS can also drop the subscription after long disuse, so handle re-subscribes on app open.

Does Pushfire replace the Web Push setup for a PWA?

It replaces the delivery server and the per-browser plumbing. You still register a service worker and ask for permission inside the app. Because Pushfire runs on FCM, once a device is a subscriber you send through workflows or broadcasts in the console rather than writing your own send code. For Flutter and FlutterFlow PWAs, the SDK handles registration for iOS, Android, and web.

Ship PWA push without a send server

Pushfire runs on FCM, so one project covers iOS, Android, and web push, and you build sequences on a canvas instead of coding delivery. Start on the free tier at pushfire.app.

PWA Push Notifications: iOS and Android Setup Guide | PushFire