SDK Integration

Changes to note from 4.4.0 onwards

Personalisation improvements made to the SDK requires TenantID to be passed as a parameter while initialising the SDK.

SDK Integration

  1. AppDelegate

  2. AppDelegate Lifecycle Methods

  3. Notification Service Extension

  4. Carousel Notification Content Extension

  5. AppGroup

AppDelegate

In AppDelegate create two references to hold the SDK and a PushologiesUserNotificationDelegate (PushologiesCUserNotificationDelegate for Obj-C).

var sdk: Pushologies? 
var userNotificationDelegate: PushologiesUserNotificationDelegate?
Pushologies *sdk;
PushologiesCUserNotificationDelegate *sdkUserNotificationDelegate;

The PushologiesUserNotificationDelegate (PushologiesCUserNotificationDelegate for Obj-C) can be subclassed if customisation is required, but make sure that super calls are made at the end of each overridden method.

class MyAppUserNotificationDelegate: PushologiesUserNotificationDelegate {}
#import <PushSDK/PushSDK.h>
#import "PushSDK/PushologiesCUserNotificationDelegate.h"

NS_ASSUME_NONNULL_BEGIN

@interface AppUserDelegate : PushologiesCUserNotificationDelegate

@end

NS_ASSUME_NONNULL_END

During the didFinishLaunchingWithOptions AppDelegate lifecycle method instantiate the SDK, using the API credentials gathered in Stage Two.

sdk = Pushologies(
    apiKey: “MyPushologiesAPIKey”, 
    apiSecret: “MyPushologiesSecretKey”,
    inAppOpenDelay: 5000,
    tenantID: “MyTenantID”
)
sdk = [
    Pushologies.alloc
    initWithApiKey: infoDict[@"API_KEY"]
    apiSecret: infoDict[@"API_SECRET_KEY"]
    inAppOpenDelay: infoDict[@"IN_APP_OPEN_DELAY"]
    tenantID: infoDict[@"TENANT_ID"]
];

The inAppOpenDelay represented in milliseconds determines the delay applied before displaying an In-App Notification on app launch.

Immediately after creating the SDK instantiate and set a PushologiesUserNotificationDelegate (PushologiesCUserNotificationDelegate for Obj-C)

userNotificationDelegate = PushologiesUserNotificationDelegate(sdk: sdk) 
UNUserNotificationCenter.current().delegate = userNotificationDelegate
sdkUserNotificationDelegate = [
    AppUserDelegate.alloc
    initWithSdk: sdk
];
UNUserNotificationCenter.currentNotificationCenter.delegate = sdkUserNotificationDelegate;

Next set the customer ID to any string value you wish by calling

sdk?.customerID = "YourCustomIDHere"
sdk.customerID = @"YourCustomIDHere";

Lastly, following the above statements, ask the SDK to show authorisation prompts for push notification authorisation and location access authorisation.

Task {
    await sdk?.showAuthorisationPrompts()
}
[sdk showAuthorisationPromptsWithCompletionHandler:^{}];

Alternatively location access authorisation can be deferred or omitted entirely by calling only to authorise push notifications which is required.

Task {
    await sdk?.showPushNotificationAuthorisationPrompt()
}
[sdk showPushNotificationAuthorisationPromptWithCompletionHandler:^{}];

Any time later calling on the SDK to show the location authorisation prompt will enable any location dependent features to function.

sdk?.showLocationAuthorisationPrompt()
[sdk showLocationAuthorisationPrompt];

AppDelegate Lifecycle

If not already present add the following three lifecycle methods and call the SDK’s corresponding methods. Here is a complete example.

func application( 
    _ application: UIApplication, 
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data 
) { 
    sdk?.application( 
        application, 
        didRegisterForRemoteNotificationsWithDeviceToken: deviceToken 
    ) 
} 

func application( 
    _ application: UIApplication, 
    didReceiveRemoteNotification userInfo: [AnyHashable : Any], 
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void 
) { 
    sdk?.application( 
        application, 
        didReceiveRemoteNotification: userInfo, 
        fetchCompletionHandler: completionHandler 
    ) 
} 

func application( 
    _ application: UIApplication, 
    didFailToRegisterForRemoteNotificationsWithError error: Error 
) { 
    sdk?.application( 
        application, 
        didFailToRegisterForRemoteNotificationsWithError: error 
    ) 
} 

func application(
    _ application: UIApplication,
    handleEventsForBackgroundURLSession identifier: String,
    completionHandler: @escaping () -> Void
) {
    sdk?.application(
        application,
        handleEventsForBackgroundURLSession: identifier,
        completionHandler: completionHandler
    )
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [sdk application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [sdk application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

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

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {
    [sdk application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler];
}

Notification Service Extension

In the folder for the notification service extension target created in Stage One, create a new class that inherits from PSDKServiceExtension. Here is an example of the new class:

import PushSDK

class NotificationServiceExtension: PSDKServiceExtension {

    override func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
    ) {
       if request.isPushologiesRequest {
           super.didReceive(request, withContentHandler: contentHandler)
       }
    }
    
}
#import "NotificationService.h"
#import <PushSDK/PushSDK.h>

@interface NotificationService ()

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

@end

@implementation NotificationService

PSDKServiceExtension *serviceExtension;

- (instancetype)init
{
    self = [super init];
    if (self) {
        serviceExtension = [PSDKServiceExtension.alloc init];
    }
    return self;
}

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    if (request.isPushologiesRequest) {
        [serviceExtension didReceiveNotificationRequest:request withContentHandler:contentHandler];
    }
}

- (void)serviceExtensionTimeWillExpire {
    [serviceExtension serviceExtensionTimeWillExpire];
}

@end

Carousel Notification Content Extension

In the folder for the notification content extension target created in Stage One open the storyboard for the view controller found there. Edit the view controller in the storyboard and make it inherit from CarouselNotificationContentViewController in the PushSDK framework. If this produces an error check that the framework has been included in the target's Frameworks and Libraries section. Also, remove any views including labels inside this view controller. Failing to do so will hide the preview content in carousel notifications.

Next open the Info.plist for the Content Extension target. Find UNNotificationExtensionCategory under NSExtension -> NSExtensionAttributes and add in PushologiesCarouselNotification. This will allow the content extension to recognise that it must do something if a carousel push notification arrives.

App Group

The following needs performed for each target in the project. At a minimum this will include the main app, and the two notification extension targets created while following this guide.

Signing & Capabilities

Add the AppGroup capability if not present. Then under the AppGroup capability add the reverse domain name specified during Stage One in the Apple Developer Portal. (ie. group.com.MyApp).

Info.plist

In the Info.plist of each target add the following key PushologiesAppGroup and then for the value fill in the AppGroup domain used above.

Adding Tags

By attaching a tag you can create segments and target notifications to your devices subscribed to those tags.

sdk?.subscribeTag(to: "YourTagHere")
[sdk subscribeTagTo: @"YourTagHere"];

To detach a tag

sdk?.unsubscribeTag(from: "YourTagHere")
[sdk?.unsubscribeTagFrom:@ "YourTagHere"]

Show In-App Notifications (custom triggered)

By calling this method and passing the custom event identifier string as parameter, the app will show any active in-app notification already received and stored in the app.

sdk?.showInAppNotification(with: "YourCustomIdentifierHere")
[sdk showInAppNotificationWith: @"YourCustomIdentifierHere"]

Personalisation

Please note that a new optional parameter TENANT_ID has been introduced from v4.4.0 onwards to incorporate Personalisation into the SDK. This parameter will be passed in when the SDK is initialised. Failing to add this parameter would mean that the Personalisation values cannot be set and processed by the SDK.

Where to find the TENANT_ID?

It can be copied from the Pushologies portal under the SETTINGS -> API KEYS tab

Methods to set and get the personalisation values.

  1. The below methods are used to set values to existing variables in the local personalisation schema. The local schema will be updated periodically and kept in sync with any variable changes in the Pushologies portal. Please note that if the value that you are trying to set is not part of the local schema then this value will be rejected.

To set multiple values

func updatePersonalisationSchema() {
      let schemaArray =
      """
      [{"name":"FirstName","value":"Mark"},{"name":"key2","value":"value2", {"name":"Key3","value":"Value3"}}]
      """
    do {
      let schema = try JSONDecoder().decode([PSDKPersonalisationSchema].self, from: Data(schemaArray.utf8))
      try sdk?.updatePersonalisationVariables(schema: schema)
      let data = sdk?.getAllPersonalisations()
      dump (data)
    } catch {
    }
}
- (void)updatePersonalisationSchemaArray {
    NSString* schemaArray = @"[{\"name\":\"FirstName\",\"value\":\"Mark\"}]";
    NSData* data = [schemaArray dataUsingEncoding: NSUTF8StringEncoding];
    NSArray *jsonArray = (NSArray *)[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    [sdk updatePersonalisationVariablesFor:jsonArray error:nil];
    NSArray* getAll = [sdk getAllPersonalisationsLegacy];
    NSLog(@"%@", getAll);
}

To set a single value

func updatePersonalisationSchema() {
    do {
        try sdk?.updatePersonalisation(
                schema: PSDKPersonalisationSchema(name: "firstName", value: "Mark")
            )
        isShowingSuccessfulAlert = true
    }
    catch {
        isShowingSuccessfulAlert = false
    }
}
- (void)updatePersonalisationSchema {
    @try {
        [sdk updatePersonalisationFor:@"firstName" with:@"Mark" error: nil];
        self.isShowingSuccessfulAlert = YES;
    }
    @catch (NSException *exception) {
        self.isShowingSuccessfulAlert = NO;
    }
}
  1. This method getAllPersonalisations() returns all personalisation keys and values stored locally. This will return empty if there is no schema available or the tenantID is not set while the SDK is initialised.
private var personalisationSchemas: [PSDKPersonalisationSchema]? {
   sdk?.getAllPersonalisations()
}
- (NSArray *)personalisationSchemas {
    return [sdk getAllPersonalisationsLegacy];
}

SDK Event listener.

To receive NOTIFICATION_TAPPED event, access the observer as shown below and choose the event as Pushologies.eventNotificationTapped

sdk?.observeEvent(name: Pushologies.eventNotificationTapped, using: { notification in
            print("AnalyticsEvent: \(String(describing: notification.object))")
        })

sdk?.observeEvent(name: Pushologies.eventNotificationTapped, using: { notification in
            print("AnalyticsEvent: \(String(describing: notification.object))")
        })

Please note these Notification_Tapped events will not be generated for In-App messages