Configure the Service Extension for the iOS Extension SDK
Set up the Notification Service Extension to enable push delivery tracking.
The notification service extension runs as a separate bundle within your main app.
-
In Xcode, go to File > New > Target.
-
In the iOS > Application Extension section, select Notification Service Extension.
-
Click Next.
-
Configure the app extension and click Finish.
-
In your project target’s General settings, verify that the new extension is listed under Frameworks, Libraries, and Embedded Content. If it’s not there, add it.

Use the same Xcode-managed profile for the extension targets as your main app. Match the service extension version to the main app version, and prefix the service extension bundle ID with the main app’s bundle ID. For example, if your main app’s bundle ID is
com.salesforce.MyAwesomeApp, usecom.salesforce.MyAwesomeApp.MyServiceExtensionfor the service extension.
Choose an integration method based on your project setup.
- Integrate the SDK with CocoaPods
- Integrate the SDK with Swift Package Manager (SPM)
- Integrate the SDK Manually
Add the SDK as a dependency in your app’s Podfile. Follow the instructions for Adding pods to an Xcode project in the CocoaPods documentation.
After installation completes, open the .xcworkspace file that CocoaPods created.
Avoid opening .xcodeproj directly. Opening a project file instead of a workspace can lead to errors.
Integrate the iOS Extension SDK using Swift Package Manager.
- In Xcode, open your project and select Project Settings.
- Go to the Package Dependencies tab, and click + to add a new package.
- Enter the repository URL and add these packages required for your implementation:
- Review the package details and confirm to complete the installation.
To integrate the extension SDK manually:
-
Download these SDKs:
-
Copy the relevant
.xcframeworkdirectories from your downloads folder into your project folder. -
In Xcode, open your project and select the appropriate target. Add the required
.xcframeworkfiles to Frameworks, Libraries, and Embedded Content in the target’s General settings. -
Add
MarketingCloudSDK.bundleto Copy Bundle Resources under Build Phases. -
In Build Settings, add
-ObjCto Other Linker Flags.
Remove the autogenerated code from your Service Extension class and inherit from SFMCNotificationService.
View Swift code example
View Objective-C code example
Don’t implement any UNNotificationServiceExtension methods, such as func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) → Void) and open func serviceExtensionTimeWillExpire(). The SFMCNotificationService class handles these methods.
The MCExtensionSDK manages the UNNotificationServiceExtension lifecycle methods. Customize the extension’s behavior to:
- Enable or disable logging and configure log levels
- Download and attach images or videos to push notifications
- Add custom key-value pairs to the notification’s
userInfo - Perform other operations your app requires
Enable or disable logging and configure log levels by overriding the sfmcProvideConfig() method: override func sfmcProvideConfig() → SFNotificationServiceConfig
Show the first image of a carousel as a thumbnail by overriding the sfmcProvideConfig() method and setting shouldShowCarouselThumbnail to false.
View Swift code example
View Objective-C code example
Execute custom code by overriding func sfmcDidReceive(_ request: UNNotificationRequest, mutableContent: UNMutableNotificationContent, withContentHandler contentHandler: @escaping ([AnyHashable : Any]?) → Void). Use this method to process notifications, download media, or add custom key-value pairs.
These examples show how to configure logging and customize notification handling.
View Swift code example
View Objective-C code example
When you customize func sfmcDidReceive(_ request: mutableContent: withContentHandler:), don’t modify mutableContent.request.content.userInfo directly. Use contentHandler to add custom key-value pairs. The system provides limited time for processing, so minimize custom processing time and invoke the completion handler on every return path.