iOS rich media notifications

Send push notifications with images, GIFs and videos

iOS 10 introduced the ability to send push notifications with images, GIFs, and video. To enable this functionality, clients must create a Service Extension which enables modification of a push payload before it is displayed.

Creating a service extension

To create a Notification Service Extension, in Xcode navigate to File > New > Target and select Notification Service Extension.


Xcode Notification Service Extension

Ensure that Embed In Application is set to embed the extension in your application.

Make sure that you set the deployment target to iOS 10 or higher depending on your specifics. By default, Xcode sets deployment target to latest iOS which will silently fail to work on lower OS version. For example, if you set the Service Extension's deployment target to 11.0, and run the app on an iOS 10.3 and an iOS 11.0 device, the Service Extension will not work on the 10.3 device, but by setting the deployment target to 10.0 it will work on both.

Setting up the service extension

Notification Service Extension is its own binary that is bundled with your app. As such, it must be set up in the Apple Developer Portal with its own App ID and Provisioning Profile. Extensions are generally named with a suffix on the main application's ID (e.g. com.xtremepush.test.testwatchnotificationservice). Details of supported file types and sizes for rich media can be found in the Apple Developer documentation.

Finally, be sure that notifications are enabled for you service extension. In Targets > Capabilities select your service extension and make sure Push Notifications are on.


Xcode extension toggle push notifications

Displaying an image

This is the most common rich media use case and has a dedicated field in the iOS push content tab when creating a campaign in Xtremepush. iOS supports JPG, GIF and PNG formats up to 2 MB in size. Review our mobile push notifications creative guidelines for more details.

If you want to add an image via API you can use the push_picture parameter in the Campaign methods, for example:

Simple example of a broadcast iOS push with a picture hosted on your CMS or elsewhere being loaded and sent via API below:

curl --request POST \
  --url \
  --header 'content-type: application/json' \
  --data '{
    "apptoken": "YOURAPPTOKEN", 
    "text": "Just Testing My Service Extension",
    "ios": {"active": 1},
    "push_picture": "",
    "send_type": 0,
    "broadcast": 1

To display the picture on the mobile device, it must be handled in the service extension.


iOS rich notification example

The Xtremepush SDK can handle displaying the image, by linking the SDK against your extension target.

If you use CocoaPods, you can do something similar to this:

def shared_pods
  pod 'Xtremepush-iOS-SDK'

target 'MainTarget' do

  pod 'Alamofire'

target 'ExtensionTarget' do

Or, you can add the framework manually be using drag and drop into the extension folder, or by adding the Extension to the frameworks Target Membership in the right window, as shown below:


extension target framework

Finally, you must add the notification service code:

import XPush

class NotificationService: UNNotificationServiceExtension {

    var token: String? 

    override func didReceive(_ request: UNNotificationRequest,
                             withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.token = XPush.didReceive(request, withContentHandler: contentHandler)

    override func serviceExtensionTimeWillExpire() {
        XPush.serviceExtensionTimeWillExpire(with: token)

#import <XPush/XPush.h>

@interface NotificationService ()

@property (nonatomic) NSString* token;


@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request 
                   withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.token = [XPush didReceiveNotificationRequest:request

- (void)serviceExtensionTimeWillExpire {
    [XPush serviceExtensionTimeWillExpireWith:self.token];