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

  • To add an application to the Pyze platform, begin by selecting Settings from the Navigation Pane.
  • Under the Apps Tab, click the Add App+ button at the top right of the window.
  • Enter the App Name and Appstore URL (if available), Platform (iOS, Android, Web/SaaS, tvOS, watchOS) and select your Timezone.

3. Copy Your Pyze App Key

Once you add your new app, refresh the page. Navigate to your newly added app’s settings by selecting the app from the drop-down list. The Pyze App Key will be displayed below to the right (bEIUdgQ0REW-31ZWvFXrEQ in this example). Copy Pyze App Key.

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

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.

Enable Logging

Pyze Initialize API accepts optional 2nd parameter. To control the debug log level. Default log level for the Pyze SDK is set as minimal.

Following are the logging level options you could use.

PyzelogLevelMinimal
PyzelogLevelWarnings
PyzelogLevelErrors
PyzelogLevelAll

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 @implementation block of your Extension delegate code file. (usually ExtensionDelegate.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:

    #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" 
        }
    ];
    func yourMethod() {
        PyzeAd.postAdRequested("https://www.google.com",
            fromAppScreen: "home",
            withAdSize: "320x160",
            adType: "Banner",
            withAttributes: ["FirstName": "John", "LastName" : "Smith", "Age" : "28"])
    }
    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).

    [PyzeCustomEvent postWithEventName:@"My Blog Read Event"
        withAttributes:@{
            @"Author" : @"nav iosnavtabsS",
            @"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 iosnavtabsS", @"Author",
        @"Registered", @"User Status",
        @"blog.pyze.com", @"Article Source",
        @"2015-12-17", @"Publish Time",
        nil];
    [PyzeCustomEvent postWithEventName:@"Blog Read" withAttributes:attributes];
 
    PyzeCustomEvent.postWithEventName("Blog Read",
        withAttributes: ["Author": "nav iosnavtabsS", "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 iosnavtabsS",
        "User_Status" : "Registered",
        "CNN" : "Article Source",
        "12-17-2015" : "Publish Time"
    ]

    PyzeCustomEvent.postWithEventName("Blog Read", withAttributes: attributes)
 
    PyzeCustomEvent.post(withEventName: "Blog Read", withAttributes: ["Author": "nav iosnavtabsS", "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 iosnavtabsS",
        "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

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.

1. Generate Personal Information Exchange PKCS #12 (.p12)
  • Go to Certificates, Identifiers & Profiles page of your apple developer account.
  • Select Identifiers and go to YOUR_APP_IDENTIFIER.
  • Under Capabilities go to Push Notifications and select Configure
  • Now under Development/Production SSL Certificate select Create Certificate
  • Upload the Certificate Signing Request as mentioned here
  • Download the certificate generated and add to the Keychain Access
  • Now select the certificate just imported and choose Export.
  • Enter the password and save the .p12 to the desired location.
2. 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
  • Click Settings from the Navigation Pane
  • Select the app you want to provide keys for from the drop down list
  • 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.
  • Select daily and weekly quota limits
  • Click Save
3. Enabling Push Notifications
  • Goto to capability under application target, add capability Push Notifications and Background Modes.
  • Under Background Modes check Remote notifications.
4. Modify AppDelegate

Update AppDelegate as shown below

 

@import Pyze;
#import <UserNotifications/UserNotifications.h>

@import CoreMotion;

//Let AppDelegate inherit UNUserNotificationCenterDelegate
@interface ALAppDelegate () <UNUserNotificationCenterDelegate>
@end

@implementation ALAppDelegate

//Initialize Pyze
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [Pyze initialize:@"PYZE_APP_KEY" withLogThrottling: PyzelogLevelMinimal];
    return YES;
}

//Register for remote notification
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert +UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {}];
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[PyzeNotification getPyzeDefaultNotificationCategories]];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    [PyzeNotification initWithLaunchOptions:launchOptions];
    return YES;
}

//Set remote notification token to Pyze
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [Pyze setRemoteNotificationDeviceToken:deviceToken];
}

//Notify Pyze when push received.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    [Pyze processReceivedRemoteNotification:userInfo withState:[[UIApplication sharedApplication] applicationState] withCompletionHandler:completionHandler];
}

//Let pyze handle the remote notification action
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
    [PyzeNotification handlePushNotificationResponseWithUserinfo:response.notification.request.content.userInfo actionIdentifier:response.actionIdentifier];
    completionHandler();
}

//Enable app to view notification in foreground
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    completionHandler(UNNotificationPresentationOptionAlert);
}

@end
 

import Pyze
import UserNotifications

//Let AppDelegate inherit UNUserNotificationCenterDelegate
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    //Initialize Pyze
    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        Pyze.initialize("PYZE_APP_KEY", withLogThrottling: .PyzelogLevelMinimal)
        return true
    }

    //Register for remote notification
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self;
        UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) { granted, error in }
        UNUserNotificationCenter.current().setNotificationCategories(PyzeNotification.getPyzeDefaultNotificationCategories() as! Set<UNNotificationCategory>);
        UIApplication.shared.registerForRemoteNotifications();
        PyzeNotification.initWithLaunchOptions(launchOptions);
        return true
    }

    //Set remote notification token to Pyze
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Pyze.setRemoteNotificationDeviceToken(deviceToken);
    }

    //Notify Pyze when notification received
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Pyze.processReceivedRemoteNotification(userInfo, with: application.applicationState, withCompletionHandler: completionHandler)
    }

    //Let pyze handle the remote notification action
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        PyzeNotification.handlePushResponse(withUserinfo: response.notification.request.content.userInfo, actionIdentifier: response.actionIdentifier)
        completionHandler()
    }

    //Enable app to view notification in foreground
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler(.alert);
    }
}
5. Enable Rich Push Notification for your app.

Enable your app to receive images and gifs inside push notification messages.

  • Go to File -> New -> Target and cretea Notification Service Extension.
  • Fill the Product Name and select required language.
  • Make sure to select Embed in Application as YOUR PROJECT.
  • XCode will create a NotificationService class after adding the above extension. Replace its content by below code.
 
#import "NotificationService.h"

@interface NotificationService ()

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

@end

@implementation NotificationService

- (NSURL *) attachmentFileURLWithTempLocation:(NSURL *)location name:(NSString *)fileName {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray * domainDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [domainDirectories objectAtIndex:0];
    NSString *attachmentLocalFilePath = [documentsDirectory stringByAppendingPathComponent:@"/Pyze/"];
    if(![fileManager fileExistsAtPath:attachmentLocalFilePath]) [fileManager createDirectoryAtPath:attachmentLocalFilePath withIntermediateDirectories:NO attributes:nil error:&error];
    attachmentLocalFilePath =  [attachmentLocalFilePath stringByAppendingFormat:@"/%@",fileName];
    if([fileManager fileExistsAtPath:attachmentLocalFilePath]) {
        [fileManager removeItemAtPath:attachmentLocalFilePath error:&error];
        if (error) NSLog(@"Error in removing file : %@", error.debugDescription);
    }
    [fileManager moveItemAtPath:[location path] toPath:attachmentLocalFilePath error:&error];
    if (error) NSLog(@"Error in moving file to location : %@", error.debugDescription);
    NSURL *mediaFileURL = [NSURL fileURLWithPath:attachmentLocalFilePath];
    return mediaFileURL;
}

- (NSURLSessionDownloadTask *) loadAttachmentsWithURLString:(NSString *)urlString {
    NSURL *mediaURL = [NSURL URLWithString:urlString];
    NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithURL:mediaURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
          if (!error) {
              NSURL *mediaFileURL = [self attachmentFileURLWithTempLocation:location name:[response suggestedFilename]];
              UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:[response suggestedFilename] URL:mediaFileURL options:nil error:&error];
              if (attachment) self.bestAttemptContent.attachments = @[attachment];
              self.contentHandler(self.bestAttemptContent);
          }
      }];
    return task;
}

#pragma mark - UNNotificationServiceExtension delegate

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    self.bestAttemptContent.title = self.bestAttemptContent.title;
    self.bestAttemptContent.subtitle = self.bestAttemptContent.subtitle;
    NSString *mediaUrlString = request.content.userInfo[@"mediaUrl"];
    NSURLSessionDownloadTask *task = [self loadAttachmentsWithURLString:mediaUrlString];
    [task resume];
}

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

@end
 
import UserNotifications

class NotificationService: UNNotificationServiceExtension {

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

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        defer {
            contentHandler(bestAttemptContent ?? request.content)
        }
        guard let attachment = request.attachment else { return }
        bestAttemptContent?.attachments = [attachment]
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}

extension UNNotificationRequest {
    var attachment: UNNotificationAttachment? {
        guard let attachmentURL = content.userInfo["mediaUrl"] as? String, let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else {
            return nil
        }
        return try? UNNotificationAttachment(data: imageData, options: nil)
    }
}

extension UNNotificationAttachment {
    convenience init(data: Data, options: [NSObject: AnyObject]?) throws {
        let fileManager = FileManager.default
        let temporaryFolderName = ProcessInfo.processInfo.globallyUniqueString
        let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(temporaryFolderName, isDirectory: true)
        try fileManager.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil)
        let imageFileIdentifier = UUID().uuidString + ".jpg"
        let fileURL = temporaryFolderURL.appendingPathComponent(imageFileIdentifier)
        try data.write(to: fileURL)
        try self.init(identifier: imageFileIdentifier, url: fileURL, options: options)
    }
}

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.

Show in-app notification from your app

To display in-app notifiction scheduled, just call the below API. It’ll display the in-app message if there are any scheduled messages from growth.pyze.com.

[Pyze showInAppNotification];
Sending In-App notifications from growth.pyze.com

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

  • Sending In-App notifications from Conversion Funnels

    Create an event sequence and specify filters. You can reach out from either Build & Run or from Saved Funnels.

    Create and send an In-App Notification. In this example, we will congratulate the user for reaching a milestone with a reward.

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"]]);

User Privacy

Pyze provides APIs to allow end-users to Opt out of Data Collection and also instruct the Pyze system to forget a user’s data.

setUserOptOut

Allows end-users to opt out from data collection. Opt-out can be toggled true or false.

[Pyze setUserOptOut:true];
Pyze.setUserOptOut(true)

To resume user data collection set value to false

[Pyze setUserOptOut:false];
Pyze.setUserOptOut(false)

deleteUser

Allows end-users to opt out from data collection and delete the user in the Pyze system. We recommend you confirm this action as once a user is deleted, this cannot be undone.

[Pyze deleteUser:true]; 
Pyze.deleteUser(true)

Reference

iOS Troubleshooting Guide

  1. Missing Frameworks

    If you chose to install the Pyze Framework manually and forgot to add frameworks CoreTelephony and SystemConfiguration, following compilation errors will occur.

      "_CNCopyCurrentNetworkInfo", referenced from: ...
      "_CNCopySupportedInterfaces", referenced from: ...
      "_OBJC_CLASS_$_CTTelephonyNetworkInfo", referenced from: ...
      "_SCNetworkReachabilityCreateWithAddress", referenced from: ...
      "_SCNetworkReachabilityCreateWithName", referenced from: ...
      "_SCNetworkReachabilityScheduleWithRunLoop", referenced from: ...
      "_SCNetworkReachabilitySetCallback", referenced from: ...
      "_SCNetworkReachabilityUnscheduleFromRunLoop", referenced from: ...   
    


    Resolution: Add frameworks CoreTelephony and SystemConfiguration

  2. Missing CoreTelephony framework

    Missing CoreTelephony framework would generate the following compilation errors.

     "_OBJC_CLASS_$_CTTelephonyNetworkInfo", referenced from: ...
     "_CNCopySupportedInterfaces", referenced from: ...   
    


    Resolution: Add CoreTelephony framework

  3. Missing SystemConfiguration framework

    Missing SystemConfiguration framework would generate the following compilation errors.

     "_SCNetworkReachabilityCreateWithAddress", referenced from: ...
     "_SCNetworkReachabilityCreateWithName", referenced from: ...
     "_SCNetworkReachabilityScheduleWithRunLoop", referenced from: ...
     "_SCNetworkReachabilitySetCallback", referenced from: ...
     "_SCNetworkReachabilityUnscheduleFromRunLoop", referenced from: ...   
    


    Resolution: Add SystemConfiguration framework

  4. Following exception will be raised by calling empty PyzeAppKey passed to initializeWithKey method.

     *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
     reason: 'PyzeAppKey needs to be set via initializeWithKey: method. 
     Log on to growth.pyze.com to get it.'
    
  5. Screen flows will not automatically get updated at growth.pyze.com if you have missed adding ObjC value to Other Linker Flags under Linking of your project’s build settings.

    Resolution: Add ObjC flag

  6. Following error will be shown upon compiling your project if you are using Cocoapods and opened .xcodeproj instead of .xcworkspace.

     *** ld: library not found for -lPods-Project_Name-ObjC
     clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
  7. If you encounter following error while using Cocoapods, please ensure that your deployment target is set to 8.0.

     Specs satisfying the `pyze-sdk-iOS` dependency were found, but they required a higher minimum deployment  target.
    
  8. If you get a build spec validation error in cocoapods while installing or updating Pyze SDK as show below, please either change the target in your app to iOS 8 (from iOS 7), or use the framework version of Pyze from GitHub. See here for installing Pyze using Framework.

     ERROR | [iOS] dynamic: Dynamic frameworks and libraries are not supported on iOS 8.0 and onwards 
    
  9. If you get ‘Image not found’ error while running as shown below, ensure that @executable_path/Frameworks is added to Runpath Search Paths under Linking section of your project build settings. This usually happens if you created Xcode project version 5.x or 6.x.

     dyld: Library not loaded: @rpath/Pyze.framework/Pyze
     Referenced from: <path_to_your_app>
     Reason: image not found
    

    More info provided in this link

  10. If you encounter errors like fatal error: lipo: can't open input file: then go to Xcode project target settings and change Build Active Architecture only to YES.

If above does not solve your problem, please open a ticket and we will help you. Contact us at support@pyze.com

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