> For the complete documentation index, see [llms.txt](https://docs.buildnatively.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildnatively.com/natively-platform/features/notifications/onesignal-push-notifications.md).

# OneSignal - Push Notifications

## What are OneSignal Push Notifications?

Natively provides built-in support for [OneSignal](https://onesignal.com/) to handle push notification delivery for your app. OneSignal manages device registration and targeting through its own dashboard, and you send notifications either directly from the OneSignal dashboard or via the OneSignal REST API.

{% hint style="warning" %}
We do not currently support Rich Push Notifications (notifications containing action buttons or images). This feature will be added soon.
{% endhint %}

{% embed url="<https://youtu.be/C2wyJIFsKYc>" %}

## Prerequisites

{% hint style="success" %}
This feature requires the **Unlimited** or **Lifetime** plan. [See all plans](/getting-started/subscription-plans.md)
{% endhint %}

* A [OneSignal](https://onesignal.com/) account.
* **iOS:**
  * An [Apple Developer](https://developer.apple.com/account) account.
  * Your iOS app is already [published](/natively-platform/app-info/ios-build.md) in the Natively Dashboard.
* **Android:**
  * A [Firebase](https://firebase.google.com/) account.
  * Your Android app is already [published](/natively-platform/app-info/android-build.md) in the Natively Dashboard.

## OneSignal Configuration

### Pre-OneSignal Configuration

{% tabs %}
{% tab title="Android" %}
To send push notifications to Android devices, OneSignal requires **Firebase Cloud Messaging (FCM) credentials**.

{% stepper %}
{% step %}

#### Create or open your Firebase Project

1. Go to the [Firebase console](https://console.firebase.google.com/).
2. If you don’t have a project yet, click **Create a project** and complete the setup.
3. If you already have a project, **select it**.
   {% endstep %}

{% step %}

#### Confirm Firebase Cloud Messaging API v1 is enabled

While in the **Project Overview** page, select **Settings > General** from the left sidebar, then go to the **Cloud Messaging** tab.

{% hint style="success" %}
**Firebase Cloud Messaging API (V1)** is enabled by default for most projects.&#x20;
{% endhint %}

If it shows as disabled:

1. Click on the 3-dots menu.
2. Click **Manage the API in Google Cloud Console**.
3. Click **Enable** in the Google Cloud Console. Wait a few minutes for the change to reflect in Firebase.
   {% endstep %}

{% step %}

#### Generate a Service Account JSON file

While on the **Project Overview** page, select **Settings > General** from the left sidebar, then go to the **Service Accounts** tab:

1. At the bottom, click **Generate new private key**.
2. Confirm by clicking **Generate key** in the popup.
3. **Save** the `.json` file in a secure location.&#x20;

You'll need it for [OneSignal Dashboard Configuration](#onesignal-dashboard-configuration).
{% endstep %}
{% endstepper %}
{% endtab %}

{% tab title="iOS" %}
To send push notifications to iOS devices, OneSignal requires the **Push Notifications** **App Capability** enabled on your Bundle ID and an **APNs authentication key** from your Apple Developer account.

{% stepper %}
{% step %}

#### App Capabilities Configuration

{% hint style="info" %}
App capabilities define what system-level features your app is allowed to use on iOS. Before Natively can include the **OneSignal Push Notifications** feature in your build, the **Push Notifications** capability must be explicitly enabled in your Apple Developer account for your app's Bundle ID.
{% endhint %}

1. Open your [Apple Developer](https://developer.apple.com/account) account and navigate to [Certificates, IDs & Profiles > Identifiers](https://developer.apple.com/account/resources/identifiers/list).
2. Select your app's Bundle ID.
3. Scroll down the **Capabilities** list and enable **Push Notifications**.
4. Click **Save** and confirm.
   {% endstep %}

{% step %}

#### Set up APNs Authentication Key

1. Open your [Apple Developer](https://developer.apple.com/account) account and navigate to [Certificates, IDs & Profiles > Keys](https://developer.apple.com/account/resources/authkeys/list).
2. Click **+** to register a new key.
3. Enter **Key Name**.
4. Select the **Apple Push Notifications service (APNs)** checkbox and click **Configure**.
5. In the **Environment** dropdown menu, select **Sandbox & Production** and click **Save**.
6. Click **Continue**, then **Register**.
7. **Download** the generated `.p8` key.

{% hint style="warning" %}
You can only download this file once, so save it securely. If you lose it, you'll need to revoke the key and generate a new one.
{% endhint %}
{% endstep %}

{% step %}

#### Gather your credentials

Collect:

* **Key ID** - located in the row of the key you just created. Make sure it matches the downloaded `.p8` file.
* **Team ID** - located in your [Apple Developer](https://developer.apple.com/account) account under **Membership details**.
* **Bundle ID** - located in your Natively Dashboard under **Publish** > **iOS Build** > **Bundle Identifier**.

You'll need these for [OneSignal Dashboard Configuration](#onesignal-dashboard-configuration).

<figure><img src="https://mintcdn.com/onesignal/9_Q1FZLh6C0BFLq-/images/docs/c8d0207041e7c277f7e4ca49a3f6100280ddcbf970fce9b720fddfbda6683bb6-p8.png?fit=max&#x26;auto=format&#x26;n=9_Q1FZLh6C0BFLq-&#x26;q=85&#x26;s=fc9c689b0880bda69813428ee7fdbe5f" alt=""><figcaption><p>Credentials to collect</p></figcaption></figure>
{% endstep %}
{% endstepper %}
{% endtab %}
{% endtabs %}

### OneSignal Dashboard Configuration

{% stepper %}
{% step %}

#### Create OneSignal App

1. Navigate to your [OneSignal dashboard](https://app.onesignal.com/apps) and click **New App/Website**.
2. Enter your application's name in the **OneSignal App Name** field.
3. Select the option to create a new organization and enter its name.
4. Choose either the **Apple iOS (APNs)** or **Google Android (FCM)** channel.
5. Click **Next**.

{% hint style="info" %}
If you have both an iOS and Android app for one website, you only need one OneSignal application with both platforms enabled.&#x20;

You can add the second platform later in your OneSignal app dashboard under **Settings** > **Push & In-App**.
{% endhint %}
{% endstep %}

{% step %}

#### Configure your platform

{% tabs %}
{% tab title="Google Android (FCM)" %}

1. Click **Select file** under **Service Account JSON** and upload the `.json` file you downloaded in the [Generate a Service Account JSON file](#android) step above.
2. Click **Save & Continue**.
3. In the **Select your target SDK**, select **Android Native**.
4. Click **Save & Continue**.
5. Copy your **App ID** and click **Done**.

{% hint style="warning" %}
The **OneSignal App ID** is the same for both iOS and Android.&#x20;

You can find it later in your OneSignal app dashboard under **Settings** > **Keys & IDs** > **OneSignal App ID**.
{% endhint %}
{% endtab %}

{% tab title="Apple iOS (APNs)" %}

1. Choose **.p8 Auth Key (Recommended)** under **APNs Authentication Type**.
2. Provide the following:
   * `.p8` **file** - the private key file you downloaded in the [Set up APNs Authentication Key](#ios) step above.
   * **Key ID**, **Team ID**, and **App Bundle ID** - gathered in the [Gather your credentials](#ios) step above.
3. Click **Save & Continue**.
4. In **Select your target SDK**, select **Native iOS**.
5. Click **Save & Continue**.
6. Copy your **App ID** and click **Done**.

{% hint style="warning" %}
The **OneSignal App ID** is the same for both iOS and Android.&#x20;

You can find it later in your OneSignal app dashboard under **Settings** > **Keys & IDs** > **OneSignal App ID**.
{% endhint %}

{% hint style="info" %}
When configuring Apple iOS (APNs), you'll see an **Enable iOS 12 direct to history** checkbox. This controls whether **iOS Provisional Notifications** are enabled - notifications that can appear quietly in Notification Center before the user explicitly grants permission. This setting lives entirely in OneSignal's dashboard, not in the Natively Dashboard. See [OneSignal's Provisional Push Notifications docs](https://documentation.onesignal.com/docs/en/ios-provisional-push-notifications) for details.
{% endhint %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## Natively Dashboard Setup

Before proceeding, make sure you have completed the [OneSignal Configuration](#onesignal-configuration) steps above.

1. Open your Natively app dashboard and navigate to **Features** > **Notifications** > **OneSignal**.
2. Toggle the feature to **Enabled**.
3. Enter the **OneSignal App ID**.
4. Enter the **Permission Description**.
5. *(Optional)* Adjust the **Automatically request push permission on app launch** checkbox.
6. Click **Save**.
7. Rebuild your app(s).

{% hint style="info" %}
The **Permission Description** is the text shown to users when the OS asks them to grant **notification** access. Explain clearly why your app needs this permission - for example: "We'll send you push notifications when your order ships."
{% endhint %}

{% hint style="info" %}
The **Automatically request push permission on app launch** is enabled by default, triggering the system permission prompt immediately after the user launches the app. Disable it if you'd rather request permission later, at a more relevant moment in your app's flow.
{% endhint %}

{% hint style="warning" %}
You must rebuild your app for these changes to take effect.
{% endhint %}

## Implementation

Choose your integration method below: **Bubble.io Plugin** (No-Code), **JavaScript SDK** (Code), or **AI Agents** (for AI-powered editors like Lovable, Base44, and Replit).

### Initialization

{% tabs %}
{% tab title="Bubble.io Plugin" %}
**Check Plugin**

Before starting, verify if the Natively plugin is already installed in your Bubble project.

1. Open your Bubble editor and navigate to the Plugins tab in the left sidebar.
2. **Check Installed Plugins:** Look through your list of installed plugins for "Natively iOS & Android app builder".
   * If it IS installed: Check the version number. If an update is available (e.g., you see a button saying "Update"), click it to ensure you have the latest features and bug fixes.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FmfnSUug82IdnxOAoBrak%252Fnatively_app_builder_bubble_plugin_update.png%3Falt%3Dmedia%26token%3Dc193f69f-b03b-4be4-b80b-f34ba37ac212&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=a89e4510&#x26;sv=2" alt=""><figcaption></figcaption></figure>

* If it is NOT installed: Click the + Add plugins button, search for "Natively", and click Install.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FC5rA42yQHcN1uGKFbzmF%252Fnatively_app_builder_bubble_plugin.png%3Falt%3Dmedia%26token%3Dd9706d9b-dbe8-459b-b9b3-5667648aa4b7&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=9aae2297&#x26;sv=2" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="JavaScript SDK" %}
**Check SDK**

Before writing any logic, ensure the Natively SDK is correctly installed and up-to-date in your codebase.

1. Open your project's main HTML file (or header settings) and look for the Natively script tag inside the `<head>` section.
2. Install/Update: If missing or outdated, add the following code. You can specify the SDK version in the URL (e.g., `@2.26.0`).

```javascript
<head>
  <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script>
</head>
```

{% hint style="info" %}
To ensure you are using the most up-to-date version, check the [Natively GitHub releases page](https://github.com/buildnatively/js-sdk/releases) for the latest version number.
{% endhint %}
{% endtab %}

{% tab title="AI Agents" %}
**Initialize the SDK**

AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features. Before implementing any feature, the Natively SDK must be initialized in your project.

Copy the line below and paste it into your AI agent to check and set up the Natively SDK in your project.

```
Check if the following Natively SDK script is present in the <head> of index.html. If missing or outdated, add it: <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script><script>function nativelyOnLoad() { window.natively.setDebug(true); console.log("✅ Natively SDK loaded successfully."); }</script> For reference: https://docs.buildnatively.com/guides/integration/how-to-get-started https://github.com/buildnatively/js-sdk/releases
```

{% endtab %}
{% endtabs %}

### &#x20;Setup logic

{% tabs %}
{% tab title="Bubble.io Plugin" %}

### \[Element] Natively - Push Notifications (OneSignal)

{% hint style="warning" %}
This element must be set to **Visible on page load** to initialize correctly. It should be placed directly on the page root and not inside hidden containers, such as Popups, Floating Groups, Group Focus elements, or Repeating Groups. To hide the element from your UI, you may set its dimensions to 0x0 px.
{% endhint %}

#### Events:

* **OneSignal Player ID Updated** - fires whenever the Player ID is successfully retrieved from OneSignal.
* **Permissions Authorized** - fires when the user taps **Allow** on the native system permission dialog.
* **Permissions Denied** - fires when the user taps **Don't Allow** on the native system permission dialog.
* **Permission Status Updated** - fires whenever the device's notification settings change.
* **External ID Updated** - fires after an External ID is successfully set, updated, or removed.
* **External ID Error** - fires if an operation involving an External ID fails.

#### States:

* **Permission Status** - Yes/No. `Yes` if the user has granted notification permissions.
* **OneSignal PlayerId** - the unique identifier for the current device, used to target this specific user (equivalent to the Subscription ID under **Audience** > **Subscriptions** in your OneSignal dashboard).
* **OneSignal ExternalId** - the unique identifier for the current user, used to target this specific user.
* **Error message** - the text of the error encountered during a failed operation (e.g. a failed External ID update).

#### Actions:

* **Request the user's push notification permission** - triggers the native system dialog using the Permission Description defined in your dashboard:
  * **Open Settings** - if permission was previously denied, displays a native alert offering to take the user directly to system settings to enable notifications.
* **Get the user's OneSignal PlayerId** - manually refreshes the **OneSignal Player ID** state.
* **Get the user's push notification permission status** - re-checks the device's notification settings and updates the **Permission Status** state.
* **Get the user's External ID** - fetches the custom ID currently associated with this Player ID in OneSignal.
* **Set the user's External ID** - links a custom ID to this OneSignal Player ID.
* **Remove the user's External ID** - unlinks the custom ID from the current Player ID.
  {% endtab %}

{% tab title="JavaScript SDK" %}

```javascript
// ============================================================================
// NATIVELY NOTIFICATIONS (ONESIGNAL) - DOCUMENTATION & EXAMPLES
// ============================================================================

const notifications = new NativelyNotifications();

// ============================================================================
// ALL AVAILABLE METHODS
// ============================================================================
// notifications.getPermissionStatus(callback)
//   - Checks if the user has currently granted push notification permissions.
//
// notifications.requestPermission(fallbackToSettings, callback)
//   - Prompts the native OS permission dialog.
//   - fallbackToSettings: boolean — if true, prompts the user to open OS settings if previously denied.
//
// notifications.getOneSignalId(callback)
//   - Retrieves the unique OneSignal Player ID for this device.
//   - In the OneSignal dashboard, this is labeled as the Subscription ID.
//
// notifications.getExternalId(callback)
//   - Fetches the custom External ID linked to this Player ID in OneSignal.
//
// notifications.setExternalId({ externalId }, callback)
//   - Links a custom ID (e.g. your database User ID) to this Player ID in OneSignal.
//
// notifications.removeExternalId(callback)
//   - Unlinks the current custom External ID from this Player ID.

// ============================================================================
// CALLBACK RESPONSE FIELDS - getPermissionStatus
// ============================================================================
// resp.status: boolean — true if allowed, false if denied/undetermined

// ============================================================================
// CALLBACK RESPONSE FIELDS - requestPermission
// ============================================================================
// resp.status: boolean — true if the user just tapped Allow, false if Don't Allow

// ============================================================================
// CALLBACK RESPONSE FIELDS - getOneSignalId
// ============================================================================
// resp.playerId: string — the device's OneSignal Player ID (e.g. "a301a5b5-ac6e-...")

// ============================================================================
// CALLBACK RESPONSE FIELDS - getExternalId / setExternalId
// ============================================================================
// resp.externalId: string — the linked External ID, if present
// resp.error: string — present if the operation failed
// resp.message: string — present if the operation failed

// ============================================================================
// CALLBACK RESPONSE FIELDS - removeExternalId
// ============================================================================
// A null/empty response indicates the External ID was successfully removed.
// resp.error: string — present if the operation failed
// resp.message: string — present if the operation failed

// --- Push Notifications. Permissions & Player ID. Start ---

const permission_check_callback = function (resp) {
  console.log(resp.status); // true if allowed, false if denied/undetermined
};

const permission_request_callback = function (resp) {
  console.log(resp.status); // true if the user just tapped Allow, false if Don't Allow
};

const player_id_callback = function (resp) {
  console.log(resp.playerId); // e.g. "a301a5b5-ac6e-..."
};

const fallbackToSettings = false; // true shows a custom alert offering to open OS settings if previously denied

notifications.getPermissionStatus(permission_check_callback);
notifications.requestPermission(fallbackToSettings, permission_request_callback);
notifications.getOneSignalId(player_id_callback);

// --- Push Notifications. Permissions & Player ID. End ---


// --- Push Notifications. External ID Management. Start ---

notifications.getExternalId((resp) => {
  const res = Array.isArray(resp) && resp.length > 0 ? resp[0] : null;

  if (res && res.externalId) {
    console.log("Current External ID:", res.externalId);
  } else {
    console.warn((res && (res.error || res.message)) || "No External ID found.");
  }
});

notifications.setExternalId({ externalId: "user_db_id_12345" }, (resp) => {
  if (resp && resp.externalId) {
    console.log("External ID set successfully to:", resp.externalId);
  } else {
    console.error((resp && (resp.error || resp.message)) || "Failed to set External ID.");
  }
});

notifications.removeExternalId((resp) => {
  if (resp && (resp.error || resp.message)) {
    // Failure — an error or message is present
    console.error("Failed to remove External ID:", resp.error || resp.message);
  } else {
    // Success — a null/empty response indicates the ID was successfully removed
    console.log("External ID removed successfully. Device is now anonymous.");
  }
});

// --- Push Notifications. External ID Management. End ---
```

{% endtab %}

{% tab title="AI Agents" %}
AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features.

Copy the line below and paste it into your AI agent.

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively Push Notifications (OneSignal) SDK: const notifications = new NativelyNotifications(); notifications.getPermissionStatus(callback) checks current permission status, returning resp.status (boolean). notifications.requestPermission(fallbackToSettings, callback) prompts the native permission dialog — fallbackToSettings: boolean, if true offers to open OS settings when previously denied — returning resp.status (boolean). notifications.getOneSignalId(callback) retrieves the device's OneSignal Player ID, returning resp.playerId (also labeled Subscription ID in the OneSignal dashboard). notifications.getExternalId(callback) and notifications.setExternalId({ externalId }, callback) manage a custom External ID linked to this Player ID, returning resp.externalId on success or resp.error/resp.message on failure. notifications.removeExternalId(callback) unlinks the External ID — a null/empty response indicates success, while resp.error/resp.message indicate failure. For reference: https://docs.buildnatively.com/natively-platform/features/notifications/onesignal-push-notifications
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Request push notification permission after the user completes onboarding, and link their account with an External ID on login".
{% endhint %}
{% endtab %}
{% endtabs %}

### How to use

{% hint style="danger" %}
Client-side calls from the Natively OneSignal Push Notifications SDK can be tested directly in the Natively Preview app, but actually [sending notifications](#sending-notifications) should always happen server-side, via your backend - not from the client.
{% endhint %}

#### Time the permission request carefully

Avoid overwhelming users with a permission prompt the moment the app opens. Request push notification access at a high-value moment in the user journey instead — during onboarding, or right after a user opts into a feature that requires alerts (e.g., "Notify me when my order ships").

#### Sync devices to users on login

To ensure users receive notifications reliably across all their devices:

1. **Verify Player ID on login.** Retrieve the current device's Player ID and compare it against the ID stored in your database for that user.
2. **Register new devices.** If the current Player ID isn't in your database, the user is likely on a new device - request push permissions and register it.
3. **Sync via External ID.** Once registered, call `setExternalId` with your internal User ID, so OneSignal knows this device belongs to your user.
4. **Maintain your database.** Save the latest Player ID to your user record - consider storing these as a list to support multiple active devices (e.g. iPhone and iPad).

{% hint style="warning" %}
If a user grants permission during their current session, the updated status is reflected in OneSignal starting from the next app launch, not immediately.
{% endhint %}

Think of the Player ID as the device's digital address - without saving it, your server-side logic won't know where to deliver the notification.

## Sending Notifications

Once a user's Player ID or External ID is saved, you can send them a push notification from the **OneSignal dashboard**, the **OneSignal REST API**, or - if you're on **Bubble** - directly from a Backend Workflow.

{% tabs %}
{% tab title="Bubble.io Plugin" %}
{% hint style="warning" %}
To authorize push notifications from your Bubble workflows, navigate to the Plugin Settings tab and enter your OneSignal REST API Key into the onesignal\_apiKey field and the App ID into the onesignal\_appId field.
{% endhint %}

Detailed instructions on creating and managing your API keys can be found in the [OneSignal Documentation](https://documentation.onesignal.com/docs/accounts-and-keys).

<figure><img src="/files/3Y8RtVSlsWM9zZBilAn5" alt="" width="375"><figcaption></figcaption></figure>

**Requesting Permissions**

Trigger the permission request when a user explicitly opts in to receive notifications (e.g., flipping a "Enable Notifications" toggle).

* Existing Permissions: If the user has already granted access, the system popup will not reappear. Instead, the element will silently refresh the `OneSignal PlayerId` state.
* Handling Denials (Open Settings): If the Open Settings option is enabled and the user previously denied permissions, a dialog will appear. This prompt invites the user to navigate to their device settings to manually re-enable notifications for your app.

<figure><img src="/files/dJhx6lPNGu6INVu9h2pl" alt="" width="179"><figcaption></figcaption></figure>

<figure><img src="/files/32k142hDFthVmBvppNKC" alt="" width="228"><figcaption></figcaption></figure>

**Capturing the Player ID**

To send targeted notifications, you must map the device's unique identifier to your user records.

* Create a workflow for the event **Notification permission authorized**. Within this workflow, trigger the action **Get the user's OneSignal Player Id**. This ensures that as soon as a user grants access, the app actively fetches their new identifier.
* Listen for the **OneSignal Player Id updated** event. This event fires automatically once the identifier is successfully received from the OneSignal servers.
* Within the "Updated" event workflow, save the `OneSignal Player Id` state's value to the Current User in your database.

Think of the Player ID as the "digital address" for the device. Without saving this address to your database, your backend workflows will not know where to deliver the notification.

<figure><img src="/files/npU2nhkagXkt2AAayqiO" alt="" width="178"><figcaption></figcaption></figure>

<figure><img src="/files/Ce4Oy0DPTC5ATqT7z4MY" alt="" width="180"><figcaption></figcaption></figure>

**Sending a Notification**

In this scenario, we will schedule an automated push notification to be sent three days after a customer orders a product, informing them that their order is on its way.

1\. The Trigger (Client-Side) When a customer completes a purchase (e.g., `new_order_placed`), trigger a Backend Workflow to run with a 3-day delay. You must pass the user's Player ID and the Order Details to this backend workflow.

<figure><img src="/files/VlRSuMQ9FpwxvJCOcuGH" alt="" width="178"><figcaption></figcaption></figure>

2\. The Execution (Backend Workflow) Create a backend workflow (e.g., `send_delivery_update`) that uses the OneSignal - User Single PlayerId - Send Push action.

Configure the following parameters:

* Player ID: The unique identifier retrieved from your database.
* Title & Message: "Your order is on its way!"
* Redirect URL: The specific internal page link (e.g., `https://example.com/orders/123`) that the app will open when the user taps the notification. This parameter is optional. If not provided, the app will open the App URL.

<figure><img src="/files/30OdsSyah2a0QwKibILB" alt="" width="181"><figcaption></figcaption></figure>

3\. The Result: Deep Linking When the user receives and taps the notification, the app intercepts the Redirect URL and automatically opens that specific page within the app, rather than just the home screen.

<figure><img src="/files/owQJWSjp8LWyHnd7dZmD" alt="" width="180"><figcaption></figcaption></figure>

**Using OneSignal Templates**

If you have pre-defined layouts in your OneSignal dashboard, you can trigger them by providing a Template ID.

* The Override Rule: When a Template ID is provided, it takes precedence over the Title, Subtitle, Message, and Redirect URL fields. Any content entered into those individual fields will be ignored in favor of the template's settings.
* Setup: Simply paste your Template ID (found in the OneSignal Dashboard under Messages → Templates) into the designated field in the OneSignal - User Single PlayerId - Send Push action.

<figure><img src="/files/W9S3L11EQPl2MojZcRJB" alt="" width="176"><figcaption></figcaption></figure>

<figure><img src="/files/eZ2VDE9whRoSXSbRgSNp" alt="" width="188"><figcaption></figcaption></figure>

**Targeting by OneSignal Segments**

Use segments to broadcast messages to specific groups of users based on their behavior, location, or custom tags. Use the **OneSignal - Segments - Send Push** action in your backend workflows to reach large audiences simultaneously.

* Included Segments: Enter the exact names of the segments you wish to target (e.g., `Active Users` or `Free Tier`). To reach your entire audience, use the default OneSignal segment name: `Total Subscriptions`.
* Excluded Segments: (Optional) Specify segments that should *not* receive the notification. For example, you can target `All Users` but exclude `Premium Subscribers` to send a specific upgrade promotion.
* Important: Segment names must match the spelling and capitalization used in your OneSignal dashboard exactly.

<figure><img src="/files/ELi50UfrYg5kXVbMJ86B" alt="" width="177"><figcaption></figcaption></figure>
{% endtab %}

{% tab title="OneSignal Dashboard" %}
**OneSignal Dashboard** - the simplest way to send a test or one-off notification to an individual device, segment, or your entire audience. See [OneSignal's Mobile push setup](https://documentation.onesignal.com/docs/en/mobile-push-setup) guide.
{% endtab %}

{% tab title="Backend (REST API)" %}
**OneSignal REST API** - send notifications programmatically from your backend. See [OneSignal's REST API](https://documentation.onesignal.com/reference/push-notification) for the full request/response schema or its [Server SDKs](https://documentation.onesignal.com/docs/en/server-sdk-reference) for other platforms.
{% endtab %}
{% endtabs %}

## Custom Notification Sound

{% stepper %}
{% step %}

#### Create a sound file

According to these rules - if the device can't find it, or the format isn't supported, it falls back to the default system sound:

* Filename **must** be `natively.wav`.
* Recommended length under 30 seconds; keep file size small, as large files may not play on some devices.
  {% endstep %}

{% step %}

#### **Natively Dashboard Configuration**

1. Open your Natively app dashboard and navigate to **Features** > **Notifications** > **OneSignal**.
2. Under **Notification custom sound**, select **Click to upload file** and upload your audio file.
3. Rebuild your app(s).

{% hint style="warning" %}
You must rebuild your app for these changes to take effect.
{% endhint %}
{% endstep %}

{% step %}

#### OneSignal Dashboard Configuration

{% tabs %}
{% tab title="Android" %}

1. In your **OneSignal Dashboard**, go to **Settings** > **Push & In-App** > **Android Notification Channels**.
2. Click **Add Group**, name it, and click **Submit**.
3. Click **Add Channel**, name it.
4. Set Importance to **Urgent** or **High** (required for the sound to trigger).
5. Select **Custom** under the **Sound** section and set it exactly to `natively`.
6. **Create** the channel.
7. Click on the created channel and copy the **Channel ID**.

To trigger a custom sound from your Bubble workflows, navigate to the **Custom Sound** section of your **Send Push** action, and enter the copied **Channel ID** in the **Android Channel ID** field.

To trigger a custom sound via the **OneSignal REST API**, include the `android_channel_id` parameter in your JSON payload, set to the copied **Channel ID**.&#x20;

{% hint style="warning" %}
Because Android "locks" channel settings, you must reinstall your app on your device for the new sound settings to take effect.
{% endhint %}

<div><figure><img src="/files/31OXEmQPNLk36wvzA18A" alt=""><figcaption><p>Step 1-2</p></figcaption></figure> <figure><img src="/files/b9pszCFk52A64RtJ4pUs" alt=""><figcaption><p>Step 3</p></figcaption></figure> <figure><img src="/files/CWNUcR5fMcj3WeoLoQae" alt=""><figcaption><p>Step 4-6</p></figcaption></figure> <figure><img src="/files/ktdAyE3clQMupsuD2xcN" alt=""><figcaption><p>Step 7</p></figcaption></figure></div>

<figure><img src="/files/CK5ShcRkjEkltTgAD0XQ" alt="" width="89"><figcaption><p>Bubble example</p></figcaption></figure>
{% endtab %}

{% tab title="iOS" %}
To trigger a custom sound from your Bubble workflows, navigate to the **Custom Sound** section of your **Send Push** action, and enter `natively.wav` in the **iOS Sound** field.

To trigger a custom sound via the **OneSignal REST API**, include the `ios_sound` parameter in your JSON payload, set to `natively.wav`.

<figure><img src="/files/qfx1zL4Z9nthmocNJaEr" alt="" width="88"><figcaption><p>Bubble example</p></figcaption></figure>
{% endtab %}
{% endtabs %}

{% endstep %}
{% endstepper %}

## Troubleshooting

<details>

<summary>Notifications don't arrive at all</summary>

Go through this checklist:

* Confirm OneSignal is enabled and the App ID is entered correctly in the Natively Dashboard under **Features** > **Notifications** > **OneSignal**.
* Confirm the app has been rebuilt after enabling or changing this configuration.
* Confirm the Player ID or External ID being targeted actually matches the intended user/device - check in **Audience** > **Subscriptions** in your OneSignal dashboard.
* Check for [network issues](https://documentation.onesignal.com/docs/en/notifications-show-successful-but-are-not-being-shown#network-and-connectivity) on the receiving device.
* Confirm the app has push permission granted - check [app push permissions](https://documentation.onesignal.com/docs/en/notifications-show-successful-but-are-not-being-shown#permission-and-subscription-status).
* On Android, confirm the relevant [notification category](https://documentation.onesignal.com/docs/en/notifications-show-successful-but-are-not-being-shown#android-notification-categories-disabled) isn't disabled.
* Confirm the device isn't in [Low Power Mode](https://documentation.onesignal.com/docs/en/notifications-show-successful-but-are-not-being-shown#low-power-mode-and-battery-optimization) or [Do Not Disturb](https://documentation.onesignal.com/docs/en/notifications-show-successful-but-are-not-being-shown#do-not-disturb-and-focus-modes).

</details>

<details>

<summary>Notifications don't arrive on iOS specifically</summary>

Your APNs authentication key may need to be regenerated and re-uploaded to OneSignal - see [iOS Pre-OneSignal Configuration](#ios) to generate a new `.p8` key if needed.

</details>

<details>

<summary>Notifications don't arrive on Android specifically, but only during development</summary>

Delete the app and reinstall it. This is a development-only quirk and won't recur after release to the store.

</details>

<details>

<summary>OneSignal shows an "Invalid Request" error when uploading the Service Account JSON file</summary>

OneSignal doesn't indicate the actual cause of this error. The generated Service Account JSON file needs the following roles to be accepted by OneSignal:

* **Firebase Admin SDK Administrator Service Agent** - `roles/firebase.sdkAdminServiceAgent` .
* **Firebase App Check Admin** - `roles/firebaseappcheck.admin` .
* **Service Account Token Creator** - `roles/iam.serviceAccountTokenCreator` .

Check the [Google Cloud IAM console](https://console.cloud.google.com/iam-admin/iam) and confirm your Firebase Service Account has these roles.

</details>

<details>

<summary>Permission status doesn't match what the user actually granted on iOS</summary>

If **Enable iOS 12 direct to history** (Provisional Notifications) is enabled in your OneSignal dashboard, iOS may silently grant limited, quiet delivery to Notification Center without the user ever seeing a permission prompt. Natively's SDK treats provisional permission as **not fully granted** - matching how permission behaves on your website - so `getPermissionStatus` may report notifications as disabled even though the user is receiving them quietly in Notification Center. If you don't need this quiet/provisional behavior and want your app to always request full notification permission (Sounds, Banners, and Notification Center all together), disable **Direct to History** in the OneSignal dashboard.

</details>

<details>

<summary>Notifications don't work in the Natively Preview app</summary>

Devices running the Preview app use a pre-configured sandbox environment and won't appear as active subscriptions in your OneSignal dashboard. To test your actual OneSignal integration, generate a full build of your app instead.

</details>

<details>

<summary>Custom notification sound doesn't play</summary>

Confirm the file is named exactly `natively.wav`, is under 30 seconds, and has a reasonably small file size.&#x20;

On Android, confirm **Importance** is set to **Urgent** or **High** on the notification channel, and that you've reinstalled the app after configuring the channel.

</details>

<details>

<summary>Not working in a web browser</summary>

This is a native feature and will not work in a standard web browser. Test on a real device using a Natively build.

</details>

[^1]: Replace this placeholder
