MoEngage Docs

Push Notification Implementation

PREREQUISITE :

Make sure you have created APNS certificate and uploaded it to MoEngage dashboard as mentioned in APNS Certificate/ PEM file before testing push notification.

App Target Implementation

Settings Changes:

Capabilities Tab Changes

First, select your App Target and select Capabilities do the changes as shown in the image below:

  1. Turn ON App Groups in for your app target and enable one of the App group ids, in case if you don't have an App Group ID then create one. The name of your app group should be group.{your_bundle_id}.MoEngage.

  2. Turn ON Background mode and set/enable Remote Notification.

  3. Turn ON the Push Notifications capability for your app.

NOTE:

On enabling Remote Notification background mode, we will be able to track uninstalls even for devices where push notification is disabled by the user.

Adding UserNotifications framework

In the App's Target add UserNotifications framework in Linked Frameworks and Libraries and set it Optional.

Code Changes in App Target:

1. Provide the App Group ID to SDK

Provide the App Group ID selected in Capabilities tab by calling setAppGroupID: method before initializing the SDK as shown below:

[MoEngage setAppGroupID:<Your AppGroupID>];
MoEngage.setAppGroupID(<Your AppGroupID>)

2. Registering for Push notification

Make sure that class, where UserNotificationCenter delegate methods are implemented, should agree to UNUserNotificationCenterDelegate as shown below (In this case AppDelegate is set to be UserNotificationCenter delegate) :

Call SDK's registerForRemoteNotificationWithCategories: to initiate registration of remote notifications as shown below, also in case if you are supporting iOS version below iOS10 we have a separate method for below versions(registerForRemoteNotificationForBelowiOS10WithCategories:) :

if (@available(iOS 10.0, *)) {
        [[MoEngage sharedInstance] registerForRemoteNotificationWithCategories:nil withUserNotificationCenterDelegate:self];
} else {
        [[MoEngage sharedInstance] registerForRemoteNotificationForBelowiOS10WithCategories:nil];
}
if #available(iOS 10.0, *) {
	MoEngage.sharedInstance().registerForRemoteNotification(withCategories: nil, withUserNotificationCenterDelegate: self)
} else {  
	MoEngage.sharedInstance().registerForRemoteNotificationForBelowiOS10(withCategories: nil)
}

Now after registering for push, the below given callback methods will be called. Call the respective MoEngage SDK methods for the callbacks as shown below :

//Remote notification Registration callback methods
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
	[[MoEngage sharedInstance] setPushToken:deviceToken];
}

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
	[[MoEngage sharedInstance]didFailToRegisterForPush];
}

//This method is for getting the types of notifications that app may use 
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
    
	[[MoEngage sharedInstance]didRegisterForUserNotificationSettings:notificationSettings];
}
//Remote notification Registration callback methods
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
	MoEngage.sharedInstance().setPushToken(forPush: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
	MoEngage.sharedInstance().didFailToRegisterForPush()
}
    
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
	MoEngage.sharedInstance().didRegister(for: notificationSettings)
}

Notification Actions

You can send the set of categories(UNNotificationCategory for iOS10 and MONotificationCategory for earlier versions of iOS) for supporting Notification actions. Get more info regarding notification actions here.

3. Callback methods on receiving Push Notification:

Include calls to MoEngage SDK methods on receiving notification callbacks as shown below:

// UserNotifications Framework Callback for iOS10 and above
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)())completionHandler{
           
    [[MoEngage sharedInstance] userNotificationCenter:center didReceiveNotificationResponse:response];
           
    //Custom Handling of notification if Any  
    completionHandler();
}


- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
    completionHandler((UNNotificationPresentationOptionSound
                       | UNNotificationPresentationOptionAlert ));
}

//Remote notification received callback method for iOS versions below iOS10
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
        [[MoEngage sharedInstance]didReceieveNotificationinApplication:application withInfo:userInfo openDeeplinkUrlAutomatically:YES];
}
// MARK:- UserNotifications Framework callback method
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        MoEngage.sharedInstance().userNotificationCenter(center, didReceive: response)
        //Custom Handling of notification if Any
        let pushDictionary = response.notification.request.content.userInfo
        print(pushDictionary)
        completionHandler();
    }
    
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.sound,.alert])
    }

// MARK:- Remote notification received callback method for iOS versions below iOS10

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
	MoEngage.sharedInstance().didReceieveNotificationinApplication(application, withInfo: userInfo, openDeeplinkUrlAutomatically: true)
}

Method userNotificationCenter:willpresentnotification:withCompletionHandler: is called when the app receives notification in foreground. Here, in the completion handler you can mention how you want to let the user know that the app has received a notification.

Method userNotificationCenter:didreceivenotificationresponse:withCompletionHandler is called when the app receives a response from the user. Response can be Default Click on the Notification or Dismissing the notification or any of the other custom actions implemented using UNUserNotificationCategory. Here, call userNotificationCenter:didreceivenotificationresponse: of MoEngage class.

NOTE:

  1. userNotificationCenter:didreceivenotificationresponse:withCompletionHandler is the only method called when the user clicks on notification, if implemented. Therefore, include your custom handlers here instead of application:didreceiveremotenotification: for iOS10.

  2. While implementing deep links, make sure that you have added the apps URL Scheme to LSApplicationQueriesSchemes array in Info.plist to whitelist your app. Without this, the deep links won't work post iOS9.

Notification Service Extension Target Implementation

Why add a Notification Service Extension to your project?

Notifications have got a complete revamp after the release of iOS10 with the introduction of new UserNotifications and UserNotificationsUI framework. And with this we got Notification Service App Extensions, which can be used for following:

  1. Add media support in Notifications: Post iOS10 Apple has given us the ability to add images, gifs, audio, and video files to the notifications and this can be done using the Notification Service Extension.

  2. For supporting Inbox Feature: Notification Service Extension is also used to save the received notifications which can later be shown in the App Inbox.

  3. For Updating the Notification Badge count: MoEngage makes use of the extension to update the notification badge count and doesn't send badge in the notification payload.

  4. For Tracking Notification Impression: We can track if a Notification is received by the device using the Notification Service Extension.

Follow the below steps to set up Notification Service Extension:

1. Create a Notification Service Extension Target:

Set the name of the extension target and the programing language which you want to use:

Once the target is created, Activate the scheme for Extension when prompted for the same. After this, your extension will be added to project you will see a class with the extension name provided by you while creation and .plist file associated with it.

2. Enable Push Notification Capabilities

Then make sure that the Push Notifications Capability is enabled for the Notification Service Extension created:

3. Add UserNotifications framework to extension target:

Add UserNotifications framework to Linked Frameworks and Libraries of notification service extension target as shown below:

4. Integrate MORichNotification framework to Extension:

IMPORTANT

Incase, if your app is supporting iOS versions below iOS 10, there is an issue with CocoaPods wherein the MORichNotification framework is linked to the main app target, though its added only for NotificationService Extension, this results in a crash in iOS9. This is an issue on CocoaPods configuration side. To prevent this, you will have to add the MORichNotification manually from this link

  • Through CocoaPods :

For integrating through CocoaPod, include MORichNotification pod for your Notification Service Extension as shown below, and run pod update / install command :

target "NotificationServices" do
	pod 'MORichNotification'
end
  • Manual Integration :

For manual integration follow the following steps :

  1. Download the latest sdk from the following link

  2. Add the MORichNotification folder to your Notification Service Extension target.

  3. Add the following compiler flag: -ObjC. Select your Notification Service Extension target. Go to “Build Settings” ->”Linker” ->”Other Linker Flags” and add this flag.

5. Set the App Group ID for Extension:

Turn ON App Groups in for your notification service extension target and enable the same App group id which was selected for the App Target(In the above steps).

6. Code Changes in Notification Service Extension:

#import "NotificationService.h"
// 1st Step
#import <MORichNotification/MORichNotification.h>


@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    @try {
      
        // 2nd Step
      	[MORichNotification setAppGroupID:<Your AppGroupID>];
      
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
				
      	// 3rd Step
        [MORichNotification handleRichNotificationRequest:request withContentHandler:contentHandler];
    } @catch (NSException *exception) {
        NSLog(@"MoEngage : exception : %@",exception);
    }
}


/// Save the image to disk

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    self.contentHandler(self.bestAttemptContent);
}



@end
import UserNotifications
// 1st Step
import MORichNotification

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    
    	// 2nd Step	
      MORichNotification.setAppGroupID(<Your AppGroupID>)
    
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        // To Increase badge count
        MORichNotification.updateBadge(with: bestAttemptContent)
        
        // 3rd Step
        MORichNotification.getAttachmentFrom(request) { (attachment) in
            if let att = attachment {
                self.bestAttemptContent?.attachments = [att]
            }
            
            if let bestAttemptContent = self.bestAttemptContent {
                contentHandler(bestAttemptContent)
            }
        }
        
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

}

Refer to the code above and do the following changes:

  1. Import MORichNotification framework.
  2. Set the App Group ID selected in the settings earlier using setAppGroupID: method.
  3. Call method to process the notification request:
    • Obj-C: Call handleRichNotificationRequest: withContentHandler: method.
    • Swift: Call getAttachmentFromRequest() method and in the completion block add attachment instance and call contentHandler() as shown above.
  4. Only for Swift: Call separate method updateBadge()<Required only in case of Swift> if you intend to increase the badge count on receiving the Notification.

Rich Notification Media Limitations:

  • Refer to the following link to know about the size and format limitation for attachments(media) supported in Rich Notifications.

  • Http URL's aren't supported in iOS10 unless explicitly specified in the plist. You will have include App Transport Security Settings Dictionary in your Notification Service Extension's Info.plist and inside this set Allow Arbitrary Loads to YES.

IMAGE GUIDELINES:

  • File Size: The maximum file size for image attachments can be 10MB.
  • Dimensions: The maximum possible dimensions are 1038 x 1038 pixels. It can be anything smaller than 1038 pixels.
  • Landscape vs Portrait: iOS supports both the orientations but we recommend using images that have a landscape orientation this is because depending on the dimensions, portrait images may look too tall.

Test/Live Builds

  • If you are testing the app on Test Flight or on a live app store build, make sure you upload the adhoc or production pem to our dashboard. And also in this case you have to send push notifications from Live environment of your account.

  • For dev build, you can upload development or production certificate in dashboard, but make sure that you create your campaign in Test environment, as you cannot send push notifications to dev build from Live environment.

Notification Payload

While sending push notifications, you can add key value pairs to your notification payload. An example of the push payload is :

{
    "app_extra" =     {
        moe_deeplink = "moe://screen/settings";
        screenData =         {
            key1 = val1;
            key2 = val2;
        };
        screenName = "";
    };
    aps =     {
        alert = {
          title = "Title";
          subtitle = "Subtitle";
          body = "Hello MoEngage";
        };
        mutable-content = 1;
        badge = 1;
    };
  
  // Do not use any keys under moengage. They are for internal purposes.
    moengage =     {
        cid  		= 55f2ba15a4ab4104a287bf88;
      	webUrl 	= "https://www.google.com";
        media-attachment = "http://s32.iamwire.com.s3.amazonaws.com/wp-content/uploads/2015/09/MoEngage.jpg";
      	media-type = "image";
    };
}

Use of screenName

The possible values for screenName parameter is something which you will have to define in your project. It will be present in the notification payload. And you will have to implement the part to parse and get screenName parameter's value and to navigate to the mentioned screen.

  • DeepLinking
    The moe_deeplink parameter will contain deeplinking URL to open. From SDK version 2.2 we support automatic deep linking from the SDK. If the campaign created had a deeplink field and the initialize method in App Delegate had openDeeplinkUrlAutomatically set to true, the SDK will call handleOpenUrl with the specified deep link.For older SDK's, you can use your own key value pair or make use of screenName parameter to define which screen to navigate to.

Define Valid URL Schemes for DeepLinks (LSApplicationQueriesSchemes)

LSApplicationQueriesSchemes(Array - iOS) Specifies the URL schemes you want the app to be able to use with the canOpenURL: method of the UIApplication class(which is being used in our SDK). For each URL scheme you want your app to use with the deeplinks, add it as a string in this array in Info.plist. For more info follow this link.

  • Coupon Code
    If you wish to send a coupon code to your user, add a key "couponCode" in the payload, with the value as the coupon. For e.g. couponCode - ZEF30.
    When the user clicks on the push notification, he/she will be shown an alert that Coupon Code ZEF30 is copied to your clipboard.

  • Rich Landing
    If you wish to open a web page inside the app, from a push notification, add a key "webUrl" in the payload, with the value as the url. For e.g. webUrl - https://www.google.com.
    When the user clicks on the push notification, he/she will see a webpage (WebView) inside the app with the url opened.

  • Rich Notifications (iOS10)
    The "media-attachment" key in the payload gives you the URL of the media which you can download and show in the notification and "media-type" key gives you the type of media of which the URL is provided. Get more info on this here.

HTTP URLs

Http URL's aren't supported in iOS9 unless explicitly specified in the plist. You will have include App Transport Security Settings Dictionary in your Info.plist and inside this set Allow Arbitrary Loads to YES.

Push Notification Implementation


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.