Unity

Unity SDk

Before starting your application instrumentation, ensure that you have created an app and have an appKey

Install

  1. Download the Pyze Unity Package

    Download Pyze.unity package from here

  2. Verify iOS and Android modules are installed in your Unity Installation

    Verify under File > Build Settings

  3. Import Pyze unity package in your Unity project

    From your Downloads folder by selecting Assets, Import and Custom Package…. A Pyze Menu would be added.

Initialize

After importing Pyze Unity package, you will notice the Pyze menu. Select the Initialize Pyze option and enter your Pyze App Keys for android and/or iOS platforms and select desired log level - you should default to PyzeLogLevelMinimal.

Ensure you have set the Android Minimum Api Level to 15 or higher and given a unique bundle id.

Click on Save and you are done!

Alternate manual setup

If you do not want to use, or can not use the Pyze plugin for Unity, you can also install our Android and iOS SDK’s manually.

iOS

Modify the PyzeAppController.mm file present in the, Plugin/iOS/ folder and replace the Pyze App Key with your own key and set the logThrottling attribute to desired LogLevel. If you already have an AppController, merge the two controllers accordingly.

#import "UnityAppController.h"
@import Pyze;
@interface PyzeAppController : UnityAppController {}
@end
@implementation PyzeAppController
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [Pyze initialize:@"Add your iOS Pyze App Key Here" withLogThrottling:PyzelogLevelMinimal];
    [super application:application willFinishLaunchingWithOptions:launchOptions];
    return YES;
}
@end

IMPL_APP_CONTROLLER_SUBCLASS( PyzeAppController )

Note: For and iOS generated build, -ObjC linker flag will automatically be added to your project.

Android

//Import the PyzeUnity Package
Using PyzeUnity;

//Make sure to call Pyze.initialize api, before calling any other Pyze api

void Start(){
    Pyze.Initialize ("PYZE_APP_KEY",PyzeLogLevel.PyzelogLevelMinimal);
}

Ensure “Player Settings”, Internet Access is set to require

Custom Events

Custom events allow you to easily track unique user actions within your app.

See a detailed Events Overview at api & events.

You can access the all pyze events classes from the pyze.unity namespace

Event

Attributes are any key-value pair that you can attach to an event. You can have up to 99 attributes with any event. It is highly recomended to follow our Best Practices and heavily rely on attributes to make your instrumentation as minimal and useful as possible. In a typical application, you should have many more attributes than events.

For example, to send a custom “Game End event” use:

using PyzeUnity; //Import the PyzeUnity package
    ...
    ...
Dictionary<string, object> customAttributes = new Dictionary<string, object>();
customAttributes.Add("First Name","John");
customAttributes.Add("Last Name","Smith");
customAttributes.Add("Age",25);
Pyze.PyzeEvents.Ad.PostAdRequested(
    "AdMob",            // AdNetwork
    "Settings",            // App Screen
    "300x50",            // Ad SIze
    "Banner",            // Type
    customAttributes
);

Profile

Profiles are a powerful way to add data about your users to Pyze. Use profiles to add data that is not specific to a point in time (events) and are attached to a specific user.

When a user logs in to your app, call setUserProfile to identify them to Pyze. Any events that happen after they are identified, will be attributed to this user. You should only call this method once upon the initial login of a session.

You can optionally include profile attributes.

Pyze built-in profile attributes get special handling in the pyze UI, and we will attempt to discern the data type for custom attributes based on the data recieved. There is no difference between the built-in attributes and custom ones outside of formatting applied.

//Create Pyze Profile Attributes object
Dictionary <string, string> pyzeProfileAttributes = new Dictionary<String, String>();
pyzeProfileAttributes.Add("email_id", "xyz@abc.com");
pyzeProfileAttributes.Add("date_of_birth", "1984-06-01");
pyzeProfileAttributes.Add("first_name", "John");
pyzeProfileAttributes.Add("last_name", "Jacobs");

//Create Custom Profile Attributes object
Dictionary <string, string> customProfileAttributes = new Dictionary<String, String>();
customProfileAttributes.Add("age", 29);
customProfileAttributes.Add("picode", "23200");
customProfileAttributes.Add("city", "XYZ");

//Call the setUserProfile API
Pyze.PyzeIdentity.setUserProfile(userId,pyzeProfileAttributes,customProfileAttributes);

Pyze profile attributes

Pyze User Profile Field Name Data Type/Description
background (string) User background, biography or historical data
country (string) Country codes must be sent in the ISO-3166-1 alpha-2 standard.
current_location (object) Format: {“longitude”: -33.991894, “latitude”: 25.243732}
date_of_first_use (date at which the user first used the app) String in ISO 8601 format or in yyyy-MM-dd’T’HH:mm:ss.SSSZ format.
date_of_last_use (date at which the user last used the app) String in ISO 8601 format or in yyyy-MM-dd’T’HH:mm:ss.SSSZ format.
date_of_birth (date of birth) String in format “YYYY-MM-DD”, example: 1984-06-01.
email_id (string) Email Id
email_subscribe (string) Acceptable values are “opt_in” (explicit approval to receive email messages), “opt_out” (explicit denial to email messages), and “subscribed” (neither opted in nor out).
email_hard_bounced Automatically updated when a hard bounce occurs (true or false)
email_spam_reported Automatically updated when a user marks your email as spam, via the ISP (true or false)
facebook_id facebook ID
first_name (string) User’s First name
gender (string) “M”, “F”, “O” (other), “N” (not applicable), “P” (prefer not to say) or “U” (unknown).
home_city (string) User’s Home City
image_url (string) URL of image to be associated with the user
language (string) Require language to be sent in the ISO-639-1 standard.
last_name (string) User’s Last Name
marked_email_as_spam_at (string) Date at which the user’s email was marked as spam. Must be in ISO 8601 format or in yyyy-MM-dd’T’HH:mm:ss.SSSZ format.
phone (string) Phone number
push_subscribe (string) Available values are “opted_in” (explicitly registered to receive push messages), “unsubscribed” (explicitly opted out of push messages), and “subscribed” (neither opted in nor out).
push_tokens Array of objects with app_id and token string. You may optionally provide a device_id for the device this token is associated with, e.g., [{“app_id”: App Identifier, “token”: “abcd”, “device_id”: “optional_field_value”}]. If a device_id is not provided, one will be randomly generated.
time_zone (string) Time Zone’s must be sent as per IANA Time Zone Database (e.g., “America/New_York” or “Eastern Time (US & Canada)”). Only valid values will be respected.
twitter_id Twitter ID

Updating an existing user Profile

To update user profile attributes which are already set, use the following api.

Note : Do not call this api before calling setUserProfile.

//Create Pyze Profile Attributes object
HashMap <String, String> pyzeProfileAttributes = new HashMap<String, String>();
pyzeProfileAttributes.put("email_id", "xyz@abc.com");
pyzeProfileAttributes.put("date_of_birth", "1984-06-01");
pyzeProfileAttributes.put("first_name", "John");
pyzeProfileAttributes.put("last_name", "Jacobs");

//Create Custom Profile Attributes object
HashMap <String, String> customProfileAttributes = new HashMap<String, String>();
customProfileAttributes.put("age", 29);
customProfileAttributes.put("picode", "23200");
customProfileAttributes.put("city", "XYZ");
//Call the updateUserProfileAttributes API
Pyze.PyzeIdentity.updateUserProfile(userId,pyzeProfileAttributes,customProfileAttributes);

Logging out a user

Call this api when a user logs out. Event sent after this call will have no identity attached, and will be attributed to an anonymous user.

Pyze.PyzeIdentity.resetUserProfile(); 

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) 

To resume user data collection set value to 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) 

IOS Push Notifications

Apple provides the Apple Push Notification Service (APNS) to allow app publishers to reach out to their users via push notifications.

1. Generate P12 Certificate

  • 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 create a 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)
 }
}

Android Push Notifications

Google provides the Firebase Cloud Messaging service (FCM) to allow app publishers to reach out to their users via push notifications.

Set Firebase Credentials in pyze

Login into your Firebase Console

  1. Select Your Project and Click on the Settings icon next to the Project name
  2. In the Cloud Messaging Tab, locate the Legacy Server Key and Sender ID

Login into your Pyze Account

  1. On the Settings page, select an app from the drop down menu.
  2. On the App Settings page, navigate to the Push Notifications settings from the left pane.
  3. Enter the Server key and Sender ID along with quota limits for the maximum number of push messages your app can send in a day and a week.

Integrate FCM Push Notifications in your App project

  1. Create a new Android project at https://console.firebase.google.com/ and download the google-services.json.
  1. Place the google-services.json file into Assets folder of your Unity project.
  1. Make sure that you are using the same bundle identifier in firebase and your unity project.
  2. Under the “Pyze” Menu option select, “Enable Push Notification for Android”.
  1. Paste the code displayed in the window inside the tag of your manifest file.
  1. To specify custom notification icon image, you need to place two icon images in Assets/Plugins/Android/res/drawable/ folder by name “pyze_notification_icon” and “pyze_notification_icon_transperent”.
  2. Pyze also supports Rich Push Notifications. You can send images and add custom buttons in your push notifications and increase mobile engagement.

You may refer to the Android Documentation For further UI handling options

In-App Notifications

In-app notifications allow app businesses to reach out to app users when they use your app. In-App notifications are built-in to the pyze sdk and have no additional dependecies.businesses to reach out to users from manually from Dynamic Funnels and Intelligence Explorer, and automatically based on workflows and campaigns from Growth Automation. In-App notifications can be sent from Campaigns Call the following methed, wherever you want to check for new messages and pop-up a modal with the notification:

void ShowInAppMessagesWithDefaultUI(EventHandler callback);

Debugging and Logging

Please refer to the ios and android documentation for platform-specific information

API Reference

Full API reference available here


Last modified 2021-01-07