Configure the Service Extension for the iOS Extension SDK

Set up the Notification Service Extension to enable push delivery tracking.

Add a Service Extension Target 

The notification service extension runs as a separate bundle within your main app.

  1. In Xcode, go to File > New > Target.

  2. In the iOS > Application Extension section, select Notification Service Extension.

  3. Click Next.

  4. Configure the app extension and click Finish.

  5. 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.

    The Frameworks, Libraries, and Embedded Content section for a project, showing the new extension highlighted.

    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, use com.salesforce.MyAwesomeApp.MyServiceExtension for the service extension.

    Important

Integrate the Extension SDK with the Service Extension 

Choose an integration method based on your project setup.

Integrate the SDK with CocoaPods 

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.

Important

Integrate the SDK with SPM 

Integrate the iOS Extension SDK using Swift Package Manager.

  1. In Xcode, open your project and select Project Settings.
  2. Go to the Package Dependencies tab, and click + to add a new package.
  3. Enter the repository URL and add these packages required for your implementation:
  4. Review the package details and confirm to complete the installation.

Integrate the SDK Manually 

To integrate the extension SDK manually:

  1. Download these SDKs:

  2. Copy the relevant .xcframework directories from your downloads folder into your project folder.

  3. In Xcode, open your project and select the appropriate target. Add the required .xcframework files to Frameworks, Libraries, and Embedded Content in the target’s General settings.

  4. Add MarketingCloudSDK.bundle to Copy Bundle Resources under Build Phases.

  5. In Build Settings, add -ObjC to Other Linker Flags.

Inherit from SFMCNotificationService 

Remove the autogenerated code from your Service Extension class and inherit from SFMCNotificationService.

View Swift code example
1import UserNotifications
2import MCExtensionSDK
3
4class NotificationService: SFMCNotificationService { }
View Objective-C code example
1#import <UserNotifications/UserNotifications.h>
2#import <MCExtensionSDK/MCExtensionSDK.h>
3
4@interface NotificationService : SFMCNotificationService
5
6@end
1#import "NotificationService.h"
2
3@implementation NotificationService
4
5@end

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.

Warning

Additional Configuration Options 

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

Configure Logging 

Enable or disable logging and configure log levels by overriding the sfmcProvideConfig() method: override func sfmcProvideConfig() → SFNotificationServiceConfig

Configure Thumbnail 

Show the first image of a carousel as a thumbnail by overriding the sfmcProvideConfig() method and setting shouldShowCarouselThumbnail to false.

View Swift code example
1override func sfmcProvideConfig() -> SFNotificationServiceConfig {
2    return SFNotificationServiceConfig(logLevel: .debug, shouldShowCarouselThumbnail: false)
3}
View Objective-C code example
1- (SFMCNotificationServiceConfig *)sfmcProvideConfig {
2 return [[SFMCNotificationServiceConfig alloc] initWithLogLevel:SFMCExtensionSdkLogLevelDebug shouldShowCarouselThumbnail:NO];
3}

Execute Custom Code 

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
1import UserNotifications
2import MCExtensionSDK
3
4class NotificationService: SFMCNotificationService {
5
6    // Use this method to enable logging or change logging levels.
7    override func sfmcProvideConfig() -> SFNotificationServiceConfig {
8        var logLevel: LogLevel = .none
9#if DEBUG
10        logLevel = .debug
11#endif
12        return SFNotificationServiceConfig(logLevel: logLevel)
13    }
14
15    // Use this method to do custom processing, such as image and video downloads or inserting
16    // custom keys in notification userInfo.
17    // Don’t modify `mutableContent.request.content.userInfo` directly. If you need to add a custom
18    // key in notification userInfo, return a dictionary in the completion handler.
19    // The system provides limited time to perform your processing operation.
20    override func sfmcDidReceive(_ request: UNNotificationRequest, mutableContent: UNMutableNotificationContent, withContentHandler contentHandler: @escaping ([AnyHashable : Any]?) -> Void) {
21        // Your custom code here
22
23        // To add custom key/value pairs in the notifications userInfo object, update this line.
24        var customUserInfo: [AnyHashable : Any] = [:]
25        customUserInfo["MyCustomKey"] = "MyCustomValue"
26
27        // Call the content handler to signal the end of your processing operation.
28        contentHandler(customUserInfo)
29    }
30}
View Objective-C code example
1#import "NotificationService.h"
2
3@implementation NotificationService
4
5// Use this method to enable logging and change logging levels.
6- (SFMCNotificationServiceConfig *)sfmcProvideConfig {
7    SFMCExtensionSdkLogLevel logLevel = SFMCExtensionSdkLogLevelNone;
8#if DEBUG
9    logLevel = SFMCExtensionSdkLogLevelDebug;
10#endif
11    return [[SFMCNotificationServiceConfig alloc] initWithLogLevel: logLevel];
12}
13
14// Use this method to do custom processing, such as image and video downloads or inserting
15// custom keys in notification userInfo.
16// Don’t modify `mutableContent.request.content.userInfo` directly. If you need to add a custom
17// key in notification userInfo, return a dictionary in the completion handler.
18// The system provides limited time to perform your processing operation.
19- (void)sfmcDidReceiveRequest:(UNNotificationRequest *)request
20               mutableContent:(UNMutableNotificationContent *)mutableContent
21           withContentHandler:(void (^)(NSDictionary * __nullable))contentHandler {
22    // Your custom code here
23
24    // To add custom key/value pairs in the notifications userInfo object, update this line.
25    NSDictionary *customUserInfo = @{@"MyCustomKey": @"MyCustomValue"};
26
27    // Call the content handler to signal the end of your processing operation.
28    contentHandler(customUserInfo);
29}
30
31@end

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.

Important