> For the complete documentation index, see [llms.txt](https://docs.amply.tools/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amply.tools/recipes/soft-push-permission.md).

# Soft push permission

Ask for push permission inside a custom popup first, so users who would decline never see the OS prompt.

**Use this when** push is core to your retention strategy and the stock "allow notifications" rate is under 50%. **Don't use this when** you do not have a clear value story for push. Pre-asking for nothing-in-particular is worse than the default flow.

## Goal

The OS push prompt can only be shown once. If the user taps "Don't Allow," they are effectively unreachable forever — pushing them into app settings to flip it back is not a retention strategy. This recipe shows your own popup first, with copy that explains what the user gets. Only users who tap "Yes, notify me" trigger the real OS prompt. The ones who would have tapped "Don't Allow" are silently queued for a better moment.

## Setup

### In the dashboard

* Create a campaign `push-softask`.
* Trigger: event `ValueMomentReached` — not session start, and not right after install. Wait until the user has seen something worth pushing about.
* Conditions: `push_permission_status = "unknown"` (never asked yet).
* Action: fire a deeplink to your in-app soft-ask popup, e.g. `yourapp://popup/push-softask`. The popup presents a clear value prop ("Get daily streak reminders?") and two buttons: "Yes, notify me" / "Not now". See [Custom popups](/user-guide/custom-popups.md) for the popup-as-deeplink pattern.
* The app handles branching locally:
  * "Yes, notify me" → the app tracks `PushSoftAskApproved` and calls the OS prompt.
  * "Not now" → the app tracks `PushSoftAskDeclined`. The OS prompt is not called.
* Frequency: once per user until declined, then one retry 14 days later if value has been delivered since (use a `push_softask_declined_at` attribute in the audience filter).

### In the app (engineering hand-off)

Note: `session_count` is not a built-in targeting attribute — if you gate the campaign on session count (for instance, to wait past a new-user window), the app must increment and set it as a custom property on each session start, e.g. `amply.setCustomProperty("session_count", n)`.

* Listen for the approved event and call the OS prompt only then:

  ```swift
  // on PushSoftAskApproved
  UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
    amply.setCustomProperty(key: "push_permission_status", value: granted ? "granted" : "denied")
  }
  ```
* On "Not now," keep `push_permission_status = "unknown"` (the OS prompt is preserved for later) and record the decline time so the 14-day retry window can be computed: `amply.setCustomProperty("push_softask_declined_at", now)`.
* Track the soft-ask outcome for analysis:

  ```swift
  amply.track("PushSoftAskShown")
  amply.track("PushSoftAskApproved")
  amply.track("PushSoftAskDeclined")
  ```

## How it runs

1. User installs the app. No push prompt fires. `push_permission_status = "unknown"`.
2. User uses the app and hits a meaningful moment. App tracks `ValueMomentReached`.
3. Amply evaluates event-triggered campaigns. `push-softask` matches.
4. Custom popup appears: "Get daily streak reminders?" with two buttons.
5. User taps "Yes, notify me." App fires `PushSoftAskApproved`. The OS prompt appears. User taps "Allow." `push_permission_status = "granted"`.
6. Parallel path: user taps "Not now." App fires `PushSoftAskDeclined`. The OS prompt never runs. Two weeks later, after another value moment, the campaign can re-match once with a different copy line.

## Metrics to watch

* Net push opt-in rate — soft-ask approved AND OS granted — compared to the rate you get by calling the OS prompt directly.
* Soft-ask show rate per user. If the popup fires too close to install, the whole gain vanishes.
* Decline-then-accept rate on the 14-day retry. If this is non-zero, the retry is worth keeping.
* Push-driven session count after rollout. The reason you do this is downstream sessions, not the permission number itself.

## Related

* [Custom popups](/user-guide/custom-popups.md) — building the soft-ask popup
* [Campaigns](/user-guide/campaigns.md) — event-triggered campaigns
* [Tracking events](/developer-guide/tracking-events.md) — firing the soft-ask events
* [User attributes](/concepts/user-attributes.md) — storing permission state as a user attribute
* [Campaign delivery](/concepts/campaign-delivery.md) — frequency caps and retry windows
* [AI-assisted integration](/getting-started/ai-assisted-integration.md) — describe this campaign in plain language and have your AI assistant build it


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amply.tools/recipes/soft-push-permission.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
