Enable push notifications in a native iOS app
This guide walks you through enabling push notifications in your iOS app using the Acoustic Connect SDK. The SDK supports push delivery tracking — including notifications dismissed before the app opens — and rich media images such as banner thumbnails and expanded images.
Language: Swift. Push notifications are not supported in Objective-C apps.
Availability: Pro, Premium, and Ultimate
PrerequisitesHave an Apple Developer Program membership. Push notifications require a paid account. Required role: Account Holder or Admin.
Overview
- You — generate an APNs authentication key and share your push notification credentials with your Connect administrator
- Connect administrator — uploads your APNs credentials to Connect and sends you the app key and collector URL
- You — integrate the Connect SDK using the app key and collector URL
- You — configure push notifications in the Apple Developer portal
- You — configure push notifications in Xcode
- You — add code to request notification permission from your users
Step 1: Get an APNs authentication key
Connect uses token-based APNs authentication. A single .p8 key works across all apps in your team.
- In your Apple Developer account, go to Certificates, Identifiers & Profiles > Keys > +.
- Enter a name (for example, "Acoustic Connect APNs") and enable Apple Push Notifications service (APNs).
- Click Configure next to Apple Push Notifications service (APNs) and set Environment to Sandbox & Production unless your security team requires tighter scoping. The key is accepted at both APNs hosts regardless of this selection — the meaningful environment match is between your build's
aps-environmententitlement and the environment your Connect administrator selects in Connect (see Step 2). This setting cannot be changed once saved. - Click Save > Continue > Register.
- Download the
.p8file — Apple only allows you to download it once. - Note the Key ID shown on the confirmation page.
- Note your Team ID — visible in the top-right of the portal or under Membership.
Step 2: Share push notification credentials with your Connect administrator
Share the following with your Connect administrator so they can register your app's push notification credentials in Connect. They will send you back the app key and collector URL you need for the next step.
| Credential | Where to find it |
|---|---|
| Encryption key | The .p8 file you just downloaded |
| Key ID | The confirmation page, or the file name |
| Team ID | Top-right of the Apple Developer portal, or under Membership |
| Bundle ID | Your Xcode project |
| Environment | Sandbox for debug builds, Production for Release builds (App Store and TestFlight). Xcode sets the aps-environment entitlement automatically — make sure it matches what your Connect administrator selects in Connect. |
See Connect mobile apps in the Connect user guide.
Step 3: Integrate the Connect SDK
If you have not yet integrated the Connect SDK, follow Integrate the Connect SDK into a native iOS app.
ImportantUse an app key generated through the new Mobile app integration in Connect. Older Web and mobile integrations created before our April 2026 release do not support push notifications.
Step 4: Configure push notifications in the Apple Developer portal
Push notifications in Connect require three components working together:
| Component | Purpose |
|---|---|
| Main app | Initializes the SDK with push configuration and requests notification permission from the user |
| Notification Service Extension (NSE) | Downloads rich media (images) and records delivery, including dismissed notifications |
| Notification Content Extension (NCE) | Renders the expanded notification view when the user long-presses a notification |
All three targets share an App Group — a shared container that lets them exchange push data. The App Group identifier must be identical across all three targets and your SDK configuration. A mismatch in any one location causes delivery tracking and rich media to silently fail.
Register or update your App ID
If you are registering a new App ID:
- In your Apple Developer account, go to Identifiers > +.
- Select App IDs > App and click Continue.
- Enter a description and your bundle ID (for example,
com.yourcompany.yourapp). - Under Capabilities, enable Push Notifications and App Groups.
- Click Continue > Register.
If your App ID already exists:
- Click the App ID in the list to open it.
- Under Capabilities, enable Push Notifications and App Groups.
- Click Save.
NoteIf you use Automatically manage signing in Xcode, these changes should be picked up automatically. If the capabilities do not appear in Xcode after saving, go to Xcode > Settings > Accounts and click Download Manual Profiles to force a refresh.
Register App IDs for the extensions
Repeat the App ID registration for each extension target, enabling App Groups only. Unlike the main app, extension App IDs do not require the Push Notifications capability.
com.yourcompany.yourapp.NotificationServiceExtensioncom.yourcompany.yourapp.NotificationContentExtension
Create an App Group
- Go to Identifiers > + and select App Groups.
- Enter a description and an identifier using the
group.prefix convention (for example,group.com.yourcompany.yourapp). - Click Continue > Register.
- Go back to each of your three App IDs (main app, NSE, NCE) and assign the App Group you just created.
WarningThe App Group identifier is not the same as your bundle ID. It must start with
group.and be identical across all targets and your SDK configuration. Even a single character mismatch will cause delivery tracking and rich media to silently fail.
Step 5: Configure push notifications in Xcode
Configure Info.plist
In your main app's Info.plist, add the following to enable background push delivery:
| Key | Type | Value |
|---|---|---|
| Required background modes | Array | (1 item) |
| Item 0 | String | App downloads content in response to push notifications |
Raw XML equivalent
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>Initialize the SDK with push configuration
Add the push: argument to the ConnectConfig you pass to ConnectSDK.shared.enable(with:). Replace group.com.yourcompany.yourapp with the App Group identifier you created in Step 4.
ConnectSDK.shared.enable(
with: ConnectConfig(
appKey: "YOUR_APP_KEY",
postURL: "YOUR_COLLECTOR_URL",
push: ConnectPushConfig(
mode: .automatic,
appGroupIdentifier: "group.com.yourcompany.yourapp"
)
)
)
NoteThe SDK manages APNs token registration and notification callbacks automatically. Do not set your own
UNUserNotificationCenter.delegate— doing so will prevent push signals from being tracked in Connect. If your app needs a custom delegate or already has its own push infrastructure, see the sample app for the manual-mode integration pattern.
Add the Notification Service Extension
The NSE downloads rich media and records push delivery.
Create the extension target
- In Xcode, go to File > New > Target.
- Select Notification Service Extension and click Next.
- Name it
NotificationServiceExtensionand ensure Embed in Application shows your main app. - Click Finish.
- If a confirmation message appears, select Activate. It can be useful for debugging.
Add the SDK dependency
In Xcode, select the NSE target, go to General > Frameworks and Libraries, and add the Connect library.
Implement the extension
Replace the generated NotificationService.swift with the following. Use the same App Group identifier as your main app.
import Connect
final class NotificationService: ConnectNotificationService, @unchecked Sendable {
override var appGroupIdentifier: String? {
"group.com.yourcompany.yourapp"
}
}
Note
@unchecked Sendableis required when strict concurrency checking is enabled (Swift 6 or later, or when explicitly enabled in your build settings). You can omit it if your project does not use strict concurrency checking.
Verify the Info.plist
Xcode generates an Info.plist for the NSE target. Open it in the property list editor and verify the rows under NSExtension:
| Key | Type | Value |
|---|---|---|
| NSExtensionPointIdentifier | String | com.apple.usernotifications.service |
| NSExtensionPrincipalClass | String | $(PRODUCT_MODULE_NAME).NotificationService |
Add the Notification Content Extension
The NCE renders the expanded notification view when the user long-presses a notification.
Create the extension target
- In Xcode, go to File > New > Target.
- Select Notification Content Extension and click Next.
- Name it
NotificationContentExtension, ensure Embed in Application shows your main app, and click Finish. - If a confirmation message appears, click Activate.
Add the SDK dependency
In Xcode, select the NCE target, go to General > Frameworks and Libraries, and add the Connect library.
Implement the extension
Replace the generated NotificationViewController.swift with the following. Use the same App Group identifier as your main app.
import Connect
final class NotificationViewController: ConnectNotificationContentExtension, @unchecked Sendable {
override var appGroupIdentifier: String? {
"group.com.yourcompany.yourapp"
}
}Configure the NCE Info.plist
Replace the contents of the NCE's Info.plist with the following. To switch to the raw mode, right-click the file and select Open As > Source Code.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>UNNotificationExtensionCategory</key>
<array>
<string>ACOUSTIC_RICH_NOTIFICATION</string>
</array>
<!--
Keep the system-default title/body banner visible above the NCE view.
The NCE only appends the expansion content (image and/or expandedBody) below.
-->
<key>UNNotificationExtensionDefaultContentHidden</key>
<false/>
<!--
Initial height-to-width ratio used before the view calls preferredContentSize.
The view controller updates this dynamically once the image dimensions are known.
-->
<key>UNNotificationExtensionInitialContentSizeRatio</key>
<real>1</real>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.content-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationViewController</string>
</dict>
</dict>
</plist>If you named your view controller class something other than NotificationViewController, update NSExtensionPrincipalClass to match. UNNotificationExtensionInitialContentSizeRatio can also be tuned if your expanded view has a known aspect ratio, though 1 is the right default for most projects.
Table view equivalent
| Key | Type | Value |
|---|---|---|
| NSExtension | Dictionary | (3 items) |
| NSExtensionAttributes | Dictionary | (3 items) |
| UNNotificationExtensionCategory | Array | (1 item) |
| Item 0 | String | ACOUSTIC_RICH_NOTIFICATION |
| UNNotificationExtensionDefaultContentHidden | Boolean | NO |
| UNNotificationExtensionInitialContentSizeRatio | Number | 1 |
| NSExtensionPointIdentifier | String | com.apple.usernotifications.content-extension |
| NSExtensionPrincipalClass | String | $(PRODUCT_MODULE_NAME).NotificationViewController |
In the property list editor, UNNotificationExtensionDefaultContentHidden shows as type Boolean with values YES or NO. NO is equivalent to <false/> in the underlying XML.
Delete the storyboard
Xcode generates a MainInterface.storyboard for the NCE. Delete this file and, if the row NSExtensionMainStoryboard is present in the NCE's Info.plist, remove it. The SDK handles all UI programmatically.
Enable capabilities in Xcode
After enabling the capabilities on the App ID, you must also add them to the targets in Xcode. For each of your three targets (main app, NSE, NCE):
- Select the target in Xcode and go to Signing & Capabilities.
- Add the App Groups capability.
- Add the App Group identifier you created in Step 4.
For the main app target only, also add the Push Notifications capability.
Step 6: Request notification permission
Your app must request notification permission from the user. Add the following at an appropriate point in your app's UX — for example, after an onboarding screen that explains the value of notifications rather than on first launch.
func requestNotificationPermission() {
UNUserNotificationCenter.current().requestAuthorization(
options: [.alert, .badge, .sound]
) { granted, error in
try? ConnectSDK.shared.push.didReceiveAuthorization(granted: granted, error: error)
}
}
WarningiOS only shows the system permission dialog once. If the user denies it, the only way to re-enable notifications is through the Settings app. Design your UX accordingly.
Identify app users
Push setup is now complete. To make the most of push notifications, you also need to identify the people receiving them.
When someone opens your app for the first time, they are automatically added to Connect as an anonymous mobile contact. By default, the Connect SDK does not collect names, email addresses, or customer IDs, so these contacts cannot be matched to people your marketing team already knows. Identifying users lets you target push notifications to known contacts, attribute the rest of the user's session to that contact, and merge mobile activity with the rest of your audience data.
To identify users, send an identity signal at the appropriate moment in your auth flow:
- Identify users at sign-in (iOS) — when an existing user authenticates.
- Identify users at registration (iOS) — when a new user creates an account.
Testing
On the simulator
You can test basic push delivery in the simulator using .apns payload files. Create them in any text editor and drag them onto the running simulator to send a test notification. We keep ours in a TestPayloads/ folder inside the Xcode project.
NoteWhen creating your payload files, keep in mind:
- Replace
com.yourcompany.yourappin theSimulator Target Bundlefield with your app's bundle ID.- iOS limits notification titles to 50 characters and the combined title and body to 150 characters. For example, a 40-character title leaves up to 110 characters for the body.
A basic test payload:
{
"Simulator Target Bundle": "com.yourcompany.yourapp",
"aps": {
"alert": {
"title": "Test notification",
"body": "This is a test push notification."
},
"sound": "default"
}
}To test rich push (images), add "mutable-content": 1 to the payload. This tells iOS to invoke the NSE before displaying the notification:
{
"Simulator Target Bundle": "com.yourcompany.yourapp",
"aps": {
"alert": {
"title": "Rich notification",
"body": "This notification includes an image."
},
"mutable-content": 1,
"sound": "default"
},
"data": {
"notification": {
"expandedImage": "https://example.com/image.jpg"
}
}
}On a device
Full end-to-end testing requires a physical device. The simulator cannot receive real remote push notifications.
- Build and run on a physical device.
- Grant notification permission when prompted.
- Send a test push from the Acoustic Connect dashboard.
- Verify the notification appears, images load, and push signals appear in the dashboard.
Troubleshooting
Push token not received
Possible causes:
- Running on the simulator — APNs tokens are not available on the simulator
- The user denied notification permission
remote-notificationis missing fromUIBackgroundModesinInfo.plist- The bundle ID in your Xcode project does not match the App ID with Push Notifications enabled in the Apple Developer portal
Rich push images not showing
Verify the following:
"mutable-content": 1is present in the push payload- The NSE target includes the Connect library
- The
appGroupIdentifierin the NSE exactly matches the main app - The image URL is accessible over HTTPS and is not too large
Push signals not appearing in Acoustic Connect
Verify the following:
- The
appKeyand collector URL in yourConnectConfigmatch the dashboard configuration - You are not setting your own
UNUserNotificationCenter.delegate - The App Group identifier is consistent across all three targets and your
ConnectPushConfig
Extension crashes on launch
Common causes:
- The Connect library is not linked to the extension target
NSExtensionPrincipalClassin the extension'sInfo.plistis incorrect — it must be$(PRODUCT_MODULE_NAME).YourClassName- The App Group entitlement is missing on the extension target
Troubleshooting tip
To enable SDK debug logging, add these environment variables with a value of 1 to your scheme (Product > Scheme > Edit Scheme > Run > Arguments > Environment Variables):
CONNECT_DEBUGTLF_DEBUGEODebug
When reporting an issue to our support team, always attach your debug log. It speeds up troubleshooting.
Duplicate notifications in the foreground
Symptom: A notification appears as both a system banner and an in-app alert.
Cause: You are using automatic mode but have also set your own UNUserNotificationCenter.current().delegate, which overrides the SDK's transparent proxy and causes the notification to be presented twice.
Fix: Either remove your custom delegate and let automatic mode handle presentation, or switch to manual mode. See the sample app for the manual-mode integration pattern.
Updated about 4 hours ago
