iOS, tvOS & watchOS Getting Started

Learn more about installing the Pyze iOS Smart SDK, initializing it, using events and setting up In-app or push notifications.

1. Get a Pyze App Key

See instructions to get a Pyze App Key for your new app

2. Install the Pyze SDK

Install the Pyze SDK automatically using Cocoapods (recommended) OR manually using the Pyze Framework

3. Initialize

Add one line of initialization code to your app (Objective-C or Swift)

Build and Go!

You have enabled all screen flow funnels, loyalty, cohort and churn analysis, Intelligence data explorations, built-in events, auto segmentation, and much more. Use your app with the Pyze SDK and you should see data on growth.pyze.com. Note: iOS versions supported are 7.x (via Framework only), 8.x, 9.x and 10.x.

In the following sections, you can add app-defined-, timed- and curated- events. To reach out to your users and create meaningful relationships, add push and in-app notifications.

4. Add events

Add Events to your app. A comprehensive overview of curated, app defined, timed and built-in events is available under Events in the api & events.

5. Build meaningful relationships with your users with personalized messages, content and experiences

Pyze delivers intelligence-driven marketing and growth automation, so you can build meaningful relationships with your users.

See blog for integrating tvOS Pyze SDK, sending events and Engaging tvOS users with push notifications and In-App Messages

See blog about Integrating watchOS Pyze SDK in your native watchOS app

App SDK API, Samples, Resources for iOS developers

Pyze iOS, tvOS & watchOS Developer Center has links to Pyze Documentation and api, along with mobile developer resources, we maintain. Check back frequently for updates and contact us at contact@pyze.com if we can improve this page in anyway or if you have suggestions.

Install

Get Pyze App Key

Get a Pyze App Key (PAK) from growth.pyze.com

1. Login to growth.pyze.com

Every app is uniquely assigned a Pyze App Key (PAK), a 22 character app specific key, which you obtain from growth.pyze.com after logging in with your email and password. If you have not signed up for Pyze, you can Get Pyze here first.

Login to growth.pyze.com

2. Add a new app

Click on the Add App button on top right corner and provide the details for your app, including name, platform and optional URL for the app store. Specify the timezone where you are located.

3. Copy Pyze App Key from newly added app

Hover over the newly added app with rotating Pyze logo and copy the Pyze App Key (jUiix5alQ7KYSlG6ZQ_TXw in this example). Alternatively, you click on the “App Profile” icon and copy the PAK from the App profile page.

Alternatively, you click on the “App Profile” icon and copy the PAK from the App profile page.

Install Pyze iOS SDK using Cocoapods

We strongly recommend using CocoaPods when installing the Pyze SDK as it is the easiest and ensures you are using the latest stable version. However, if you do not want to use Cocoapods you can install the Pyze Framework manually.

Select the option depending on your project’s usage of Cocoapods.

Option 1. I am not using CocoaPods in my project yet

You can find detailed instructions for installing and setting up CocoaPods at the CocoaPods website, however the basic setup for first time use is essentially as follows.

1. Install CocoaPods gem - Open up a terminal window and install the CocoaPods gem:
sudo gem install cocoapods
2.Run the pod setup to download all the latest spec file.
pod setup
3.Create a Podfile - Change directories to your project and create a default Podfile
cd /path/to/project/
pod init
4.Edit generated Podfile - Edit the generated Podfile and add the following line above end in the appropriate target
  • iOS: If your iOS app is targeting iOS version 8.0 or higher please use:
pod 'pyze-sdk-iOS'
  • tvOS: If your tvOS app is targeting tvOS 9.0 or higher please use:
pod 'pyze-sdk-tvOS'
  • watchOS: If your watchOS app is targeting watchOS version 2.0 and above please use following pod. Ensure you add this in the “yourAppName WatchKit Extension” target:
pod 'pyze-sdk-watchOS'
  • iOS (Legacy): If your iOS app is targeting iOS version 7.0 and above please use following legacy pod:
pod 'pyze-sdk-iOS7'
Use specific version of Pyze SDK

Alternatively, To install an older specific version e.g. 2.0.1 of the SDK, append the version number in podfile, for example depending on target, use either: pod ‘pyze-sdk-iOS’, ‘2.0.1’ or pod ‘pyze-sdk-iOS7’, ‘2.0.1’

We highly recommend using without version number to pick the latest pod automatically every time you do a pod update.

Using Swift?

If you are using Swift, also add the following line (if missing) to your Podfile. Note the exclamation mark.

use_frameworks!
5.Run Install Command after closing Xcode - Ensure that Xcode is not running, then run the install command to download the specified version into your project
pod install

You should see this output:

Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
6.Use .xcworkspace to use Xcode - Congratulations, your project now has the Pyze SDK.

This sets up an Xcode workspace for your project. You must open your project in Xcode using the generated .xcworkspace rather than the .xcodeproj file.

Option 2. I am already using CocoaPods in my project

Before submitting your app to the AppStore (especially through Application Loader.app) we need to get rid of the simulator binaries, to achieve this please follow the below steps.

  • Go to your project target
  • Navigate to Build phase
  • Click ‘+’ to add ‘New Run script
  • Copy and paste the below script
#**************************************************************************************
echo "Target architectures: $ARCHS"

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
echo $(lipo -info $FRAMEWORK_EXECUTABLE_PATH)

FRAMEWORK_TMP_PATH="$FRAMEWORK_EXECUTABLE_PATH-tmp"

# remove simulator's archs if location is not simulator's directory
case "${TARGET_BUILD_DIR}" in
*"iphonesimulator")
echo "No need to remove archs"
;;
*)
if $(lipo $FRAMEWORK_EXECUTABLE_PATH -verify_arch "i386") ; then
lipo -output $FRAMEWORK_TMP_PATH -remove "i386" $FRAMEWORK_EXECUTABLE_PATH
echo "i386 architecture removed"
rm $FRAMEWORK_EXECUTABLE_PATH
mv $FRAMEWORK_TMP_PATH $FRAMEWORK_EXECUTABLE_PATH
fi
if $(lipo $FRAMEWORK_EXECUTABLE_PATH -verify_arch "x86_64") ; then
lipo -output $FRAMEWORK_TMP_PATH -remove "x86_64" $FRAMEWORK_EXECUTABLE_PATH
echo "x86_64 architecture removed"
rm $FRAMEWORK_EXECUTABLE_PATH
mv $FRAMEWORK_TMP_PATH $FRAMEWORK_EXECUTABLE_PATH
fi
;;
esac

echo "Completed for executable $FRAMEWORK_EXECUTABLE_PATH"
echo $(lipo -info $FRAMEWORK_EXECUTABLE_PATH)

done
#**************************************************************************************

iOS Integration Videos


iOS Integration Videos

Install Pyze iOS Framework manually

We strongly recommend using CocoaPods when installing the Pyze SDK as it is the easiest and ensures you are using the latest stable version. However, if you do not want to use Cocoapods, use the Pyze Framework to install the SDK manually, as shown below.

Installing the Pyze Framework

1. If you are targeting iOS 8.0 onwards, download Pyze Framework from here

github.com/pyze/iOS-Library

If you are targeting tvOS 9.0 onwards, download Pyze Framework from here

github.com/pyze/tvOS-Library

If you are targeting watchOS 2.0 onwards, download Pyze Framework from here

github.com/pyze/watchOS-Library

If you are targeting iOS 7.x, download Pyze Framework from here

github.com/pyze/iOS-Library-iOS7 (legacy iOS)

2. Import into Xcode

Drag and Drop the Pyze.framework from your Downloads folder into your project directory within Xcode.

Note: If targeting watchOS, Select ‘YourApp WatchKit Extension’ as drop target

  • Select following options
  • Destination:
  • Copy items into destination group’s folder (if needed) and
  • Folders:
  • Create group for any added folders options
3.Add Frameworks (iOS and tvOS only)

Add following frameworks to your target. If you are new to iOS please refer to the Apple documentation here.

watchOS Note: SystemConfiguration and CoreTelephony are not available for WatchOS and don’t need to be added.

  • CoreTelephony used to report the carrier operator information like the name, capabilities, country code

  • SystemConfiguration used to detect system errors and changes in ability to reach the internet

4.Add -ObjC linker flag

Add -ObjC linker flag to project’s target.

  • In Xcode, choose View > Navigators > Show Project Navigator, or press ⌘1.
  • Select your project under the PROJECT heading in the Project Navigator, then select the Build Settings tab and All sub tab.
  • Scroll down to the Other Linker Flags build setting under the Linking collection or type “Other Linker Flags” into the search bar.
  • Set the value of the Other Linker Flags build setting to exactly -ObjC

Screenshot:

5.Include in ‘Embedded Binaries’
  • Select Project target > Goto General > ‘Embedded Binaries’
  • Click on the ‘+’ icon
  • Select ‘Pyze.framework
  • Click on ‘Add
6. Before submitting your app to the AppStore (especially through Application Loader.app) we need to get rid of the simulator binaries, to achieve this please follow the below steps.
  • Go to your project target
  • Navigate to Build phase
  • Click ‘+’ to add ‘New Run script
  • Copy and paste the below script
#**************************************************************************************
 echo "Target architectures: $ARCHS"

 APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

 find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
 do
 FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
 FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
 echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
 echo $(lipo -info $FRAMEWORK_EXECUTABLE_PATH)

 FRAMEWORK_TMP_PATH="$FRAMEWORK_EXECUTABLE_PATH-tmp"

 # remove simulator's archs if location is not simulator's directory
 case "${TARGET_BUILD_DIR}" in
 *"iphonesimulator")
    echo "No need to remove archs"
     ;;
 *)
 if $(lipo $FRAMEWORK_EXECUTABLE_PATH -verify_arch "i386") ; then
 lipo -output $FRAMEWORK_TMP_PATH -remove "i386" $FRAMEWORK_EXECUTABLE_PATH
 echo "i386 architecture removed"
 rm $FRAMEWORK_EXECUTABLE_PATH
 mv $FRAMEWORK_TMP_PATH $FRAMEWORK_EXECUTABLE_PATH
 fi
 if $(lipo $FRAMEWORK_EXECUTABLE_PATH -verify_arch "x86_64") ; then
 lipo -output $FRAMEWORK_TMP_PATH -remove "x86_64" $FRAMEWORK_EXECUTABLE_PATH
 echo "x86_64 architecture removed"
 rm $FRAMEWORK_EXECUTABLE_PATH
 mv $FRAMEWORK_TMP_PATH $FRAMEWORK_EXECUTABLE_PATH
 fi
 ;;
 esac

 echo "Completed for executable $FRAMEWORK_EXECUTABLE_PATH"
 echo $(lipo -info $FRAMEWORK_EXECUTABLE_PATH)

 done
 #**************************************************************************************

Congratulations, your project now has the Pyze SDK.

Initialize

Initialize Pyze iOS, tvOS or watchOS App SDK when using Swift

Add code in your Swift app to use the Pyze SDK

The instructions on this page assume you have installed the Pyze SDK into your Xcode project. If not, Install the SDK and come back to this page. See iOS, tvOS & watchOS Developer Center.

Edit AppDelegate.swift or ExtensionDelegate.swift

Open AppDelegate.swift (iOS & tvOS) or ExtensionDelegate.swift (watchOS) in the project and import Pyze module i.e.

import Pyze

iOS & tvOS Open the AppDelegate.swift file and add the following lines in your ```func application(application:, willFinishLaunchingWithOptions:`` function

For iOS and tvOS, add code in willFinishLaunchingWithOptions and NOT didFinishLaunchingWithOptions. Also see iOS App Lifecycle Deconstructed to understand your app’s lifecycle

/// Swift 2.x
func application(application: UIApplication, willFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
    Pyze.initialize("<pyze app key for each app from growth.pyze.com>", withLogThrottling: .PyzelogLevelMinimal)
    return true
}

//OR Swift 3.x.x and above
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    Pyze.initialize("<pyze app key for each app from growth.pyze.com>", withLogThrottling: .PyzelogLevelMinimal)
    return true
}

watchOS Open the ExtensionDelegate.swift file and add the following lines in your ```func applicationDidFinishLaunching()`` function

For watchOS, add code in didFinishLaunchingWithOptions

/// Swift (watchOS)
func applicationDidFinishLaunching() {
       Pyze.initialize("<pyze app key for each app from growth.pyze.com>",
            withLogThrottling: .PyzelogLevelMinimal)
    }

Get the Pyze App key for your app from growth.pyze.com. Replace the key with <pyze app key> in the above function.

Build and Go.

Initialize Pyze iOS, tvOS or watchOS App SDK when using Objective C

Video: Integrate Pyze

Add code in your Objective-C app to use the Pyze SDK

The instructions on this page assume you have installed the Pyze SDK into your Xcode project. If not, Install the SDK and come back to this page. See Getting Started iOS Guide.

Edit AppDelegate.m or ExtensionDelegate.m

Open your AppDelegate.m (iOS & tvOS) or ExtensionDelegate.m (watchOS) in the project and import Pyze module i.e.

#import <Pyze/Pyze.h>

iOS and tvOS - Add following lines in application:willFinishLaunchingWithOptions: method in the @implementation block of your App delegate code file. (usually AppDelegate.m). If you do not have application:willFinishLaunchingWithOptions: method in your class simply add it.

For iOS and tvOS, add code in willFinishLaunchingWithOptions and NOT didFinishLaunchingWithOptions.

Also see iOS App Lifecycle Deconstructed to understand your app’s lifecycle.

// Objective C (iOS and tvOS)
- (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
    [Pyze initialize:@"<pyze app key for each app from growth.pyze.com>"
         withLogThrottling: PyzelogLevelMinimal]; //see https://growth.pyze.com
    return YES;
}

//Do not add in didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
...
}

watchOS - Add following lines in application:applicationDidFinishLaunching: method in the @implementationblock of your Extension delegate code file. (usuallyExtensionDelegate.m``).

For watchOS, add code in didFinishLaunchingWithOptions

// Objective C (watchOS)
- (void)applicationDidFinishLaunching {
  [Pyze initialize:@"<pyze app key for each app from growth.pyze.com>"
        withLogThrottling: PyzelogLevelMinimal];
}

Remember to replace <pyze app key for each app from growth.pyze.com> with the Pyze App key you got from growth.pyze.com

Build and Go!

Add Events

Pyze iOS, tvOS & watchOS SDK - Events


iOS Integration Videos

See a detailed Events Overview. Watch a video: Integrate Events in your iOS app.

Curated Event Handling

Pyze has made it easy for you to capture events. We support many built-in events (see api).

For example, to track ad request use:

Objective-C
#import <Pyze/Pyze.h>
//...
//Objective C
[PyzeAd postAdRequested:@"google.com"
    fromAppScreen:@"home"
    withAdSize:@"320x160"
    adType:@"banner"
    withAttributes:@{
        @"device" : @"iPhone 6s",
        @"power user index" : @"5",
        @"interests" : @"traveling" }];
Swift
func yourMethod() {
    PyzeAd.postAdRequested("https://www.google.com",
        fromAppScreen: "home",
        withAdSize: "320x160",
        adType: "Banner",
        withAttributes: ["FirstName": "John", "LastName" : "Smith", "Age" : "28"])
}
Swift4
PyzeAd.postRequested("https://www.google.com",
    fromAppScreen: "home",
    withAdSize: "320x160",
    adType: "Banner",
    withAttributes: ["FirstName": "John", "LastName" : "Smith", "Age" : "28"])

Custom Event Handling

We also support custom events in addition to built in events. See custom events class api for iOS).

Objective-C

[PyzeCustomEvent postWithEventName:@"My Blog Read Event"
    withAttributes:@{
        @"Author" : @"Nav S",
        @"User Status" : @"Registered",
        @"Article Source" : @"https://blog.pyze.com",
        @"Publish Time" : @"2015-12-17"}];

// Alternate way to pass value1,key1, value2,key2 ...
NSDictionary * attributes = [NSDictionary dictionaryWithObjectsAndKeys:
        @"Nav S", @"Author",
        @"Registered", @"User Status",
        @"blog.pyze.com", @"Article Source",
        @"2015-12-17", @"Publish Time",
        nil];
[PyzeCustomEvent postWithEventName:@"Blog Read" withAttributes:attributes];
Swift
PyzeCustomEvent.postWithEventName("Blog Read",
    withAttributes: ["Author": "Nav S", "User status":  "Registered",
    "Article Source": "CNN", "Publish Time": "12-17-2015"])

// Alternate way to pass value1,key1, value2,key2 ...
let attributes: [NSObject : AnyObject] = [
    "Author" : "Nav S",
    "User_Status" : "Registered",
    "CNN" : "Article Source",
    "12-17-2015" : "Publish Time"
]

PyzeCustomEvent.postWithEventName("Blog Read", withAttributes: attributes)
Swift4
PyzeCustomEvent.post(withEventName: "Blog Read", withAttributes: ["Author": "Nav S", "User status":  "Registered", "Article Source": "CNN", "Publish Time": "12-17-2015"])
        
    // Alternate way to pass value1,key1, value2,key2 ...
    let attributes: [AnyHashable : Any] = [
        "Author" : "Nav S",
        "User_Status" : "Registered",
        "CNN" : "Article Source",
        "12-17-2015" : "Publish Time"
    ]
    
    PyzeCustomEvent.post(withEventName: "Blog Read", withAttributes: attributes)

Enable Mobile Marketing

Push Notifications using APNS

Apple Push Notifications

Apple provides a Apple Push Notification service (APNs) to allow app developers to reach out to their users via push notifications.

The App businesses have the option of hosting and running servers “provider” themselves to send notification content “payload” to Apple over a persistent and secure channel using HTTP/2 multiplex protocol. Apple then forwards the notification content to your app on user’s device.

Pyze customers don’t have to maintain provider servers to communicate with Apple’s push notification service. Pyze can be used to send push notifications for an app in development, an app in production provisioned through the app store, and to a combination of apps in development and production.

Prerequisites

You will need access to your Apple developer Account, Xcode development environment, macOS Keychain Access, and finally iTunes Connect to publish your push-notification enabled app.

Using Pyze as your provider for push notifications

In the following sections, we will create APNs SSL certificates, use your Keychain to convert it into a file (.p12) and upload it to growth.pyze.com. We will also create a mobile provisioning file to import into Xcode. Then we will also enable Background Modes in your project using Xcode and write code to register for remote notifications in your app. Finally, we will enable your app with push notifications.

You will be doing a lot of configuring and clicking, but only write 4-5 lines of code.

1. Generate and download APNs SSL certificates
Login into your Apple developer Account
Create or Edit App and enable Push Notifications
  • From Apple developer Account, click on Certificate, Identifiers & Profiles. (Note: “People” resource is available to developers who you enroll as an organization, as opposed to an individual)

  • Under Identifiers group, click on App IDs. If creating a new app, click on the “+” button on top right. Or, if you have already created the app, select the app and click on the Edit button.

  • Get the bundle ID from your app

Enter your App Id Description and suffix (bundle id) and make sure you have enabled Push Notifications. Ensure the bundle ID that you provide matches the bundle ID that you’re using in your app. (This is a common mistake). Click on Continue.

<figure><img class="docimage" src="images/ios/register-app-ID.jpg" alt=""  /></figure>


<figure><img class="docimage" src="images/ios/bundle-id.jpg" alt=""  /></figure>


<figure><img class="docimage" src="images/ios/EnablePush.jpg" alt=""  /></figure>
Generate SSL certificate and download it
  • Once you successfully created the App-ID, select your App-ID and click the Edit button. In the resulting page scroll down to the Apple Push Notification service SSL Certificates section.

  • Click on Create Certificate button for either Development SSL certificate or Production SSL certificate. See Distribution considerations below.

  • You will be presented with instructions for creating a Certificate Signing Request (CSR) in Keychain Access. Do not click on Continue and please read the instructions provided by Apple and/or follow along below.

  • In the Applications folder on your Mac, open the Utilities folder and launch Keychain Access (Or press command-space and type Keychain Access). Within the Keychain Access Utilities App’s drop down menu, select Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.

  • In the Certificate Information window, enter the email address and a name for your private key. Leave CA Email Address field blank. In the “Request is” group, select the “Saved to disk” option. Click Continue and then save at a known location within Keychain Access to complete the CSR generating process.

  • Switch back to the Apple developer Account where you left of and click on Continue. Upload your Certificate Signing Request (CSR) needed to generate certificate.

  • Generate and then download the certificate as a .cer file

2. Generate Personal Information Exchange PKCS #12 (.p12)

Import certificates into Keychain Access and export Personal Information Exchange PKCS #12 (.p12) file

  • Import the certificate (.cer) you created, either by double clicking it or by choosing File > Import items in Keychain Access.

  • Ensure you have selected your certificate from ‘My Certificates’ under left hand side ‘Category’.

  • Select the certificate which you have added choose File > Export items from menu and export the certificate as Personal Information Exchange (.p12) file. While saving the p12, it is always recommended that you create a password. Note down your password, you will need it in the later steps.

3.Create Mobile Provisioning profile to download and import into Xcode

In this we will create a mobile provisioning profile in Apple developer Account, download it and import it into Xcode. The profile contains test devices you can send push notifications to during development.

  • Login into Apple developer Account, click on Certificate, Identifiers & Profiles.<br (Note: “People” resource is available to developers who you enroll as an organization, as opposed to an individual)

  • Select ‘All’ under Provisioning Profiles in Certificates, Identifiers & profiles. Click ‘+’ on top right to create a new profile

  • Depending on type of provisioning profile (development or production provisioning profile), select the right type. Click on Continue. See Distribution considerations below.

  • Select App ID which you have created. Click on Continue.

    Select iOS Development Certificate or iOS Production Certificate which you created and click on Continue.
    Select Devices pane appears, select device(s) which you would to want to test the APNs service and click on Continue
    Enter a profile name for your app, click Continue and Download the certificate and click Done.

    Note, if Certificates don’t exist, you will be prompted to create one.

  • Once you ‘Download’ the mobile provision certificate, import it into Xcode by double clicking downloaded mobile provisioning certificate.

  • Verify time and date of import into xcode, by opening terminal and typing the following. You should see the date time of the latest imports. ls -light ~/Library/MobileDevice/Provisioning\ Profiles

Joes-MacBook-Pro-15:~ awesomejoe$ ls -light ~/Library/MobileDevice/Provisioning\ Profiles
9453527 -rw-r--r-- 1 staff 7.7K Jan 8 15:27 cafebeef-dead-bead-fade-decadeaccede.mobileprovision
4. Configure Pyze as your provider

In order to allow Pyze to send push notifications on your behalf to users of your app, please provide the iOS push certificate to Pyze.

  • Login to growth.pyze.com
  • Navigate to the app you want to provide keys for
  • Select App Profile page either from the Portfolio page or menu
  • Select Push Notifications on the left menu
  • Upload a Push notifications certificate in .p12 format, provide p12 password (the password you generated while creating the certificate), and specify the provisioning mode: Development or Production depending on the type of certificate you are using.
  • Click Save
  • Select daily and weekly quota limits
5. Distribution considerations

Before you publish your app to AppStore or make a public Ad Hoc release, ensure you created a Production SSL certificate and used a Distribution mobile provisioning profile when following the steps above.

Also, ensure you have uploaded a Production .p12 certificate following steps mentioned in above section. Use Production Mode for Provisioning Mode.

6. Enable Remote Notifications in Xcode Project

You can either turn Remote Notifications on either from the Xcode UI or by editing the app’s property list (usually Info.plist) file depending on you preference.

Option 1: Using Xcode UI
  • In Xcode, choose View > Navigators > Show Project Navigator, or press ⌘1.
  • Select your target under the TARGET heading and then select the Capabilities tab
  • Open Background Modes, turn on slider to enable Background Modes then turn on Remote Notifications by clicking on the corresponding check mark.
Option 2: Editing app’s property list (usually Info.plist) file directly

Open your Info.plist file and add following lines

    <key>UIBackgroundModes</key>
    <array>
      <string>remote-notification</string>
    </array>
7. Enable your app for Push Notifications
Register For Remote Notifications
  • Objective-C

Add following code in your AppDelegate’s application: didFinishLaunchingWithOptions: method.

if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {    
    // iOS 8.x and iOS Phone 9.x onwards
    UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert
                                                | UIUserNotificationTypeBadge
                                                | UIUserNotificationTypeSound);

    UIUserNotificationSettings *userNotificationSettings = [UIUserNotificationSettings
                               settingsForTypes:userNotificationTypes categories:nil];

    [application registerUserNotificationSettings:userNotificationSettings];
    [application registerForRemoteNotifications];  
} else { // Fallback for versions earlier than iOS 8.x
    UIRemoteNotificationType remoteNotificationTypes = (UIRemoteNotificationTypeAlert
                     | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound);

    [application registerForRemoteNotificationTypes:remoteNotificationTypes];
}
  • Swift

Add following code in your AppDelegate’s ...didFinishLaunchingWithOptions... function

//Swift 2.x
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  // iOS 8.x and iOS Phone 9.x onwards
  if #available(iOS 8.0, *) {
    let userNotificationTypes = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
    UIApplication.sharedApplication().registerUserNotificationSettings(userNotificationTypes)
    UIApplication.sharedApplication().registerForRemoteNotifications()
  } else {
    // Fallback on earlier versions
    application.registerForRemoteNotificationTypes([.Alert, .Badge, .Sound])
  }
}

//OR
//Swift 3.x
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        let userNotificationTypes = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(userNotificationTypes)
        UIApplication.sharedApplication().registerForRemoteNotifications()

        return true
}
  • Swift 4.x

Add following code in your AppDelegate’s ...didFinishLaunchingWithOptions... function

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
    if #available(iOS 10.0, *) {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            if granted == true {
                UNUserNotificationCenter.current().delegate = self
                application.registerForRemoteNotifications()
            }
        }
    } else if #available(iOS 8.0, *) {
        
        let userNotificationTypes = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(userNotificationTypes)
        application.registerForRemoteNotifications()
        
    } else {
        // Fallback on earlier versions
        application.registerForRemoteNotificationTypes([.alert, .badge, .sound])
    }
    
    return true
}
Let Pyze know the APNS device token
  • Objective-C

Add following code in your AppDelegate’s application: didRegisterForRemoteNotificationsWithDeviceToken: method.

-(void) application: (UIApplication *) application
    didRegisterForRemoteNotificationsWithDeviceToken: (NSData *) deviceToken {
        [Pyze setRemoteNotificationDeviceToken:deviceToken];
}
  • Swift

For Swift 2.x, add following code in your AppDelegate’s func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) function

func application(application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        Pyze.setRemoteNotificationDeviceToken(deviceToken)
}

OR

For Swift 3.x, add following code in your AppDelegate’s application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) function

func application(_ application: UIApplication,
                didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Pyze.setRemoteNotificationDeviceToken(deviceToken)
}
Let Pyze process Remote Notifications
  • Objective-C

Add following code in your AppDelegate’s ````application: didReceiveRemoteNotification:ORapplication: didReceiveRemoteNotification: fetchCompletionHandler:``` methods.

//EITHER
-(void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo {
        [Pyze processReceivedRemoteNotification:userInfo];
}

//OR (recommended for background fetch)
-(void) application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
        [Pyze processReceivedRemoteNotification:userInfo];
}
  • Swift

Swift 2.x

Add following code in your AppDelegate’s func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])

OR

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) functions.

//EITHER
func application(application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        Pyze.processReceivedRemoteNotification(userInfo)
}

//OR (recommended for background fetch)
func application(application: UIApplication,
    didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
    fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        Pyze.processReceivedRemoteNotification(userInfo)
}

OR Swift 3.x

Add following code in your AppDelegate’s func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])

OR

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

//EITHER
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Pyze.processReceivedRemoteNotification(userInfo)
        completionHandler(.noData)
}

//OR
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        Pyze.processReceivedRemoteNotification(userInfo)
}
Additional code required to enable watchOS push notifications
  • Objective-C
//targeting watchOS 2 or higher
  -(void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler {

    NSDictionary *userInfo = [[remoteNotification objectForKey:@"aps"] objectForKey:@"alert"];
    NSString *title = [userInfo objectForKey:@"title"];
    NSString *message = [userInfo objectForKey:@"body"];

    WKAlertAction *act = [WKAlertAction actionWithTitle:@"OK"
                                                  style:WKAlertActionStyleCancel
                                                handler:^{
                                                    NSLog(@"Alert action ‘OK’ performed");
                                                }];
    NSArray *actions = @[act];

    [self presentAlertControllerWithTitle:title
                                  message:message
                           preferredStyle:WKAlertControllerStyleAlert
                                  actions:actions];

    [Pyze processReceivedRemoteNotification:userInfo];

}

//targeting watchOS 3 or higher
  - (void)didReceiveNotification:(UNNotification *)notification withCompletion:(void(^)(WKUserNotificationInterfaceType interface)) completionHandler {

    NSDictionary *userInfo = [[notification.request.mutableCopy content] userInfo];
    NSDictionary *alertDict = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];
    NSString *title = [alertDict objectForKey:@"title"];
    NSString *message = [alertDict objectForKey:@"body"];


    WKAlertAction *act = [WKAlertAction actionWithTitle:@"OK"
                                                  style:WKAlertActionStyleCancel
                                                handler:^{
                                                    NSLog(@"Alert action ‘OK’ performed");
                                                }];
    NSArray *actions = @[act];

    [self presentAlertControllerWithTitle:title
                                  message:message
                           preferredStyle:WKAlertControllerStyleAlert
                                  actions:actions];

    [Pyze processReceivedRemoteNotification:userInfo];

    completionHandler(WKUserNotificationInterfaceTypeCustom);
}
  • Swift
//targeting watchOS 2 or higher
  override func didReceiveRemoteNotification(_ remoteNotification: [AnyHashable : Any], withCompletion completionHandler: @escaping (WKUserNotificationInterfaceType) -> Void) {

        if let aps = remoteNotification["aps"] as? NSDictionary {
            if let alert = aps["alert"] as? NSDictionary {
                if let title = alert["title"] as? NSString {
                    if let body = alert["body"] as? NSString {


                        let alert:WKAlertAction = WKAlertAction(title: "OK", style: .default, handler: {
                            print("Alert action ‘OK’ performed")
                        })
                        let actions = [alert]
                        self.presentAlert(withTitle: title as String, message: body as String, preferredStyle: .alert, actions: actions)

                        Pyze.processReceivedRemoteNotification(remoteNotification)
                    }
                }
            }
        }

    }

  //targeting watchOS 3 or higher
    @available(watchOSApplicationExtension 3.0, *)
    override func didReceive(_ notification: UNNotification, withCompletion completionHandler: @escaping (WKUserNotificationInterfaceType) -> Swift.Void) {


        let userInfo = notification.request.content.userInfo

        if let aps = userInfo["aps"] as? NSDictionary {
            if let alert = aps["alert"] as? NSDictionary {
                if let title = alert["title"] as? NSString {
                    if let body = alert["body"] as? NSString {

                        let alert:WKAlertAction = WKAlertAction(title: "OK", style: .default, handler: {
                            print("Alert action ‘OK’ performed")
                        })
                        let actions = [alert]
                        self.presentAlert(withTitle: title as String, message: body as String, preferredStyle: .alert, actions: actions)


                        Pyze.processReceivedRemoteNotification(userInfo)
                    }
                }
            }
        }


        completionHandler(.custom)
    }
  • Swift4
//targeting watchOS 2 or higher
func didReceiveRemoteNotification(_ remoteNotification: [AnyHashable : Any], withCompletion completionHandler: @escaping (WKUserNotificationInterfaceType) -> Void) {
    
    if let alert = remoteNotification["alert"] as? [String:Any] {
        if let title:String = alert["title"] as? String {
            if let body:String = alert["body"] as? String {
                let alert:WKAlertAction = WKAlertAction(title: "OK", style: .default, handler: {
                    print("Alert action ‘OK’ performed")
                })
                Pyze.processReceivedRemoteNotification(remoteNotification)
            }
        }
    }
}


//targeting watchOS 3 or higher
@available(watchOSApplicationExtension 3.0, *)
func didReceive(_ notification: UNNotification, withCompletion completionHandler: @escaping (WKUserNotificationInterfaceType) -> Swift.Void) {
    let userInfo = notification.request.content.userInfo
    if let alert = userInfo["alert"] as? [String:Any] {
        if let title:String = alert["title"] as? String {
            if let body:String = alert["body"] as? String {
                let alert:WKAlertAction = WKAlertAction(title: "OK", style: .default, handler: {
                    print("Alert action ‘OK’ performed")
                })
                Pyze.processReceivedRemoteNotification(userInfo)
            }
        }
    }
}

Push notification registration can be implemented either in the iOS app or in the watch extension. It is recommended to do registration in iOS as we receive the device token in iOS app from APNS.

Notifications are delivered to the watch based on following scenarios:

  • iPhone is unlocked - Delivered to iPhone
  • iPhone is locked, watch is on wrist and unlocked - Delivered to Apple Watch
  • iPhone is locked, watch is on wrist and locked - Delivered to iPhone
  • iPhone is locked, watch is not on wrist and locked - Delivered to iPhone

OR

Enable your app for Interactive Push Notifications (Available iOS 8 and above)
Defining the notification categories and register for remote notification
  • Objective-C
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    if ([UNUserNotificationCenter instancesRespondToSelector:@selector(requestAuthorizationWithOptions:completionHandler:)]) {

        [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionSound |
                                                                                               UNAuthorizationOptionAlert |
                                                                                               UNAuthorizationOptionBadge)
                                                                            completionHandler:^(BOOL granted, NSError * _Nullable error) {

            if (!error) {

                //If the app make use of default notification categories provided by Pyze, call 'getPyzeDefaultNotificationCategories' method to get the categories and set it.
                // You can also include the custom categories defined along with these, if any.
                NSSet *pyzeDefaultCategorySet = [PyzeNotification getPyzeDefaultNotificationCategories];
                [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:pyzeDefaultCategorySet];

                [[UIApplication sharedApplication] registerForRemoteNotifications];
            }

        }];

    } else if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {

        UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert
                                                        | UIUserNotificationTypeBadge
                                                        | UIUserNotificationTypeSound);

        // If the app make use of default notification categories provided by Pyze, call 'getPyzeDefaultNotificationCategories' method to get the categories and set it.
        // You can also include the custom categories defined along with these, if any.
        NSSet *categories = [PyzeNotification getPyzeDefaultNotificationCategories];
        UIUserNotificationSettings *userNotificationSettings = [UIUserNotificationSettings
                                                                settingsForTypes:userNotificationTypes categories:categories];
        [application registerUserNotificationSettings:userNotificationSettings];
        [application registerForRemoteNotifications];
    }

    return YES;
}
  • Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        if #available(iOS 10.0, *) {

            let center = UNUserNotificationCenter.current()

            center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
                if granted == true {

            //If the app make use of default notification categories provided by Pyze, call 'getPyzeDefaultNotificationCategories’ method to get the categories and set it.
            // You can also include the custom categories defined along with these, if any.

                    if let pyzeDefaultCategorySet = PyzeNotification.getPyzeDefaultNotificationCategories() as? Set {
                        UNUserNotificationCenter.current().setNotificationCategories(pyzeDefaultCategorySet)
                    }

                    UNUserNotificationCenter.current().delegate = self
                    application.registerForRemoteNotifications()
                }
            }

        } else {

            // If the app make use of default notification categories provided by Pyze, call ‘getPyzeDefaultNotificationCategories’ to get the categories and set it.
            // You can also include the custom categories defined along with these, if any.

            if let pyzeDefaultCategorySet = PyzeNotification.getPyzeDefaultNotificationCategories() as? Set {

                let userNotificationTypes = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: pyzeDefaultCategorySet)

                UIApplication.shared.registerUserNotificationSettings(userNotificationTypes)
            }

            application.registerForRemoteNotifications()
        }

        return true
    }
Let Pyze know the APNS device token
  • Objective-C
 -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        [Pyze setRemoteNotificationDeviceToken:deviceToken];
 }
  • Swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Pyze.setRemoteNotificationDeviceToken(deviceToken)
    }
Handle/Parse the received actionable notification
  • Objective-C

For iOS 10 and above

-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {

    // Call below Pyze SDK method in order to handle the selected notification action by Pyze SDK.
    [PyzeNotification handlePushNotificationResponseWithUserinfo:response.notification.request.content.userInfo
                                                actionIdentifier:response.actionIdentifier];


    /*

     OR

    // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
    [PyzeNotification parsePushNotificationResponseWithUserinfo:response.notification.request.content.userInfo
                                               actionIdentifier:response.actionIdentifier
                                              completionHandler:^(PyzeNotificationContent *pyzePushObject) {

                                                  if (pyzePushObject) {

                                                      NSLog(@"\n\n******************************************************");
                                                      NSLog(@"******************************************************");
                                                      NSLog(@"*** Pyze Push Notification Objsect ***");
                                                      NSLog(@"******************************************************\n");

                                                      NSLog(@"Title : %@", pyzePushObject.title);
                                                      NSLog(@"SubTitle : %@", pyzePushObject.subTitle);
                                                      NSLog(@"Body : %@", pyzePushObject.body);
                                                      NSLog(@"MediaURL : %@", pyzePushObject.mediaURL);
                                                      NSLog(@"Category : %@", pyzePushObject.categoryIdentifier);

                                                      if (pyzePushObject.selectedAction) {
                                                          NSLog(@"------------------------------------------------------");
                                                          NSLog(@"*** Selected Action ***");
                                                          NSLog(@"Selected Action name : %@\n",pyzePushObject.selectedAction.buttonName);
                                                          NSLog(@"Selected Action identifier : %@",pyzePushObject.selectedAction.buttonActionIdentifier);
                                                          NSLog(@"Selected Action type : %@",pyzePushObject.selectedAction.buttonActionTypeString);
                                                          NSLog(@"WebPageURL : %@",pyzePushObject.selectedAction.webPageURL);
                                                          NSLog(@"DeepLinkURL : %@",pyzePushObject.selectedAction.deepLinkURL);
                                                          NSLog(@"ShareText : %@",pyzePushObject.selectedAction.shareText);
                                                          NSLog(@"------------------------------------------------------");
                                                      }


                                                      NSLog(@"All actions : %@",pyzePushObject.allActions);

                                                      NSLog(@"******************************************************");
                                                      NSLog(@"******************************************************\n\n");

                                                  }

                                              }];
     */


    completionHandler();
}

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

For iOS 8 and 9

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
    [PyzeNotification parsePushNotificationResponseWithUserinfo:userInfo
                                              completionHandler:^(PyzeNotificationContent *pyzePushObject) {

                                                  if (pyzePushObject) {

                                                      NSLog(@"\n\n******************************************************");
                                                      NSLog(@"******************************************************");
                                                      NSLog(@"*** Pyze Push Notification Objsect ***");
                                                      NSLog(@"******************************************************\n");

                                                      NSLog(@"Title : %@", pyzePushObject.title);
                                                      NSLog(@"SubTitle : %@", pyzePushObject.subTitle);
                                                      NSLog(@"Body : %@", pyzePushObject.body);
                                                      NSLog(@"MediaURL : %@", pyzePushObject.mediaURL);
                                                      NSLog(@"Category : %@", pyzePushObject.categoryIdentifier);

                                                      if (pyzePushObject.selectedAction) {
                                                          NSLog(@"------------------------------------------------------");
                                                          NSLog(@"*** Selected Action ***");
                                                          NSLog(@"Selected Action name : %@\n",pyzePushObject.selectedAction.buttonName);
                                                          NSLog(@"Selected Action identifier : %@",pyzePushObject.selectedAction.buttonActionIdentifier);
                                                          NSLog(@"Selected Action type : %@",pyzePushObject.selectedAction.buttonActionTypeString);
                                                          NSLog(@"WebPageURL : %@",pyzePushObject.selectedAction.webPageURL);
                                                          NSLog(@"DeepLinkURL : %@",pyzePushObject.selectedAction.deepLinkURL);
                                                          NSLog(@"ShareText : %@",pyzePushObject.selectedAction.shareText);
                                                          NSLog(@"------------------------------------------------------");
                                                      }

                                                      NSLog(@"All actions : %@",pyzePushObject.allActions);

                                                      NSLog(@"******************************************************");
                                                      NSLog(@"******************************************************\n\n");

                                                  }

                                              }];

    /*

     OR

     If you have any action type set for the default tap of the notification in Pyze dashboard and if you want Pyze to handle the action when app launched from push, can call "handlePushNotificationResponseWithUserinfo:actionIdentifier:" method with 'k_PyzeDefaultNotificationAction' as action identifier

     [PyzeNotification handlePushNotificationResponseWithUserinfo:userInfo actionIdentifier:k_PyzeDefaultNotificationAction];

     */

}


-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(nonnull NSDictionary *)userInfo completionHandler:(nonnull void (^)())completionHandler {

    // Call below Pyze SDK method in order to handle the selected notification action by Pyze SDK.
    [PyzeNotification handlePushNotificationResponseWithUserinfo:userInfo
                                                actionIdentifier:identifier];


    /*

     OR

    // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
    [PyzeNotification parsePushNotificationResponseWithUserinfo:userInfo
                                               actionIdentifier:identifier
                                              completionHandler:^(PyzeNotificationContent *pyzePushObject) {

                                                  if (pyzePushObject) {

                                                      NSLog(@"\n\n******************************************************");
                                                      NSLog(@"******************************************************");
                                                      NSLog(@"*** Pyze Push Notification Object ***");
                                                      NSLog(@"******************************************************\n");

                                                      NSLog(@"Title : %@", pyzePushObject.title);
                                                      NSLog(@"SubTitle : %@", pyzePushObject.subTitle);
                                                      NSLog(@"Body : %@", pyzePushObject.body);
                                                      NSLog(@"MediaURL : %@", pyzePushObject.mediaURL);
                                                      NSLog(@"Category : %@", pyzePushObject.categoryIdentifier);

                                                      if (pyzePushObject.selectedAction) {
                                                          NSLog(@"------------------------------------------------------");
                                                          NSLog(@"*** Selected Action ***");
                                                          NSLog(@"Selected Action name : %@\n",pyzePushObject.selectedAction.buttonName);
                                                          NSLog(@"Selected Action identifier : %@",pyzePushObject.selectedAction.buttonActionIdentifier);
                                                          NSLog(@"Selected Action type : %@",pyzePushObject.selectedAction.buttonActionTypeString);
                                                          NSLog(@"WebPageURL : %@",pyzePushObject.selectedAction.webPageURL);
                                                          NSLog(@"DeepLinkURL : %@",pyzePushObject.selectedAction.deepLinkURL);
                                                          NSLog(@"ShareText : %@",pyzePushObject.selectedAction.shareText);
                                                          NSLog(@"------------------------------------------------------");
                                                      }

                                                      NSLog(@"All actions : %@",pyzePushObject.allActions);

                                                      NSLog(@"******************************************************");
                                                      NSLog(@"******************************************************\n\n");

                                                  }

                                              }];
    */


    completionHandler();
}
  • Swift

For iOS 10 and above

@available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        // Call below Pyze SDK method in order to handle the selected notification action by Pyze SDK.
        PyzeNotification.handlePushResponse(withUserinfo: response.notification.request.content.userInfo, actionIdentifier: response.actionIdentifier);


        /*

        OR

        // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
        PyzeNotification.parsePushNotificationResponse(withUserinfo: response.notification.request.content.userInfo, actionIdentifier: response.actionIdentifier) { (pyzePushObject) in
            if let pyzePushObject = pyzePushObject {

                print("\n\n******************************************************")
                print("******************************************************")
                print("*** Pyze Push Notification Object ***")
                print("******************************************************\n")

                print("Title : \(pyzePushObject.title ?? "")")
                print("SubTitle : \(pyzePushObject.subTitle ?? "")")
                print("Body : \(pyzePushObject.body)")

                if let mediaURL = pyzePushObject.mediaURL {
                    print("MediaURL : \(mediaURL)")
                }

                print("Category : \(pyzePushObject.categoryIdentifier ?? "")")

                if let selectedAction = pyzePushObject.selectedAction {

                    print("------------------------------------------------------")
                    print("*** Selected Action ***")
                    print("Selected Action name : \(selectedAction.buttonName ?? "")")
                    print("Selected Action identifier : \(selectedAction.buttonActionIdentifier ?? "")")
                    print("Selected Action type :\(selectedAction.buttonActionTypeString ?? "")")

                    if let webPageURL = selectedAction.webPageURL {
                        print("WebPageURL : \(webPageURL)")
                    }

                    if let deepLinkURL = selectedAction.deepLinkURL {
                        print("DeepLinkURL : \(deepLinkURL)")
                    }

                    print("ShareText : \(selectedAction.shareText ?? "")")
                    print("------------------------------------------------------")

                }
                print("All actions",pyzePushObject.allActions)

	         print("******************************************************")
                print("******************************************************")
            }
        }
        */

        completionHandler()
    }


@available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert)
    }

For iOS 8 and 9

@available(iOS 8.0, *)
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {

        // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
        PyzeNotification.parsePushNotificationResponse(withUserinfo: userInfo) { (pyzePushObject) in
            if let pyzePushObject = pyzePushObject {

                print("\n\n******************************************************")
                print("******************************************************")
                print("*** Pyze Push Notification Object ***")
                print("******************************************************\n")

                print("Title : \(pyzePushObject.title ?? "")")
                print("SubTitle : \(pyzePushObject.subTitle ?? "")")
                print("Body : \(pyzePushObject.body)")

                if let mediaURL = pyzePushObject.mediaURL {
                    print("MediaURL : \(mediaURL)")
                }

                print("Category : \(pyzePushObject.categoryIdentifier ?? "")")

                if let selectedAction = pyzePushObject.selectedAction {
                    print("------------------------------------------------------")
                    print("*** Selected Action ***")
                    print("Selected Action name : \(selectedAction.buttonName ?? "")")
                    print("Selected Action identifier : \(selectedAction.buttonActionIdentifier ?? "")")
                    print("Selected Action type :\(selectedAction.buttonActionTypeString ?? "")")

                    if let webPageURL = selectedAction.webPageURL {
                        print("WebPageURL : \(webPageURL)")
                    }

                    if let deepLinkURL = selectedAction.deepLinkURL {
                        print("DeepLinkURL : \(deepLinkURL)")
                    }

                    print("ShareText : \(selectedAction.shareText ?? "")")
                    print("------------------------------------------------------")
                }
                print("All actions : \(pyzePushObject.allActions)")

		 print("******************************************************")
                print("******************************************************")
            }

        }


        /*
         OR

        If you have any action type set for the default tap of the notification in Pyze dashboard and if you want Pyze to handle the action when app launched from push, can call "handlePushResponse(withUserinfo:actionIdentifier:)" method with 'k_PyzeDefaultNotificationAction' as action identifier parameter

         PyzeNotification.handlePushResponse(withUserinfo: userInfo, actionIdentifier: k_PyzeDefaultNotificationAction);
         */
    }


 @available(iOS 8.0, *)
    func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {

        // Call below Pyze SDK method in order to handle the selected notification action by Pyze SDK.
        PyzeNotification.handlePushResponse(withUserinfo: userInfo, actionIdentifier: identifier);


        /*

         OR

        // Call below Pyze SDK method to get the notification payload parsed as a 'PyzeNotificationContent' object and proceed further.
        PyzeNotification.parsePushNotificationResponse(withUserinfo: userInfo, actionIdentifier: identifier) { (pyzePushObject) in

            if let pyzePushObject = pyzePushObject {

                print("\n\n******************************************************")
                print("******************************************************")
                print("*** Pyze Push Notification Object ***")
                print("******************************************************\n")

                print("Title : \(pyzePushObject.title ?? "")")
                print("SubTitle : \(pyzePushObject.subTitle ?? "")")
                print("Body : \(pyzePushObject.body)")

                if let mediaURL = pyzePushObject.mediaURL {
                    print("MediaURL : \(mediaURL)")
                }

                print("Category : \(pyzePushObject.categoryIdentifier ?? "")")

                if let selectedAction = pyzePushObject.selectedAction {
                    print("------------------------------------------------------")
                    print("*** Selected Action ***")
                    print("Selected Action name : \(selectedAction.buttonName ?? "")")
                    print("Selected Action identifier : \(selectedAction.buttonActionIdentifier ?? "")")
                    print("Selected Action type :\(selectedAction.buttonActionTypeString ?? "")")

                    if let webPageURL = selectedAction.webPageURL {
                        print("WebPageURL : \(webPageURL)")
                    }

                    if let deepLinkURL = selectedAction.deepLinkURL {
                        print("DeepLinkURL : \(deepLinkURL)")
                    }

                    print("ShareText : \(selectedAction.shareText ?? "")")
                    print("------------------------------------------------------")
                }
                print("All actions \(pyzePushObject.allActions)")

		 print("******************************************************")
                print("******************************************************")
            }

        }
         */

        completionHandler()
    }

For a more detailed information on iOS interactive notifications refer iOS interactive notifications guide

8. Enable your app for Rich Push Notifications
  • Add New Target by clicking ‘+’ sign in the Xcode project targets section
  • Select Notification Service Extension and click ‘Next
  • Give a name for the extension and click ‘Finish
  • Select ‘Activate’ button in Activate “NotificationServiceExtension” scheme? Dialog
  • Enable ‘Push Notifications’ in ‘Capabilities’ section for both app and extension targets.
  • Also enable ‘Remote notifications’ and ‘Background fetch’ in ‘Capabilities’ section for the application target.
  • Enable ‘Push Notifications’ in ‘Capabilities’ section for service extension target.
  • Create a Rich Push profile associate with your app’s certificates in iTunes Connect
  • Install the created Rich push profile and set the respective bundle identifier to the extension bundle.
To use the Service extension utility class provided by Pyze, follow the below mentioned steps:

Integrate service extension utility

a. Manual integration:

  • Download the PyzeAppExtensions from here
  • Drag and drop the PyzeAppExtensions.xcodeproj into your project
  • Select notification service extension target. Navigate to General -> Linked Frameworks and Libraries. Click on ‘+’ icon
  • Select PyzeAppExtensions.framework

b. Cocoapods integration:

  • Create a pod file using ‘pod init’ command
  • Under Notification service extension target in pod file add following line: pod ‘pyze-iOS-extensions’
  • Run ‘pod install’ command
Open “.h” of default notification service extension class created by Xcode.
  • Import PyzeNotificationServiceExtension.h and set PyzeNotificationServiceExtension as super class of your notification service class.

NOTE: In case of Manual integration, add the following code to import the ‘PyzeNotificationServiceExtension’

 #import <PyzeAppExtensions/PyzeNotificationServiceExtension.h>
Open “.m” of default notification service extension class created by Xcode
  • Remove all pre-written callback methods

NOTE : If your project is written in Swift, the NotificationServiceExtension.h class will look as below.

9 .iOS interactive notifications guide

There are four methods to which the notification call back will be received in AppDelegate file.

  • Method 1: (Available iOS 10 and above)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
  • Method 2: (Available iOS 8 and above)
func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void)
  • Method 3:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])
  • Method 4: (Available iOS 10 and above)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)

You can handle the notifications on the following Application states:

App state : Background or Terminated
Case 1 : Interactive Actions - User selects a custom interactive action from the notification (For eg ‘Share’)

For iOS 10 and above, Method 1 will be called and for iOS 8 and 9, Method 2 will be called. Options to handle the push notification received using the Pyze SDK are as follows:

Option 1 : ‘PyzeNotification.handlePushResponse’ method will be called depending on the action defined

  • iOS 10 and above

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    PyzeNotification.handlePushResponse(withUserinfo: response.notification.request.content.userInfo, actionIdentifier: response.actionIdentifier);
}

Objective-C

-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    [PyzeNotification handlePushNotificationResponseWithUserinfo:response.notification.request.content.userInfo
                                                    actionIdentifier:response.actionIdentifier];
}
  • iOS 8 and 9

Swift

func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
    PyzeNotification.handlePushResponse(withUserinfo: userInfo, actionIdentifier: identifier);
}

Objective-C

-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(nonnull NSDictionary *)userInfo completionHandler:(nonnull void (^)())completionHandler {
    [PyzeNotification handlePushNotificationResponseWithUserinfo:userInfo
                                                actionIdentifier:identifier];
}

‘PyzeNotification.handlePushResponse’ method will perform the following depending on the action defined:

 * If Action defined is 'Share text', a share dialog will be presented
 * If Action defined is 'Deep link', a call back will be given to

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool


 * If Action defined is 'Open Webpage', the obtained webpage from push payload will open in Safari

**Option 2 : Pyze will provide the 'PyzeNotificationContent' object depending on the action defined**

 * iOS 10 and above

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { PyzeNotification.parsePushNotificationResponse(withUserinfo: userInfo, actionIdentifier: identifier) { (pyzePushObject) in } }


Objective-C

-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { [PyzeNotification parsePushNotificationResponseWithUserinfo:response.notification.request.content.userInfo actionIdentifier:response.actionIdentifier completionHandler:^(PyzeNotificationContent *pyzePushObject) { } }

  • iOS 8 and 9

Swift

func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
        PyzeNotification.parsePushNotificationResponse(withUserinfo: userInfo, actionIdentifier: identifier) { (pyzePushObject) in
    }
}

Objective-C

-(void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(nonnull NSDictionary *)userInfo completionHandler:(nonnull void (^)())completionHandler {
    [PyzeNotification parsePushNotificationResponseWithUserinfo:userInfo
                                                actionIdentifier:identifier
                                                completionHandler:^(PyzeNotificationContent *pyzePushObject) {
    }
}

Pyze will provide the ‘PyzeNotificationContent’ object depending on the action defined:

  • If action defined is ‘Share text’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeShare’. The share text can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        print("ShareText : \(selectedAction.shareText ?? "")")
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"ShareText : %@",pyzePushObject.selectedAction.shareText);
    }
}
  • If action defined is ‘Follow Deeplink’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeDeepLink’. The deep link url can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        if let deepLinkURL = selectedAction.deepLinkURL {
            print("DeepLinkURL : \(deepLinkURL)")
        }
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"DeepLinkURL : %@",pyzePushObject.selectedAction.deepLinkURL);
    }
}
  • If action defined is ‘Open Webpage’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeWebLink’. The webpage url can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        if let webPageURL = selectedAction.webPageURL {
                print("WebPageURL : \(webPageURL)")
        }		
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"WebPageURL : %@",pyzePushObject.selectedAction.webPageURL);
    }
}
Case 2 : Default Notification tap - User taps on the notification
  1. For iOS 10 and above, the working will be similar to ‘Interactive Actions’ as mentioned in Case 1
  2. For iOS 8 and 9, Method 3 will be called
  3. ‘k_PyzeDefaultNotificationAction’ is the default action identifier which Pyze provides. This can be used as an ‘action identifier’ when the user taps on the notification and not on any of the interactive actions. When the user taps on the notification (not on any interactive push action) there won’t be any action identifier to perform the action, in that case developers can call the Pyze push notification handling methods with ‘k_PyzeDefaultNotificationAction’ as the action identifier.

Options to handle the push notification received using the Pyze SDK are as follows

Option 1 : ‘PyzeNotification.handlePushResponse’ method will be called depending on the action defined

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    PyzeNotification.handlePushResponse(withUserinfo: userInfo, actionIdentifier: k_PyzeDefaultNotificationAction)
}

Objective-C

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [PyzeNotification handlePushNotificationResponseWithUserinfo:userInfo actionIdentifier:k_PyzeDefaultNotificationAction];
}

The following will be performed depending on the action defined:

  • If Action defined is ‘Share text’, a share dialog will be presented
  • If Action defined is ‘Deep link’, a call back will be given to
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool                                 
  • If Action defined is ‘Open Webpage’, the obtained webpage from push payload will open in Safari

Option 2 : Pyze will provide the ‘PyzeNotificationContent’ object depending on the action defined

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
        PyzeNotification.parsePushNotificatoinResponse(withUserinfo: userInfo, actionIdentifier: k_PyzeDefaultNotificationAction) { (pyzePushObject) in
    }
}

Objective-C

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [PyzeNotification parsePushNotificatoinResponseWithUserinfo:userInfo actionIdentifier:k_PyzeDefaultNotificationAction completionHandler:^(PyzeNotificationContent *pyzePushObject) {
    }]
}

Pyze will provide the ‘PyzeNotificationContent’ object depending on the action defined:

  • If action defined is ‘Share text’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeShare’. The share text can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        print("ShareText : \(selectedAction.shareText ?? "")")
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"ShareText : %@",pyzePushObject.selectedAction.shareText);
    }
}
  • If action defined is ‘Follow Deeplink’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeDeepLink’. The deep link url can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        if let deepLinkURL = selectedAction.deepLinkURL {
            print("DeepLinkURL : \(deepLinkURL)")
        }
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"DeepLinkURL : %@",pyzePushObject.selectedAction.deepLinkURL);
    }
}
  • If action defined is ‘Open Webpage’, Pyze will provide you a ‘PyzeNotificationContent’ object with ‘selectedAction’ of type ‘ePyzeNotificationActionTypeWebLink’. The webpage url can be accessed as below

Swift

if let pyzePushObject = pyzePushObject {
    if let selectedAction = pyzePushObject.selectedAction {
        if let webPageURL = selectedAction.webPageURL {
                print("WebPageURL : \(webPageURL)")
        }		
    }
}

Objective-C

if (pyzePushObject) {
    if (pyzePushObject.selectedAction) {
        NSLog(@"WebPageURL : %@",pyzePushObject.selectedAction.webPageURL);
    }
}
App state : Foreground

For iOS 10 and above, Method 4 will be called and for iOS 8 and 9, Method 3 will be called. Options to handle the push notification received using the Pyze SDK are as follows:

Option 1 : No Interactive action or default notification tap

  • In this case since the app will be in foreground, there will not be any ‘Interactive Action’ or ‘Default Notification tap’ that can be performed. The developers can call ‘PyzeNotification.parsePushNotificatoinResponse’ without any action identifier, where Pyze will just parse the payload and return ‘PyzeNotificationContent’ object. As no ‘actionIdentifier’ is passed here, the ‘selectedAction’ will be ‘nil’
  • However, the ‘pyzePushObject.allActions’ will list you all the interactive actions defined. It is an array of ‘PyzeNotificationAction’ objects

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    PyzeNotification.parsePushNotificatoinResponse(withUserinfo: userInfo) { (pyzePushObject) in
    }
}

Objective-C

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [PyzeNotification parsePushNotificatoinResponseWithUserinfo:userInfo
                                                completionHandler:^(PyzeNotificationContent *pyzePushObject) {
    }
}

Option 2 : Notification alert on foreground

For iOS 10 and above, you can add the completionHandler(.alert) code to get notification as ‘alert’ even when the app is in foreground

Swift

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler(.alert)
}

Objective-C

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

For iOS 10 and below, the OS does not automatically show push notification when the app is in the foreground.

You can call ‘parsePushNotificatoinResponseWithUserinfo’ method to get the notification payload parsed as ‘PyzeNotificationContent’ model object when a notification is received.

Please see below usage examples:

Objective C:

  PyzeNotification parsePushNotificatoinResponseWithUserinfo:userInfo
                                                completionHandler:^(PyzeNotificationContent *pyzePushObject) {
    // Get the notification content from 'PyzeNotificationContent' object to display it in custom UI / perform the suitable action for the application.
    }

Swift:

 PyzeNotification.parsePushNotificatoinResponse(withUserinfo: userInfo) { (pyzePushObject) in
    // Get the notification content from 'PyzeNotificationContent' object to display it in custom UI / perform the suitable action for the application.
    }

See App Store Review Guidelines for Push Notifications

In-App Notifications

Enable In-app Notifications in your App

In-app notifications allow app developers to reach out to app users when they use your app. In-App Notifications are deeply integrated in Pyze Growth Intelligence and allow app developers to reach out to users from manually from Dynamic Funnels and Intelligence Explorer, and automatically based on workflows and campaigns from Growth Automation.

App developers have full control over when to display the in-app messages and have two options: use the user interface provided by Pyze or develop their own.

Option 1. Use Pyze provided user interface (iOS & tvOS)
Invoke built-in User Interface from your app
  • You can look for In-App messages and invoke the built-in UI anywhere in your app. For example, on a button click or in your viewDidAppear method or when an app is launched or resumed.

Invoke UI from your app

In your button tap handler, call showUnreadInAppNotificationUIWithCompletionHandler:

//Objective-C
[Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus){
    NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
    NSLog(@"message-ID =%@" , inAppStatus.messageID);
    NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
    NSLog(@"title = %@",inAppStatus.title);
    NSLog(@"urlString = %@",inAppStatus.urlString);

    //...
    //Now dismiss the Inapp UI
    [Pyze dismissInAppNotificationUI:YES];
}];
// Swift 3
Pyze.showUnreadInAppNotificationUI { (inAppStatus) in

            if let inAppStatus = inAppStatus {
                print("buttonIndex = "+String(describing: inAppStatus.buttonIndex))
                print("message-ID = "+String(describing: inAppStatus.messageID))
                print("campaign-ID = "+String(describing: inAppStatus.campaignID))
                print("title = "+String(describing: inAppStatus.title))
                print("urlString = "+String(describing: inAppStatus.urlString))

            }

            //...
            //Now dismiss the Inapp UI
            Pyze.dismiss(inAppNotificationUI: true)
}

or in viewDidAppear show UI if new messages are available

[Pyze countNewUnFetched:^(NSInteger result) {
    if (result > 0) {
        [Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                NSLog(@"message-ID =%@" , inAppStatus.messageID);
                NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                NSLog(@"title = %@",inAppStatus.title);
                NSLog(@"urlString = %@",inAppStatus.urlString);

                //...
                //Now dismiss the Inapp UI
                [Pyze dismissInAppNotificationUI:YES];
        }];
    }
}];
//Swift 3
Pyze.countNewUnFetched { (result) in
            if result > 0 {
                Pyze.showUnreadInAppNotificationUI { (inAppStatus) in

                    if let inAppStatus = inAppStatus {
                        print("buttonIndex = "+String(describing: inAppStatus.buttonIndex))
                        print("message-ID = "+String(describing: inAppStatus.messageID))
                        print("campaign-ID = "+String(describing: inAppStatus.campaignID))
                        print("title = "+String(describing: inAppStatus.title))
                        print("urlString = "+String(describing: inAppStatus.urlString))

                    }

                    //...
                    //Now dismiss the Inapp UI
                    Pyze.dismiss(inAppNotificationUI: true)
                }
            }
}

or use following showUnreadInAppNotificationUIWithCompletionHandler:... method to customize the look and feel of the In-App Message Navigation Bar buttons, and show Read, Unread or Both messages. Upto twenty previously read messages are cached, so your users can view them using the PyzeInAppTypeUnread or PyzeInAppTypeRead enumerations.

//Objective-C
[Pyze showInAppNotificationUIForDisplayMessages:PyzeInAppTypeAll
                                navigationTextColor:[UIColor greenColor]
                              withCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                                  NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                                  NSLog(@"message-ID =%@" , inAppStatus.messageID);
                                  NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                                  NSLog(@"title = %@",inAppStatus.title);
                                  NSLog(@"urlString = %@",inAppStatus.urlString);

                                  //...
                                  //Now dismiss the Inapp UI
                                  [Pyze dismissInAppNotificationUI:YES];
                              }];
// Swift 3
Pyze.showInAppNotificationUI(forDisplayMessages: .typeAll, navigationTextColor: .green) { (inAppStatus) in

            if let inAppStatus = inAppStatus {
                print("buttonIndex = \(inAppStatus.buttonIndex)")
                print("message-ID = \(inAppStatus.messageID)")
                print("campaign-ID = \(inAppStatus.campaignID)")
                print("title = \(inAppStatus.title)")
                print("urlString = \(inAppStatus.urlString)")

                if inAppStatus.status == .deepLinkCallFailed {
                    print("DeepLink Call Failed")
                } else if inAppStatus.status == .deepLinkCallSuccessful {
                    print("DeepLink Call Successful")
                } else if inAppStatus.status == .deepLinkNotProvided {
                    print("DeepLink Not Provided")
                }
            }


            //...
            // Now dismiss the InApp UI
            Pyze.dismiss(inAppNotificationUI: true)

        }
    }
Helper and Sample Code that uses a Button with a badge, Button handler delegate, in a few lines of code
  • Objective-C code
//Objective-C
#import "ViewController.h"
#import <Pyze/Pyze.h>


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *showMessagesButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [Pyze countNewUnFetched:^(NSInteger result) {
        if (result > 0)
            [Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                NSLog(@"message-ID =%@" , inAppStatus.messageID);
                NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                NSLog(@"title = %@",inAppStatus.title);
                NSLog(@"urlString = %@",inAppStatus.urlString);

                //...
                //Now dismiss the Inapp UI
                [Pyze dismissInAppNotificationUI:YES];
            }];
    }];

    [Pyze addBadge:self.showMessagesButton]; //1
}

- (IBAction)didTapShowMessage:(id)sender {
    [Pyze showInAppNotificationUIForDisplayMessages:PyzeInAppTypeAll
                                navigationTextColor:[UIColor greenColor]
                              withCompletionHandler:^(PyzeInAppStatus *inAppStatus) {

                                  NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                                  NSLog(@"message-ID =%@" , inAppStatus.messageID);
                                  NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                                  NSLog(@"title = %@",inAppStatus.title);
                                  NSLog(@"urlString = %@",inAppStatus.urlString);

                                  if (inAppStatus.status == PyzeDeepLinkCallFailed)
                                      NSLog(@"DeepLink Call Failed");
                                  else if (inAppStatus.status == PyzeDeepLinkCallSuccessful)
                                      NSLog(@"DeepLink Call Successful");
                                  else if (inAppStatus.status == PyzeDeepLinkNotProvided)
                                      NSLog(@"DeepLink Not Provided");

                                  //...
                                  //Now dismiss the Inapp UI
                                  [Pyze dismissInAppNotificationUI:YES];
    }];
}


@end
  • Subset of Swift code
//Swift 2
import Pyze
class ViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Pyze.addBadge(self.showMessagesButton)
        //1
    }

    @IBAction func didTapShowMessage(sender: AnyObject) {
        Pyze.showInAppNotificationUI(forDisplayMessages: PyzeInAppTypeAll,
                                    navigationTextColor: UIColor.green,
                                  withCompletionHandler: {(_ inAppStatus: PyzeInAppStatus) -> Void in
            print("buttonIndex = \(Int(inAppStatus.buttonIndex))")
            print("message-ID =\(inAppStatus.messageID)")
            print("campaign-ID = \(inAppStatus.campaignID)")
            print("title = \(inAppStatus.title)")
            print("urlString = \(inAppStatus.urlString)")

            if inAppStatus.status == PyzeDeepLinkCallFailed {
                print("DeepLink Call Failed")
            } else if inAppStatus.status == PyzeDeepLinkCallSuccessful {
                print("DeepLink Call Successful")
            } else if inAppStatus.status == PyzeDeepLinkNotProvided {
                print("DeepLink Not Provided")
            }

            //...
            //Now dismiss the Inapp UI
            Pyze.dismiss(inAppNotificationUI: true)
        })
    }
}
//Swift 3
import Pyze
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Pyze.addBadge(self.showMessageButton)
    }


    @IBAction func didTapShowMessage(_ sender: UIControl) {
        Pyze.showInAppNotificationUI(forDisplayMessages: .typeAll, navigationTextColor: .green) { (inAppStatus) in

   if let inAppStatus = inAppStatus {

                print("buttonIndex = \(inAppStatus.buttonIndex)")
                print("message-ID = \(inAppStatus.messageID)")
                print("campaign-ID = \(inAppStatus.campaignID)")
                print("title = \(inAppStatus.title)")
                print("urlString = \(inAppStatus.urlString)")


                if inAppStatus.status == .deepLinkCallFailed {
                    print("DeepLink Call Failed")
                } else if inAppStatus.status == .deepLinkCallSuccessful {
                    print("DeepLink Call Successful")
                } else if inAppStatus.status == .deepLinkNotProvided {
                    print("DeepLink Not Provided")
                }
            }

            //...
            // Now dismiss the InApp UI

        }
  Pyze.dismiss(inAppNotificationUI: true)
}
  • Helper method: Add a badge to indicate unfetched & new messages

A badge indicates new unread messages. It can be easily implemented with one call.

Add a button in your view controller using Storyboard or Programmatically and obtain a reference to the button. For example, In your view controller’s ViewDidAppear you can call addBadge``: method which will add the badge to the control passed in. (e.g. aUIButton,UILabelor anUIView```).

[Pyze addBadge:self.showMessagesButton]; //1
Option 2. Build your own user interface (iOS, tvOS & watchOS)

You can provide your own user interface for in-app messages using the base level APIs

  • Get Count of New and Unfetched In-App Messages

To get the count of new and un-fetched in-app messages you can call completionHandler method

//Objective-C
[Pyze countNewUnFetched:^(NSInteger result) {
    NSLog(@"New and Unfetched messages count: %", result);
}];
//Swift 2
Pyze.countNewUnFetched({(result: Int) -> Void in
   NSLog("New and Unfetched messages count: %", result)
})
//Swift 3
Pyze.countNewUnFetched { (count) in
    print("New and Unfetched messages count: \(count)")
}
  • Get Message Headers

To get the message headers call the following method. Upto 20 messages are cached within the SDK. Using PyzeInAppMessageType you can fetch new unfetched messages, or previously fetched and cached in-app messages or you can get all messages.

Usage

//Objective-C
[Pyze  getMessageHeadersForType:PyzeInAppTypeAll
          withCompletionHandler:^(NSArray * messageHeaders) {

            for (NSDictionary * messageHeader in messageHeaders) {
                //Log all message headers
                NSLog(@"message id: %@, content id: %@ message read status: %d",
                        messageHeader[@"mid"],messageHeader[@"cid"],
                        [messageHeader[@"contentRead"] boolValue]);

              }

}];
//Swift 2
Pyze.getMessageHeadersForType(PyzeInAppTypeAll, withCompletionHandler: {(
            messageHeaders: [AnyObject]) -> Void in
   for messageHeader: [NSObject : AnyObject] in messageHeaders {
       //Log all message headers
       NSLog("message id: %@, content id: %@ message read status: %d",
               messageHeader["mid"], messageHeader["cid"],
               CBool(messageHeader["contentRead"])!)
   }
})
// Swift 3   
    Pyze.getMessageHeaders(for: .typeAll) { (messageHeaders) in

             if let messageHeaders = messageHeaders {
                    for messageHeader in messageHeaders {
                      //Log all message headers
                        if let messageHeader = messageHeader as? [String:Any] {
                         print("message id: \(String(describing: messageHeader["mid"])), \(String(describing: messageHeader["cid"])), \(String(describing: (messageHeader["contentRead"])))")
                      }
                  }
            }        
    }
  • Get Message Body

To get the message body call the getMessageBodyWithCampaignID method with details of the messageHeaders

Usage

//Objective-C
[Pyze getMessageBodyWithCampaignID:dictionary[@"cid"] andMessageID:dictionary[@"mid"]
        withCompletionHandler:^(NSDictionary * messageBody) {

    if (messageBody) {

        NSDictionary * payload = messageBody[@"payload"];
        if (payload) {

            if (payload[@"templateData"]) {

                NSData * d = [payload[@"templateData"] dataUsingEncoding:NSUTF8StringEncoding];

                NSDictionary * template = [NSJSONSerialization JSONObjectWithData:d
                                                                          options:0
                                                                            error:nil];

                NSLog(@"title = %@ , message = %@, template-id = %@",
                      payload[@"title"], payload[@"msg"], payload[@"templateId"]);

                if (template) {
                    NSString * imageSourceURL = template[@"imageSourceURL"];
                    NSString * titleColor = template[@"titleColor"];
                    NSString * msgColor = template[@"msgColor"];
                    int imageWidth = [template[@"imageWidth"] integerValue];
                    int imageHeight = [template[@"imageHeight"] integerValue];

                    NSLog(@"img src: %@, width: %d, height: %d, msgColor: %@, titleColor: %@",
                          imageSourceURL, imageWidth, imageHeight, msgColor, titleColor );

                    NSArray * buttons = [NSArray arrayWithArray:template[@"buttons"]];
                    for (NSArray * buttonData in buttons) {
                        NSLog(@"BtnTitle: %@, deep-link: %@, BtnBgClr: %@, BtnTextClr: %@",
                              buttonData[0], buttonData[1], buttonData[2], buttonData[3]);
                    }
                }
            }
        }
    }
}];
//Swift 2
Pyze.getMessageBodyWithCampaignID(dictionary["cid"], andMessageID: dictionary["mid"], withCompletionHandler: {(messageBody: [NSObject : AnyObject]) -> Void in
   if messageBody != "" {
       var payload: [NSObject : AnyObject] = messageBody["payload"]
       if payload != nil {
           if payload["templateData"] {
               var d: NSData = payload["templateData"].dataUsingEncoding(NSUTF8StringEncoding)
               var template: [NSObject : AnyObject] = NSJSONSerialization.JSONObjectWithData(d, options: 0, error: nil)
               NSLog("title = %@ , message = %@, template-id = %@",
                       payload["title"], payload["msg"], payload["templateId"])
               if template != nil {
                   var imageSourceURL: String = template["imageSourceURL"]
                   var titleColor: String = template["titleColor"]
                   var msgColor: String = template["msgColor"]
                   var imageWidth: Int = CInteger(template["imageWidth"])!
        var imageHeight: Int = CInteger(template["imageHeight"])!
        NSLog("img src: %@, width: %d, height: %d, msgColor: %@, titleColor: %@",         
            imageSourceURL, imageWidth, imageHeight, msgColor, titleColor)
        var buttons: [AnyObject] = [AnyObject](array: template["buttons"])
        for buttonData: [AnyObject] in buttons {
        NSLog("BtnTitle: %@, deep-link: %@, BtnBgClr: %@, BtnTextClr: %@",
            buttonData[0], buttonData[1], buttonData[2], buttonData[3])
        }
      }
           }
       }
   }
}];
//Swift 3
            Pyze.getMessageBody(withCampaignID: dictionary["cid"] as! String, andMessageID: dictionary["mid"] as! String) { (messageBody) in


            if let messageBody = messageBody {
                if let payload : [String:Any] = messageBody["payload"] as? [String : Any] {
                    if let templateData = payload["templateData"] as? String {
                        if let d:Data = templateData.data(using: .utf8) {

                            do {
                                let template = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions.init(rawValue: 0))

                                if template is [String:Any] {
                                    var templateDict = template as! [String:Any]


                                    print("title = "+String(describing: payload["title"])+"message = "+String(describing: payload["msg"])+" template-id = "+String(describing: payload["templateId"]))

                                    let imageSourceURL = templateDict["imageSourceURL"] ?? ""
                                    let titleColor = templateDict["titleColor"] ?? ""
                                    let msgColor = templateDict["msgColor"] ?? ""
                                    let imageWidth = templateDict["imageWidth"] as? Int ?? 0
                                    let imageHeight = templateDict["imageHeight"] as? Int ?? 0

                                    print("img src : "+String(describing: imageSourceURL)+" width : "+String(describing: imageWidth)+" height: "+String(describing: imageHeight)+" msgColor : "+String(describing: msgColor)+" titleColor : "+String(describing: titleColor))


                                    let buttons = templateDict["buttons"] as? [[String]] ?? []

                                    for button in buttons {
                                        print("BtnTitle : "+button[0]+" deep-link : "+button[1]+" BtnBgClr : "+button[2]+" BtnTextClr : "+button[3])
                                    }

                                }

                            } catch let error {
                                print("Error in parsing : \(error.localizedDescription)")
                            }

                        }
                    }
                }

            }

        }
//Swift 4
    Pyze.getMessageBody(withCampaignID: (dictionary["cid"] as? String ?? ""), andMessageID: (dictionary["mid"] as? String ?? "")) { (messageBody) in
        
        if let messageBody = messageBody {
            
            if let payload:[String:Any] = messageBody["payload"] as? [String:Any] {
                if let templateData:String = payload["templateData"] as? String {
                    if let d:Data = templateData.data(using: .utf8) {
                        
                        do {
                            let template = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions.init(rawValue: 0))
                            
                            if template is [String:Any] {
                                var templateDict = template as! [String:Any]
                                
                                print("title = "+String(describing: payload["title"])+"message = "+String(describing: payload["msg"])+" template-id = "+String(describing: payload["templateId"]))
                                
                                let imageSourceURL = templateDict["imageSourceURL"] ?? ""
                                let titleColor = templateDict["titleColor"] ?? ""
                                let msgColor = templateDict["msgColor"] ?? ""
                                let imageWidth = templateDict["imageWidth"] as? Int ?? 0
                                let imageHeight = templateDict["imageHeight"] as? Int ?? 0
                                
                                print("img src : "+String(describing: imageSourceURL)+" width : "+String(describing: imageWidth)+" height: "+String(describing: imageHeight)+" msgColor : "+String(describing: msgColor)+" titleColor : "+String(describing: titleColor))
                                    
                                let buttons = templateDict["buttons"] as? [[String]] ?? []
                                
                                for button in buttons {
                                    print("BtnTitle : "+button[0]+" deep-link : "+button[1]+" BtnBgClr : "+button[2]+" BtnTextClr : "+button[3])
                                } 
                            }
                        }  catch let error {
                            print("Error in parsing : \(error.localizedDescription)")
                        }
                        
                    }
                }
            }
        }
        
    }
Sending In-App notifications from growth.pyze.com

In-app notifications allow app developers to reach out to app users when they use your app. In-App Notifications are deeply integrated in growth.pyze.com and allow app developers to reach out to users from manually from Dynamic Funnels and Intelligence Explorer, and automatically based on workflows and campaigns from Growth Automation. For illustration purposes, we will send In-App Notifications from Dynamic Funnels.

  • Sending In-App notifications from Dynamic Funnels

Create an event sequence, specify filters. You can reach out from either Dynamic Funnels or from Recent Sequences

Create and send an In-app Notification. In this example, we will inform users of a tour we created for users

View progress in Campaign History

In-App Notifications

Enable In-app Notifications in your App

In-app notifications allow app developers to reach out to app users when they use your app. In-App Notifications are deeply integrated in Pyze Growth Intelligence and allow app developers to reach out to users from manually from Dynamic Funnels and Intelligence Explorer, and automatically based on workflows and campaigns from Growth Automation.

App developers have full control over when to display the in-app messages and have two options: use the user interface provided by Pyze or develop their own.

Option 1. Use Pyze provided user interface (iOS & tvOS)
Invoke built-in User Interface from your app
  • You can look for In-App messages and invoke the built-in UI anywhere in your app. For example, on a button click or in your viewDidAppear method or when an app is launched or resumed.

Invoke UI from your app

In your button tap handler, call showUnreadInAppNotificationUIWithCompletionHandler:

//Objective-C
[Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus){
    NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
    NSLog(@"message-ID =%@" , inAppStatus.messageID);
    NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
    NSLog(@"title = %@",inAppStatus.title);
    NSLog(@"urlString = %@",inAppStatus.urlString);

    //...
    //Now dismiss the Inapp UI
    [Pyze dismissInAppNotificationUI:YES];
}];
// Swift 3
Pyze.showUnreadInAppNotificationUI { (inAppStatus) in

            if let inAppStatus = inAppStatus {
                print("buttonIndex = "+String(describing: inAppStatus.buttonIndex))
                print("message-ID = "+String(describing: inAppStatus.messageID))
                print("campaign-ID = "+String(describing: inAppStatus.campaignID))
                print("title = "+String(describing: inAppStatus.title))
                print("urlString = "+String(describing: inAppStatus.urlString))

            }

            //...
            //Now dismiss the Inapp UI
            Pyze.dismiss(inAppNotificationUI: true)
}

or in viewDidAppear show UI if new messages are available

[Pyze countNewUnFetched:^(NSInteger result) {
    if (result > 0) {
        [Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                NSLog(@"message-ID =%@" , inAppStatus.messageID);
                NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                NSLog(@"title = %@",inAppStatus.title);
                NSLog(@"urlString = %@",inAppStatus.urlString);

                //...
                //Now dismiss the Inapp UI
                [Pyze dismissInAppNotificationUI:YES];
        }];
    }
}];
//Swift 3
Pyze.countNewUnFetched { (result) in
            if result > 0 {
                Pyze.showUnreadInAppNotificationUI { (inAppStatus) in

                    if let inAppStatus = inAppStatus {
                        print("buttonIndex = "+String(describing: inAppStatus.buttonIndex))
                        print("message-ID = "+String(describing: inAppStatus.messageID))
                        print("campaign-ID = "+String(describing: inAppStatus.campaignID))
                        print("title = "+String(describing: inAppStatus.title))
                        print("urlString = "+String(describing: inAppStatus.urlString))

                    }

                    //...
                    //Now dismiss the Inapp UI
                    Pyze.dismiss(inAppNotificationUI: true)
                }
            }
}

or use following showUnreadInAppNotificationUIWithCompletionHandler:... method to customize the look and feel of the In-App Message Navigation Bar buttons, and show Read, Unread or Both messages. Upto twenty previously read messages are cached, so your users can view them using the PyzeInAppTypeUnread or PyzeInAppTypeRead enumerations.

//Objective-C
[Pyze showInAppNotificationUIForDisplayMessages:PyzeInAppTypeAll
                                navigationTextColor:[UIColor greenColor]
                              withCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                                  NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                                  NSLog(@"message-ID =%@" , inAppStatus.messageID);
                                  NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                                  NSLog(@"title = %@",inAppStatus.title);
                                  NSLog(@"urlString = %@",inAppStatus.urlString);

                                  //...
                                  //Now dismiss the Inapp UI
                                  [Pyze dismissInAppNotificationUI:YES];
                              }];
// Swift 3
Pyze.showInAppNotificationUI(forDisplayMessages: .typeAll, navigationTextColor: .green) { (inAppStatus) in

            if let inAppStatus = inAppStatus {
                print("buttonIndex = \(inAppStatus.buttonIndex)")
                print("message-ID = \(inAppStatus.messageID)")
                print("campaign-ID = \(inAppStatus.campaignID)")
                print("title = \(inAppStatus.title)")
                print("urlString = \(inAppStatus.urlString)")

                if inAppStatus.status == .deepLinkCallFailed {
                    print("DeepLink Call Failed")
                } else if inAppStatus.status == .deepLinkCallSuccessful {
                    print("DeepLink Call Successful")
                } else if inAppStatus.status == .deepLinkNotProvided {
                    print("DeepLink Not Provided")
                }
            }


            //...
            // Now dismiss the InApp UI
            Pyze.dismiss(inAppNotificationUI: true)

        }
    }
Helper and Sample Code that uses a Button with a badge, Button handler delegate, in a few lines of code
  • Objective-C code
//Objective-C
#import "ViewController.h"
#import <Pyze/Pyze.h>


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *showMessagesButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [Pyze countNewUnFetched:^(NSInteger result) {
        if (result > 0)
            [Pyze showUnreadInAppNotificationUIWithCompletionHandler:^(PyzeInAppStatus *inAppStatus) {
                NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                NSLog(@"message-ID =%@" , inAppStatus.messageID);
                NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                NSLog(@"title = %@",inAppStatus.title);
                NSLog(@"urlString = %@",inAppStatus.urlString);

                //...
                //Now dismiss the Inapp UI
                [Pyze dismissInAppNotificationUI:YES];
            }];
    }];

    [Pyze addBadge:self.showMessagesButton]; //1
}

- (IBAction)didTapShowMessage:(id)sender {
    [Pyze showInAppNotificationUIForDisplayMessages:PyzeInAppTypeAll
                                navigationTextColor:[UIColor greenColor]
                              withCompletionHandler:^(PyzeInAppStatus *inAppStatus) {

                                  NSLog(@"buttonIndex = %d", (int)inAppStatus.buttonIndex);
                                  NSLog(@"message-ID =%@" , inAppStatus.messageID);
                                  NSLog(@"campaign-ID = %@", inAppStatus.campaignID);
                                  NSLog(@"title = %@",inAppStatus.title);
                                  NSLog(@"urlString = %@",inAppStatus.urlString);

                                  if (inAppStatus.status == PyzeDeepLinkCallFailed)
                                      NSLog(@"DeepLink Call Failed");
                                  else if (inAppStatus.status == PyzeDeepLinkCallSuccessful)
                                      NSLog(@"DeepLink Call Successful");
                                  else if (inAppStatus.status == PyzeDeepLinkNotProvided)
                                      NSLog(@"DeepLink Not Provided");

                                  //...
                                  //Now dismiss the Inapp UI
                                  [Pyze dismissInAppNotificationUI:YES];
    }];
}


@end
  • Subset of Swift code
//Swift 2
import Pyze
class ViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Pyze.addBadge(self.showMessagesButton)
        //1
    }

    @IBAction func didTapShowMessage(sender: AnyObject) {
        Pyze.showInAppNotificationUI(forDisplayMessages: PyzeInAppTypeAll,
                                    navigationTextColor: UIColor.green,
                                  withCompletionHandler: {(_ inAppStatus: PyzeInAppStatus) -> Void in
            print("buttonIndex = \(Int(inAppStatus.buttonIndex))")
            print("message-ID =\(inAppStatus.messageID)")
            print("campaign-ID = \(inAppStatus.campaignID)")
            print("title = \(inAppStatus.title)")
            print("urlString = \(inAppStatus.urlString)")

            if inAppStatus.status == PyzeDeepLinkCallFailed {
                print("DeepLink Call Failed")
            } else if inAppStatus.status == PyzeDeepLinkCallSuccessful {
                print("DeepLink Call Successful")
            } else if inAppStatus.status == PyzeDeepLinkNotProvided {
                print("DeepLink Not Provided")
            }

            //...
            //Now dismiss the Inapp UI
            Pyze.dismiss(inAppNotificationUI: true)
        })
    }
}
//Swift 3
import Pyze
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Pyze.addBadge(self.showMessageButton)
    }


    @IBAction func didTapShowMessage(_ sender: UIControl) {
        Pyze.showInAppNotificationUI(forDisplayMessages: .typeAll, navigationTextColor: .green) { (inAppStatus) in

   if let inAppStatus = inAppStatus {

                print("buttonIndex = \(inAppStatus.buttonIndex)")
                print("message-ID = \(inAppStatus.messageID)")
                print("campaign-ID = \(inAppStatus.campaignID)")
                print("title = \(inAppStatus.title)")
                print("urlString = \(inAppStatus.urlString)")


                if inAppStatus.status == .deepLinkCallFailed {
                    print("DeepLink Call Failed")
                } else if inAppStatus.status == .deepLinkCallSuccessful {
                    print("DeepLink Call Successful")
                } else if inAppStatus.status == .deepLinkNotProvided {
                    print("DeepLink Not Provided")
                }
            }

            //...
            // Now dismiss the InApp UI

        }
  Pyze.dismiss(inAppNotificationUI: true)
}
  • Helper method: Add a badge to indicate unfetched & new messages

A badge indicates new unread messages. It can be easily implemented with one call.

Add a button in your view controller using Storyboard or Programmatically and obtain a reference to the button. For example, In your view controller’s ViewDidAppear you can call addBadge``: method which will add the badge to the control passed in. (e.g. aUIButton,UILabelor anUIView```).

[Pyze addBadge:self.showMessagesButton]; //1
Option 2. Build your own user interface (iOS, tvOS & watchOS)

You can provide your own user interface for in-app messages using the base level APIs

  • Get Count of New and Unfetched In-App Messages

To get the count of new and un-fetched in-app messages you can call completionHandler method

//Objective-C
[Pyze countNewUnFetched:^(NSInteger result) {
    NSLog(@"New and Unfetched messages count: %", result);
}];
//Swift 2
Pyze.countNewUnFetched({(result: Int) -> Void in
   NSLog("New and Unfetched messages count: %", result)
})
//Swift 3
Pyze.countNewUnFetched { (count) in
    print("New and Unfetched messages count: \(count)")
}
  • Get Message Headers

To get the message headers call the following method. Upto 20 messages are cached within the SDK. Using PyzeInAppMessageType you can fetch new unfetched messages, or previously fetched and cached in-app messages or you can get all messages.

Usage

//Objective-C
[Pyze  getMessageHeadersForType:PyzeInAppTypeAll
          withCompletionHandler:^(NSArray * messageHeaders) {

            for (NSDictionary * messageHeader in messageHeaders) {
                //Log all message headers
                NSLog(@"message id: %@, content id: %@ message read status: %d",
                        messageHeader[@"mid"],messageHeader[@"cid"],
                        [messageHeader[@"contentRead"] boolValue]);

              }

}];
//Swift 2
Pyze.getMessageHeadersForType(PyzeInAppTypeAll, withCompletionHandler: {(
            messageHeaders: [AnyObject]) -> Void in
   for messageHeader: [NSObject : AnyObject] in messageHeaders {
       //Log all message headers
       NSLog("message id: %@, content id: %@ message read status: %d",
               messageHeader["mid"], messageHeader["cid"],
               CBool(messageHeader["contentRead"])!)
   }
})
// Swift 3   
    Pyze.getMessageHeaders(for: .typeAll) { (messageHeaders) in

             if let messageHeaders = messageHeaders {
                    for messageHeader in messageHeaders {
                      //Log all message headers
                        if let messageHeader = messageHeader as? [String:Any] {
                         print("message id: \(String(describing: messageHeader["mid"])), \(String(describing: messageHeader["cid"])), \(String(describing: (messageHeader["contentRead"])))")
                      }
                  }
            }        
    }
  • Get Message Body

To get the message body call the getMessageBodyWithCampaignID method with details of the messageHeaders

Usage

//Objective-C
[Pyze getMessageBodyWithCampaignID:dictionary[@"cid"] andMessageID:dictionary[@"mid"]
        withCompletionHandler:^(NSDictionary * messageBody) {

    if (messageBody) {

        NSDictionary * payload = messageBody[@"payload"];
        if (payload) {

            if (payload[@"templateData"]) {

                NSData * d = [payload[@"templateData"] dataUsingEncoding:NSUTF8StringEncoding];

                NSDictionary * template = [NSJSONSerialization JSONObjectWithData:d
                                                                          options:0
                                                                            error:nil];

                NSLog(@"title = %@ , message = %@, template-id = %@",
                      payload[@"title"], payload[@"msg"], payload[@"templateId"]);

                if (template) {
                    NSString * imageSourceURL = template[@"imageSourceURL"];
                    NSString * titleColor = template[@"titleColor"];
                    NSString * msgColor = template[@"msgColor"];
                    int imageWidth = [template[@"imageWidth"] integerValue];
                    int imageHeight = [template[@"imageHeight"] integerValue];

                    NSLog(@"img src: %@, width: %d, height: %d, msgColor: %@, titleColor: %@",
                          imageSourceURL, imageWidth, imageHeight, msgColor, titleColor );

                    NSArray * buttons = [NSArray arrayWithArray:template[@"buttons"]];
                    for (NSArray * buttonData in buttons) {
                        NSLog(@"BtnTitle: %@, deep-link: %@, BtnBgClr: %@, BtnTextClr: %@",
                              buttonData[0], buttonData[1], buttonData[2], buttonData[3]);
                    }
                }
            }
        }
    }
}];
//Swift 2
Pyze.getMessageBodyWithCampaignID(dictionary["cid"], andMessageID: dictionary["mid"], withCompletionHandler: {(messageBody: [NSObject : AnyObject]) -> Void in
   if messageBody != "" {
       var payload: [NSObject : AnyObject] = messageBody["payload"]
       if payload != nil {
           if payload["templateData"] {
               var d: NSData = payload["templateData"].dataUsingEncoding(NSUTF8StringEncoding)
               var template: [NSObject : AnyObject] = NSJSONSerialization.JSONObjectWithData(d, options: 0, error: nil)
               NSLog("title = %@ , message = %@, template-id = %@",
                       payload["title"], payload["msg"], payload["templateId"])
               if template != nil {
                   var imageSourceURL: String = template["imageSourceURL"]
                   var titleColor: String = template["titleColor"]
                   var msgColor: String = template["msgColor"]
                   var imageWidth: Int = CInteger(template["imageWidth"])!
        var imageHeight: Int = CInteger(template["imageHeight"])!
        NSLog("img src: %@, width: %d, height: %d, msgColor: %@, titleColor: %@",         
            imageSourceURL, imageWidth, imageHeight, msgColor, titleColor)
        var buttons: [AnyObject] = [AnyObject](array: template["buttons"])
        for buttonData: [AnyObject] in buttons {
        NSLog("BtnTitle: %@, deep-link: %@, BtnBgClr: %@, BtnTextClr: %@",
            buttonData[0], buttonData[1], buttonData[2], buttonData[3])
        }
      }
           }
       }
   }
}];
//Swift 3
            Pyze.getMessageBody(withCampaignID: dictionary["cid"] as! String, andMessageID: dictionary["mid"] as! String) { (messageBody) in


            if let messageBody = messageBody {
                if let payload : [String:Any] = messageBody["payload"] as? [String : Any] {
                    if let templateData = payload["templateData"] as? String {
                        if let d:Data = templateData.data(using: .utf8) {

                            do {
                                let template = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions.init(rawValue: 0))

                                if template is [String:Any] {
                                    var templateDict = template as! [String:Any]


                                    print("title = "+String(describing: payload["title"])+"message = "+String(describing: payload["msg"])+" template-id = "+String(describing: payload["templateId"]))

                                    let imageSourceURL = templateDict["imageSourceURL"] ?? ""
                                    let titleColor = templateDict["titleColor"] ?? ""
                                    let msgColor = templateDict["msgColor"] ?? ""
                                    let imageWidth = templateDict["imageWidth"] as? Int ?? 0
                                    let imageHeight = templateDict["imageHeight"] as? Int ?? 0

                                    print("img src : "+String(describing: imageSourceURL)+" width : "+String(describing: imageWidth)+" height: "+String(describing: imageHeight)+" msgColor : "+String(describing: msgColor)+" titleColor : "+String(describing: titleColor))


                                    let buttons = templateDict["buttons"] as? [[String]] ?? []

                                    for button in buttons {
                                        print("BtnTitle : "+button[0]+" deep-link : "+button[1]+" BtnBgClr : "+button[2]+" BtnTextClr : "+button[3])
                                    }

                                }

                            } catch let error {
                                print("Error in parsing : \(error.localizedDescription)")
                            }

                        }
                    }
                }

            }

        }
//Swift 4
    Pyze.getMessageBody(withCampaignID: (dictionary["cid"] as? String ?? ""), andMessageID: (dictionary["mid"] as? String ?? "")) { (messageBody) in
        
        if let messageBody = messageBody {
            
            if let payload:[String:Any] = messageBody["payload"] as? [String:Any] {
                if let templateData:String = payload["templateData"] as? String {
                    if let d:Data = templateData.data(using: .utf8) {
                        
                        do {
                            let template = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions.init(rawValue: 0))
                            
                            if template is [String:Any] {
                                var templateDict = template as! [String:Any]
                                
                                print("title = "+String(describing: payload["title"])+"message = "+String(describing: payload["msg"])+" template-id = "+String(describing: payload["templateId"]))
                                
                                let imageSourceURL = templateDict["imageSourceURL"] ?? ""
                                let titleColor = templateDict["titleColor"] ?? ""
                                let msgColor = templateDict["msgColor"] ?? ""
                                let imageWidth = templateDict["imageWidth"] as? Int ?? 0
                                let imageHeight = templateDict["imageHeight"] as? Int ?? 0
                                
                                print("img src : "+String(describing: imageSourceURL)+" width : "+String(describing: imageWidth)+" height: "+String(describing: imageHeight)+" msgColor : "+String(describing: msgColor)+" titleColor : "+String(describing: titleColor))
                                    
                                let buttons = templateDict["buttons"] as? [[String]] ?? []
                                
                                for button in buttons {
                                    print("BtnTitle : "+button[0]+" deep-link : "+button[1]+" BtnBgClr : "+button[2]+" BtnTextClr : "+button[3])
                                } 
                            }
                        }  catch let error {
                            print("Error in parsing : \(error.localizedDescription)")
                        }
                        
                    }
                }
            }
        }
        
    }
Sending In-App notifications from growth.pyze.com

In-app notifications allow app developers to reach out to app users when they use your app. In-App Notifications are deeply integrated in growth.pyze.com and allow app developers to reach out to users from manually from Dynamic Funnels and Intelligence Explorer, and automatically based on workflows and campaigns from Growth Automation. For illustration purposes, we will send In-App Notifications from Dynamic Funnels.

  • Sending In-App notifications from Dynamic Funnels

Create an event sequence, specify filters. You can reach out from either Dynamic Funnels or from Recent Sequences

Create and send an In-app Notification. In this example, we will inform users of a tour we created for users

View progress in Campaign History

Enable Personalization

Personalization Intelligence™

Enable Personalization in your App To learn more about personalization see here.

In Intelligence explorer, for example, you may assign “High Value” tag to users who match the following criteria. This tag is available in your app to personalize content feed, experience, user interface or messaging.

  • High Engagement and High Loyalty or
  • High Advocacy and Seasonal Ticket Holder or
  • High Revenue or
  • High Engagement, High Advocacy, and Low or Medium Attrition Risk or

The Personalization Intelligence™ tags assigned to a user are available in the agent and are accessible via class PyzePersonalizationIntelligence

The following methods are available in this class

+getTags:

Get all tags assigned to the user. Note: Tags are case sensitive, High Value and high value are different tags.

Usage

[PyzePersonalizationIntelligence getTags:^(NSArray *tagsList) {
     NSLog(@"PyzePersonalizationIntelligence tags = %@", tagsList);
}];

+isTagSet:

Returns true if requested tag is assigned to user. Note: Tags are case sensitive, High Value and high value are different tags

Usage

NSLog(@"isTagSet = %d", [PyzePersonalizationIntelligence isTagSet:@"loyal"]);

+areAnyTagsSet:

Returns true if at least one tag is assigned. Note: Tags are case sensitive, High Value and high value are different tags.

NSLog(@"areAnyTagsSet = %d",[PyzePersonalizationIntelligence areAnyTagsSet:@[@"High value"]]);

+areAllTagsSet:

Returns true if all tags requested are assigned to user. Note: Tags are case sensitive, High Value and high value are different tags.

NSLog(@"areAllTagsSet = %d", [PyzePersonalizationIntelligence areAllTagsSet:@[@"loyal", @"whale",@"High value"]]);

Reference

Release Checklist

Before you release your App to the app store, make sure you go through the following checklist related to Pyze Smart Agent. We will keep this list up-to-date.

Change Log Level to Minimal

Change Pyze Log Level to Minimal, unless requested by Pyze support. See Pyze initialize:withLogThrottling: and Pyze logThrottling:

Switch to a production Pyze App Key

Many app developers use two PAKS, one for development and another for app store distribution. You can use #ifdef macros to maintain production and development deployments. See Pyze initialize: or Pyze initialize:withLogThrottling:

Get latest SDK

Developers should get the latest Pyze SDK during development, but it is a good time to get the latest SDK before the final test and deployment to app store. Pyze frequently updates the SDK with bug fixes and updates.

If you are using Cocoapods, and your podfile references the Pyze SDK without the version,

pod 'pyze-sdk-iOS'

all you have to do is

cd /path/to/project/
pod update

Push Notifications: Ensure you are using a Production SSL certificate and Distribution mobile provisioning profile

Before you publish your app to AppStore or make a public Ad Hoc release, ensure you created a Production SSL certificate and used a Distribution mobile provisioning profile when following the steps outlined in iOS Push Notifications page.

Also, ensure you have uploaded a Production .p12 certificate following steps mentioned in above section. Use Production Mode for Provisioning Mode.

Developer Resources

Here is a curated list of iOS resources that should be useful to iOS developers and publishers. Obviously, Google and Stackoverflow are your best bet when you know what you are looking for. Help us complete the list by contacting us at contact@pyze.com if we should add an active resource (or remove an inactive resource) or if we have not credited the sources accurately.

Updated October 2017

Apple resources

Resources

Archived resources

  • objc.io 24 issues from June 2013 to May 2015
  • Tapfame Newsletters 87 weeks of content for stakeholders in the mobile ecosystem from October 2013 to April 2016