---
title: "Ask for permission after a clear action · Agent Wranglers"
url: https://agentwranglers.se/playbook/notifications/push-notifications/push-permission-in-context
updated: 2026-10-20
licence: "All rights reserved"
---

# Ask for permission after a clear action

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
- Rule: Ask for notification permission only after the person clicks a control that says what they will get. Never ask on page load.
- How: Show your own button first, such as "Tell me when my order ships". Call `Notification.requestPermission()` inside its click handler. Firefox and Safari ignore the call without a user action, and Chrome shows a muted prompt to sites that ask too early. A "Block" is close to permanent, because only the person can undo it in browser settings. On iPhone and iPad, web push works only after the site is added to the Home Screen, from iOS 16.4. Native apps follow the same idea before calling the platform's permission API.
- Check: A browser test loads every page with a fresh profile and records permission prompts. None appear before a click. A grep finds `requestPermission` only inside click handlers.

Example:

```js
document.querySelector('#notify-shipping').addEventListener('click', async () => {
  if (await Notification.requestPermission() !== 'granted') return showSettingsHint();
  const registration = await navigator.serviceWorker.ready;
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: VAPID_PUBLIC_KEY,
  });
  await fetch('/push/subscriptions', { method: 'POST', body: JSON.stringify(subscription), headers: { 'Content-Type': 'application/json' } });
});
```

```python
# Server side: store the subscription against the signed-in user, once per endpoint
@app.post("/push/subscriptions")
@login_required
def save_push_subscription():
    body = request.get_json()
    db.push_subscriptions.upsert(endpoint=body["endpoint"], keys=body["keys"], user_id=current_user.id)
    return "", 201
```

```sh
# Fails when the permission call sits outside a click or submit handler
grep -rn "requestPermission" src/ | grep -v -E "click|submit" && exit 1 || echo PASS
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/push-notifications/push-permission-in-context`.

- Next: [Send web push with VAPID and an encrypted payload](https://agentwranglers.se/playbook/notifications/push-notifications/web-push-vapid)
- [Push notifications](https://agentwranglers.se/playbook/notifications/push-notifications)
