When Should You Ask for Push Notification Permission?

Ask for push notification permission only after a visitor has done something that shows they want ongoing updates from you — never on page load, and never before they understand what they'd be signing up for. The browser's notification permission prompt is a native dialog, controlled entirely by the browser and never by your page's CSS or JavaScript, and in most browsers its outcome is cached permanently. Once someone clicks Block, no standard API lets your site show that dialog again, so a badly timed request can cost you that visitor's push channel forever.

This matters more than it looks like it should. A monitoring script, a CI pipeline, a support inbox, or a status page all eventually want one thing: a way to reach a human the moment something needs their attention. Push notifications are the only web-native channel that can do that without email, SMS, or a third-party chat app — but the permission model that makes push possible is unforgiving of bad timing, and there's no undo button for the browser's own memory of a Block.

What Is the Push Notification Permission Prompt?

The permission prompt is the small browser dialog — "pingwire.dev wants to send you notifications, Allow / Block" — that appears when a page calls the Notification API's requestPermission() method. It is rendered by the browser chrome, not the page, so you cannot style it, delay its buttons, or add explanatory copy inside it. The Notification API's requestPermission() resolves to exactly one of three values: granted, denied, or default (meaning the visitor closed the dialog without choosing). That three-state result is the entire API surface you get to react to, as the MDN Notification API reference documents. For the rest of the send pipeline — the service worker, the subscription object, the actual push message — see how web push works under the hood.

Why the Browser Owns This, Not You

Browsers moved permission out of page control specifically because sites abused it — auto-prompting on load became indistinguishable from a pop-up ad. The tradeoff is that you get one clean shot per visitor per browser profile, and the browser, not your code, decides whether you get a second one.

Why Does Timing the Permission Request Matter?

A visitor who hits Block because a prompt interrupted them mid-scroll is not choosing to reject your notifications specifically — they're closing an unexpected dialog. But the browser records it exactly the same as an informed refusal. There is no separate "annoyed dismissal" state; denied is denied. That's the entire argument for timing: you're not just asking for permission, you're spending a resource that doesn't replenish for that visitor.

Once a visitor chooses Block, no standard browser API lets a site show that prompt again on its own. The only way back is the visitor manually reopening the browser's own per-site permission settings — a page most people have never visited and will not think to visit because of your product.

When Should You Actually Ask for Permission?

Ask at the point where the value is concrete and the visitor just asked for something that implies ongoing updates. In practice, that means:

  1. Wait until after a meaningful action — creating an alert, finishing a signup, sending a first message — not on the landing page.
  2. Explain first, in your own UI, what they'll receive and how often, using a button you control before triggering the real browser prompt.
  3. Only call requestPermission() when the visitor clicks that button, so the real dialog appears attached to a decision they already made.
  4. Give them a working product without push, so declining costs them nothing and they can opt in later from settings.
  5. Never re-prompt automatically on a later visit if the state is already denied — check the state first and stop asking.

The pattern above is sometimes called a "pre-prompt": you ask your own UI first, and only call the browser's real API when the answer is already yes. It doesn't get you a second browser prompt after a Block, but it makes far fewer visitors reach Block in the first place, because the ones who click your explainer button already want it.

What Happens After a User Blocks Notifications?

The browser remembers the decision per origin, and your JavaScript can read the current state via Notification.permission before deciding whether to show your own "enable alerts" UI at all.

Permission stateWhat the browser doesWhat your code can do
defaultNo prompt has been answered yetShow your explainer UI, then call requestPermission() on click
grantedPush is allowed for your originSubscribe the service worker and start sending
deniedThe browser will not show the prompt againHide the push UI; offer email or another channel instead

Does Web Push Work the Same Way on iPhone and Android?

No, and this is the part that catches teams off guard late. Apple added Web Push support to Safari, but only for web apps the visitor has added to the iOS Home Screen — a platform restriction that has nothing to do with your code and cannot be worked around from JavaScript. A visitor browsing your site in Safari without installing it will never see a working notification prompt on iOS, no matter how well you time it. Android's Chrome, by contrast, supports the standard Push API directly in the browser tab, no installation required. If iOS reach matters to you, "add to Home Screen" has to be part of your onboarding, not an afterthought.

This is also where most teams discover that building push notification infrastructure themselves means solving two separate problems — the permission UX above, and the delivery plumbing (service worker, VAPID keys, a subscription store, a send queue) — before a single alert reaches anyone.

If what you actually need is a way for cron jobs, monitors, CI pipelines, and scripts to reach you, you don't have to solve the permission-UX problem for every source separately. You grant notification permission to Pingwire once, and after that every alert from any script or webhook arrives as a real push through a channel that's already approved — no per-integration prompt design, no re-earning consent for the fifth tool you wire up this month.

The Honest Tradeoff

Routing alerts through an existing PWA instead of building your own push stack means depending on someone else's send path. If that's a real concern, know that the underlying send is a plain HTTP API, and Pingwire is self-hostable, so the dependency is on the protocol, not a black box you can't inspect. For most teams the tradeoff still favors not re-solving permission UX, service workers, and VAPID key rotation for every internal tool that needs to reach a human.

How Do You Recover a Visitor Who Blocked Notifications?

You mostly don't, in-browser. The realistic options are: offer a different channel (email, a status page, a chat webhook) so the relationship doesn't die with one dialog; and, if the product is worth reinstalling for, a visible in-UI setting that links to the browser's own site-permission page with instructions, since your code cannot open it directly. Treat the first prompt as the one that counts, because for a meaningful share of visitors, it is. A granted permission is also not the end of the story — if push still isn't reliable after that, see why a web push notification doesn't arrive even with a granted subscription.

Create a free Pingwire account and grant notification permission once — then send yourself a test alert from curl, a cron job, or your CI pipeline and watch it arrive as a real push. It takes about a minute, and there's no separate prompt to design for the tenth script that wants to reach you after the first.

Frequently asked questions

Should a website ask for notification permission on the first page load?

No. Asking before a visitor has taken any action produces the highest rate of reflexive Block clicks, and most browsers cache that decision permanently for your origin. Wait until after a meaningful action, like finishing signup or creating an alert, so the request lines up with something the visitor already wants.

What happens if a user blocks notifications by mistake?

The browser stores the decision per site and will not show your prompt again automatically. The visitor has to open the browser's own site-permission settings and change it manually, a page most people never visit unprompted, so a misclick usually needs an in-UI explanation and a link to that settings page.

Does web push work the same way on iPhone and Android?

No. Android's Chrome supports the standard Push API directly in a browser tab. Safari on iOS only delivers web push to apps a visitor has added to their Home Screen, a platform restriction outside your code's control, so iOS reach depends on getting visitors to install the app first.

Can a website ask for notification permission more than once?

Only while the state is still 'default', meaning the visitor has never answered. Once the state is 'denied', calling requestPermission() again just returns 'denied' immediately with no dialog shown; there is no standard way to re-trigger the browser's own prompt after a Block.

Do I need to build my own push infrastructure to send browser notifications?

No. A service worker, VAPID keys, and a subscription store are required by the Push API spec either way, but you can avoid rebuilding them per project by routing alerts through an existing platform that already handles delivery, so your only remaining job is the permission-timing decision covered above.

Try Pingwire

Send your first alert in under 30 seconds — one HTTP call, straight to a chat and your phone.

Create a free account Read the API docs

More from the blog