Blog · Product

When to ask for notification permission without getting blocked

A "Block" in the browser dialog is close to permanent. When to ask for notification permission, what to say first, and how to help users who already blocked you.

Leer en español

Ask for notification permission right after the user does something that makes an alert useful, never on page load, and always with your own message before the browser's dialog. That dialog is close to single-use: once the user clicks "Block", your site loses the channel until they change it in their settings themselves.

In short:

  • Permission has three states: default, granted and denied. Once it's denied, you can't ask again.
  • Firefox and Safari require the request to come from a user gesture, and Chrome shows a quieter UI to sites with very low acceptance rates.
  • Use two steps: your own prompt that explains the benefit and, only if the user agrees, the browser's dialog.
  • Ask at high-intent moments: tracking an order, waiting for an export, watching a price.
  • If you're already blocked, don't push: explain how to unblock when the user goes looking.

Why a "Block" is almost permanent

Notification.permission can be default (no decision yet), granted or denied. While it's default, you can ask with Notification.requestPermission() or when subscribing with pushManager.subscribe(). But as soon as the user picks "Block", the state becomes denied and every new request resolves to denied instantly, without showing anything. No code change or redesign fixes that: only the user can, from the site settings.

Browsers also penalize bad habits:

  • Firefox, since version 72, only shows the dialog if the request comes from a user gesture (a click, tap or key press). Otherwise it rejects the request and leaves a small icon in the address bar.
  • Safari, on Mac and iPhone, requires a user gesture too.
  • Chrome, since version 80, replaces the dialog with a quiet indicator in the address bar for sites with very low acceptance rates and for users who usually deny these requests.

Asking the moment someone lands is the fastest route to that quiet UI. Google sums it up in its permissions best practices: ask after an interaction, once the user understands why.

The two-step pattern: your prompt first

The fix is to split the question in two. First you show your own prompt, such as a banner, a card or an inline button, explaining what you'll send. That prompt costs nothing: if the user says "Not now", the browser permission stays default and you can offer it again later. Only when they say yes do you trigger the browser dialog, which now arrives with context and a decision that's mostly made.

const SNOOZE_DAYS = 14;

function shouldOffer() {
  if (!('PushManager' in window) || Notification.permission !== 'default') return false;
  const snoozedAt = Number(localStorage.getItem('push-snoozed-at') || 0);
  return Date.now() - snoozedAt > SNOOZE_DAYS * 86400000;
}

async function onAccept() { // click on "Notify me" in your prompt
  const permission = await Notification.requestPermission();
  if (permission === 'granted') await subscribeAndSave();
}

function onNotNow() { // click on "Not now"
  localStorage.setItem('push-snoozed-at', String(Date.now()));
}

onAccept runs inside the click, so it meets the gesture requirement in every browser. subscribeAndSave() is your function that creates the subscription and sends it to your server; for a refresher on what happens there, see what Web Push is.

When to ask: high-intent moments

The best moment comes right after an action that makes the value of an alert obvious. A few examples:

Type of siteMomentPrompt copy
Online storeAfter an order is confirmed"Want us to tell you when it ships and when it arrives?"
Online storeOn an out-of-stock product page"Notify me when it's back in stock"
SaaS toolWhen starting an export or a long job"We'll let you know when it's done. You can close this tab."
Publication or blogAfter finishing an article in a section"Get new security articles as they're published"
BookingsAfter booking an appointment"We'll remind you the day before"

They all share one thing: the user just showed interest in something that will happen later, and the prompt promises exactly that. Compare it with a generic banner on the homepage two seconds after arrival, when the visitor doesn't even know what you sell yet.

As a rule of thumb, don't offer it on a new visitor's first page view, don't show it at the same time as the cookie banner, and don't repeat it to someone who just said "Not now".

What to say in your prompt

A good prompt answers three questions in two lines: what will I get, how often, and how do I turn it off. Compare:

  • Weak: "Do you want to receive notifications?" with "Yes" and "No" buttons.
  • Better: "We'll notify you when your order leaves the warehouse and when it's out for delivery. Just those two alerts." with "Notify me" and "Not now" buttons.

A few rules that hold up:

  • The yes button describes the action ("Notify me", "Turn on delivery alerts"), not a generic "OK".
  • The alternative is "Not now", not "No thanks, I'd rather miss out on deals". Guilt-trip buttons breed distrust.
  • Don't imitate the browser or operating system dialog: users feel tricked when the real one shows up.
  • If you promise a frequency, stick to it.

If they already blocked you: helping them unblock

When Notification.permission is denied, hide your prompt and the subscribe button; showing them only causes frustration. But if the user goes looking for alerts, say in their account settings, explain how to undo it:

  • Chrome and Edge: the icon to the left of the address, then site settings, and set Notifications to "Allow".
  • Firefox: the permissions icon in the address bar, to clear the block.
  • Safari on Mac: Safari > Settings > Websites > Notifications.
  • iPhone, with the site installed: Settings > Notifications > the site's name.

After the change, reloading the page shows granted, and you can subscribe them without any dialog. A different case is when the user closes the dialog without choosing: the state stays default and technically you can ask again, but Chrome may block the request for a while if it's dismissed several times in a row. Treat that dismissal as a "Not now".

Measure acceptance and adjust

Without data, everything above is a hunch. Track five events: prompt shown, prompt accepted, "Not now", permission granted and permission denied. From those you get two rates that tell you different things:

  • Prompt acceptance (accepted over shown): tells you whether the moment and the copy are convincing.
  • Browser grant rate (granted over accepted): should be close to everyone. If it isn't, something between your prompt and the dialog is confusing people.

Compare by page and by moment: the same prompt can work great after an order and terribly on the homepage. If you use castly, the prompt is configured per project in the dashboard: copy in Spanish and English, position, delay, from which page view, on which paths and how many days to wait after "Not now". The SDK only shows it while permission is still default, so you can test different moments without a deploy; details are in the opt-in prompt docs.

Frequently asked questions

Can I ask on page load if the user already knows my site?

You can, but you shouldn't. Firefox and Safari won't even show the dialog without a user gesture, and in Chrome a low acceptance rate can push your site into the quiet UI. Even with loyal users, a button in the right place works better.

Does any click count as a user gesture?

Technically yes, but hijacking an unrelated click, like the cookie banner or a menu, feels like a trick. The click should be the answer to a question about notifications.

How many times can I show my own prompt?

There's no technical limit, since it's your UI. As a rule of thumb, wait one to several weeks after a "Not now", and stop offering it proactively after two or three refusals; a toggle in account settings can stay available.

What should I do with users who already granted permission?

Don't show them any prompt. On each visit, check with pushManager.getSubscription() that their subscription still exists and, if it's gone, offer to turn it back on with a button: with permission already granted, they won't see a browser dialog.

Does it work the same way on iPhone?

The pattern is the same, but on iPhone and iPad the permission only exists inside the site once it's installed to the Home Screen. Before your prompt you need one more step: explaining installation. We cover it in web push on iPhone.

Put it into practice with castlyWeb and PWA push notifications for developers: an SDK under 3 KB, a REST API and delivery logs for every device. Free up to 10,000 pushes a month.
Create a free account →

Send your first push notification today.

Create a project, add the SDK and send with one API call. Free to start.

Create a free account →