Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Batch allows you to customize your notifications adding specific keys to the payload.
Since we allow the overriding of Apple's keys, you can use and override anything Apple accepts in the aps key. Apple's full documentation about the payload is located here
All of the following JSON examples go into the custom_payload field of both Transactional and Campaigns APIs.
You can add a badge to your iOS notifications by adding a badge key to the payload of your push. Here is how it looks:
You can add action buttons to your notification by adding a category key to the payload of your push. Here is how it looks:
You can set a custom sound for your notification by adding the sound key to your payload. All you need to do is to add your custom sound to your app bundle before choosing it. Here is how it looks:
iOS (7+) supports sending pushes that will wake up your app in the background. It works like background fetching, except that you control when your app will wake up.
This allows you to fetch new content (news feed, conversation list, etc) so your users won't have to wait for your app to sync when then open it.
First, you'll need to go in Xcode and enable "Remote notifications" as a Background Mode in your app's Capabilities:
Then, add "content-available":1 in your aps object:
Users can disable background refresh for your application, or the system might not deliver it in some cases (like battery saving mode).You shouldn't rely on this to work at all times: always fetch data that you can fetch in a more reliable way when your app starts.
Batch supports background notifications, which allow you to run actions for a limited amount of time without notifying the user.
Please keep in mind that the same restrictions apply as the ones described higher up for Background Refresh.
When calling our Campaign/Transactional APIs, add 'push_type': 'background' to the request's JSON body, and remove the message/messages/media keys.
Silent notifications are not supported from the dashboard yet. Using the legacy way to do silent notifications using only the custom payload will NOT work on iOS 13 and later.
As said earlier for background refresh, we advise against triggering local notifications in response to a silent notification. While they are handy, the delivery rate will suffer heavily due to the unreliableness of background refresh.
Since Batch 2.0 the SDK always display notification while the App is in foreground. You can change this behaviour as following:
If you registered BatchUNUserNotificationCenterDelegate as your delegate, use the showForegroundNotifications property.
You can also do so with your own UNUserNotificationCenterDelegate:
Create a class that implements UNUserNotificationCenterDelegate
Override userNotificationCenter(center:willPresentNotification:withCompletionHandler) with willShowSystemForegroundAlert to false and call completionHandler([]).
Call Batch's appropriate methods so you don't break any features
iOS allows your app to show a button to configure notifications when the user long presses a notification.
You can enable this by calling this API:
Note that this still requires you to implement a UNUserNotificationCenterDelegate, and the appropriate method to open the settings.
Set it as the default UNUserNotificationCenter's delegate
{"aps":{"badge":2}}{"aps":{"category":"CATEGORY_NAME"}}{"aps":{"sound":"mysound.caf"}}{"aps":{"content-available":1}}// If you did not use BatchUNUserNotificationCenterDelegateregisterAsDelegate() but instanciated your own instance, use it instead of `sharedInstance`.
BatchUNUserNotificationCenterDelegate.sharedInstance.showForegroundNotifications = false// If you did not use [BatchUNUserNotificationCenterDelegate registerAsDelegate] but instanciated your own instance, use it instead of `sharedInstance`.
[BatchUNUserNotificationCenterDelegate sharedInstance].showForegroundNotifications = false; [BatchPush setSupportsAppNotificationSettings:true]
URLs present in notifications and mobile landings/in-app messages are handled by the Batch SDK in the following ways:
the default implementation by the SDK will automatically call -[UIApplication openURL:] with any URL it encounters
alternatively you can use a BatchDeeplinkDelegate to handle the URL your way
let delegate: BatchDeeplinkDelegate
// deeplinkDelegate is a class property of the Batch class
BatchSDK.deeplinkDelegate = delegate
// Then make your delegate implement the only function from the BatchDeeplinkDelegate protocol
func openBatchDeeplink(_ deeplink: String)id<BatchDeeplinkDelegate> delegate;
// deeplinkDelegate is a class property of the Batch class
BatchSDK.deeplinkDelegate = delegate;
// Then make your delegate implement the only method from the BatchDeeplinkDelegate protocol
- (void)openBatchDeeplink:(nonnull NSString*)deeplink;The SDK references your delegate weakly so make sure you hold a strong reference to it. A good idea could be to use your application delegate as the deeplink delegate.
Universal links let you connect to content deep inside your app using standard HTTP or HTTPS links (see documentation on the ).
As Universal links cannot be opened from within an app that supports them using UIApplication.openURL, some extra configuration is needed.
1.18.0 Once you have configured your app to handle universal links, you will need to declare your associated domains to the Batch SDK like in your Associated Domains Entitlement file.
For older SDK versions, you will have to use a BatchDeeplinkDelegate to handle these URLs manually.
Custom URL schemes, like customScheme://first-page, provide a way to reference resources inside your app (see documentation on the ).
This type of URL is properly handled without a deeplink delegate. However, if you find yourself using a deeplink delegate, you will need to pass your custom-scheme URL manually to -[UIApplication openURL:]. This is a necessary step, considering setting a deeplink delegate overrides the default implementation of the SDK.
class AppDelegate: UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchSDK.associatedDomains = ["example.com", "www.example.com"]
// ...
}
}@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[BatchSDK setAssociatedDomains:@[@"example.com", @"www.example.com"]];
// ...
}Step 1
First, download the SDK and Include Batch.xcframework in your project by dragging and dropping it into the Project Navigator as shown here:
Unless you manually copied the XCframework folder into your project's directory, check Copy items if needed. Make sure the only checked target is your Application target: extensions should be unchecked.
Step 2
Be sure Batch.xcframework and libsqlite3.tbd are in the Build Phases of your application target:
Step 3
In order to avoid a link issue when building your application, add -ObjC -lz to Other Linker Flags, under Build Settings of your application target.
Batch servers need to have a certificate in order to communicate with Apple Push Notification Services (APNS). This certificate is generated for an unique Application Identifier (App ID).
Step 1.
Open your Keychain application on your Mac. In the menu bar, select "Keychain Access" → "Certificate Assistant" → "Request a Certificate From a Certificate Authority…"
Then, enter your information in the required fields and select "Saved to disk". Save the "CertificateSigningRequest.certSigningRequest" file to your Desktop.
Step 2.
Head to the , open the Identifiers section and create a new App ID (or choose an existing Explicit App ID) to configure Push Notifications.
Scroll down to the Push Notifications section, check it if needed and click configure.
Under "Production SSL Certificate", click on "Create Certificate...". The Production certificate can push both sandbox and production environments.
The next screen will ask us to upload the Certificate Signing Request (CSR), which we have created earlier.
Select "Choose File…" and locate the .certSigningRequest file on your desktop. Finally, select "Continue" and download the generated SSL certificate.
Now you have the certificate, you need to have it with its key bundled into a .p12 file format.
Step 1.
First, add the certificate to your Keychain by double clicking on the downloaded SSL certificate.
In Keychain Access, pick the default keychain (login on English systems) using the sidebar. Then, click on "My Certificates" and find the certificate you just added. It should be called "Apple Push Services:".
Step 2.
Make sure that the certificate is collapsed (the arrow on the left ( > ) should point to the right). Right-click on the certificate, select "Export Apple Push Services:…", and save it as a .p12 file.
You will be prompted to enter a password which will be used to protect the exported certificate.
Step 3.
Now go to Batch's dashboard → ⚙ Settings → Channel -> iOS, and upload your P12 certificate.
After creating a new App ID or modifying your existing one, you need to (re)generate your provisioning profile and build with it.
Step 1.
Go to Apple Developer website, then click on "Provisioning Profiles" from the iOS Apps section.
Click on the "+" button to create a new iOS Provisioning Profile or select an existing one.
Step 2.
In the Provisioning Profile creation wizard:
Select Type: Choose "App Store".
Configure: Choose the App ID you created before from the drop down and make sure to select your iOS Production certificate.
Generate: Choose a name for this provisioning profile, such as "Batch Push App Profile" and select "Generate"
Step 3.
Install the profile by double-clicking on the downloaded file.
Your new provisioning profile should appear in the Provisioning Profiles section in your Xcode settings under the "Accounts" section. Make sure that your developer certificate is installed in your Keychain.
If Batch tells you that it was unable to automatically integrate with your application delegate, it's probably because there is a conflict with another SDK.
Try calling [BatchSDK startWithAPIKey:] earlier in your application delegate.
Batch 1.16 comes with a number of changes regarding the distribution of the SDK and it's extension counterpart.
This migration guide will help you update your implementation.
Batch 1.16 requires iOS 10.0 or higher. If your app targets an older version of iOS, please downgrade to 1.15.
With the 1.16 release, BatchExtension has been rewritten and open-source in two repositories:
(Swift version, recommended)
(Objective-C version, should only be used if you cannot use the Swift one)
This marks the end of the binary distribution of BatchExtension, which used to be bundled with the SDK downloads. The only way to integrate BatchExtension in your application from now on is using the source. Fortunately, package managers make this easy to deal with!
Migrating to the new BatchExtension is done in three steps:
Remove the old BatchExtension framework
Add the new one using a package manager
Update your code to match the new API signatures, if needed.
Since BatchExtension has never been distributed on a package manager, you had to copy it in your project and add a script phase.
In order to remove the framework, simply find it in the Project Navigator (which is the first tab of the left sidebar), and delete it:
When asked what to do with the deletion, pick Move To Trash.
Xcode should have automatically removed the framework reference from the Link Binary With Libraries and Embed Frameworks build steps.
Now, go in your main target's Build Steps and find the Run Script phase that refences a script which path contains BatchExtension.framework/strip-frameworks.sh. Be careful, as you might have multiple script phases.
Delete it.
BatchExtension has now been fully removed from your project. Now, we have to add it back!
Note: If your extension code is written in Objective-C and uses BAENotificationServiceExtension, please use the Objective-C version of the extension.
The extension is available on Swift Package Manager, CocoaPods and Carthage.
Please which will walk you through integrating the extension, and come back here once done.
If the extension builds without issues, you do not have anything to do!
If it doesn't, what you have to do depends on how you integrated the extension and which language you use:
You're using Swift code
BatchExtension 3.0.0 introduces the following source breaking changes for Swift users:
Classes have been unprefixed (except BAENotificationServiceExtension). For example, if your Swift code references BAERichNotificationHelper, you need to change it to RichNotificationHelper.
RichNotificationHelper.appendRichData(to: completionHandler:) has been renamed. It is now RichNotificationHelper.appendRichData(toContent: completionHandler:). Xcode offers a quickfix for this.
You're using Objective-C code
While the public API doesn't change, you might run into the following message: Cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute.
This happens if you used the standard version of the extension using Swift PM.
To fix this, use the Objective-C version of the extension as described in the , or rewrite the extension code in Swift (do not forget to update the extension's Info.plist with the new class name).
If you run into any other issue, please contact our support team to get help on your migration.
Batch 1.16 is now distributed as a static XCFramework instead of a legacy fat static framework. While the legacy framework format is still distributed, we encourage you to switch to the XCFramework build as soon as possible.
Batch 1.16.0 and higher are distributed as a XCFramework in CocoaPods. CocoaPods should handle the transition without needing any action on your end.
If you're running into issues, make sure you've updated to the latest CocoaPods version for XCFrameworks support.
As of writing, Carthage (ver 0.36.0) does not support XCFrameworks. Therefore, Batch is still distributed as a fat framework for Carthage.
iOS Simulator for Apple Silicon and Mac Catalyst support are not available with carthage.
We've heard loud and clear that developers would like to use Swift Package Manager to add Batch in their app. Unfortunately due to bugs in Xcode 12's handling of binary frameworks in SPM packages, Batch isn't distributed there yet. We will reevaluate this decision when a new version of Xcode that fixes the issues is released.
.
Replacing your manual Batch integration with the XCFramework distribution is quite easy.
First, delete Batch.embeddedframework (or Batch.framework) in the Project Navigator. Xcode should remove all of the Framework's reference in the build steps. Pick Move To Trash when asked.
Then, drag & drop Batch.xcframework in the Project Navigator where the framework you deleted was.
Unless you manually copied the XCframework folder into your project's directory, check Copy items if needed. Make sure the only checked target is your Application target: extensions should be unchecked.
Xcode should have added Batch.xcframework in the Link Binary With Libraries build step. Add it manually if this did not happen.
Your project should now build!


















Batch SDK v2 is a major release, which introduces breaking changes from 1.x. This guide describes how to update your application when using a previous version.
⚠️ Batch SDK 2.0 now requires Xcode 15.3 and iOS 13.0 or higher.
To upgrade from v1 to v2, you need to change the SDK version according to your package manager:
Update by using the "update package" option from Xcode or updating your package.swift.
.package(url: "https://github.com/BatchLabs/Batch-iOS-SDK", from: "2.0.0")Update your Podfile as following and run pod update.
Update your Cartfile if necessary and run carthage update Batch.
Batch is now distributed as a dynamic framework. This mean you can now safely link Batch between multiple framework targets!
Since Batch is now a , the additional metadata induced by this feature makes the XCFramework distribution heavier, but has no effect in the final size of Batch in your app once compiled.
This version introduced the visionOS support but some features are still unsupported like:
In-App messaging and mobile landings are unavailable.
In-App rating is not supported on visionOS due to an OS limitation.
This version introduced an important change since the default Batch module has been renamed into BatchSDK. This mean you have to replace all your calls to this module like when starting the SDK.
The iOS Batch SDK 1.21 had removed automatic collection of IDFA (Identifier For Advertisers). This version has totally dropped the support of the IDFA and you can no longer set an advertising id to Batch since all related APIs have been removed.
The Batch SDK v1 allowed you to disable advanced information generally with setUseAdvancedDeviceInformation(false). This has been removed and replaced with a more fine-tuning control of what you want to enable with:
For more information, please visit our .
All deprecated APIs in the SDK v1 have been removed. Some other APIs have been renamed/reworked to feel Swift native. To see in details the differences, please visit our .
This version follows Batch's pivot to being an omnichannel platform. It allows you to collect data for your Projects and Profiles. If you are not familiar with these two concepts, please see beforehand.
First of all, most of the user-related write APIs have been removed. Reading methods are still usable since we do not provide yet a way to get synced data for a Profile, but keep in mind that the data returned is only about your installation and not your Profile.
To interacts with our user-centered model, you should now use the BatchProfile module. Let's see a migration example.
If you were previously doing something like that:
You should now do:
For more information, please see the following sections :
To make it easier to collect data to a Profile, Batch has added two automatic ways to migrate old installation's data on a Profile. So the first time a user will launch your application running on v2 :
He will be automatically identified (logged-in) if he had a Batch custom_user_id set on the local storage.
Its natives (language/region) and customs data will be automatically migrate to a Profile if your app is attached to a Project.
These migrations are enabled by default, but you may want to disable them, to do so add the following before starting the SDK:
For more information, please visit our
Android Batch SDK v2 introduced two new types of attribute that can be attached to an event : Array and Object.
What's change:
BatchEventData has be renamed into BatchEventAttributes.
addTag API is no longer available and has been replaced by putStringArray with the $tags reserved key.
Optional withLabel
Note: Limits are unchanged and still 200 chars max for $label and 10 items max for $tags .
So if you were previously doing something like:
You should now do:
For more information, please visit our .
To see in details what's precisely changed since v1 please consult our or visit the .
In order to make your SDK integration as easy as possible, Batch Push automatically integrates into your application delegate by using a technique called "method swizzling".
Even though we've taken the greatest care when writing our swizzling code, you may encounter some cases where you don't want that, such as:
Incompatibility with other SDKs that also try to integrate themselves
Incompatibility with third party app development solutions
Swizzling breaks your delegate's architecture
You don't want code swizzled on your behalf
That's why, starting with Batch 1.5.3, we support a fully manual integration of the SDK.
To disable automatic integration, simply call:
This must be done before [BatchSDK startWithAPIKey:].
Then, you'll have to put calls to BatchPush where needed, in order to ensure that all Batch Push functionality works. Not implementing any of them will cause issues.
Here's a sample app delegate:
If using Batch 1.15 or lower on an application that supports iOS 8 and 9, you need to implement some extra methods:
On iOS 10 and higher, you should also implement UNUserNotificationCenterDelegate. How to correctly integrate it with Batch does not change in manual mode, and is detailed in .
iOS 8 introduced actionnable notifications: action buttons can be attached to notifications. Batch includes support for them: this documentation describes how to make the best of Batch's features and how to integrate them with iOS' native features, including how to work with the new iOS 10 APIs without breaking backwards compatibility.
This guide has no intention of being a full replacement of .
In order to be able to use action buttons in your notifications, you will have to register them to the framework in the application itself.
To do so, you'll create Actions
$labelBatchEventAttributespod 'Batch', '~> 2.0'github "BatchLabs/Batch-iOS-SDK" ~> 2.0BatchPush.disableAutomaticIntegration()[BatchPush disableAutomaticIntegration];func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchPush.disableAutomaticIntegration()
BatchSDK.start(withAPIKey: "YOUR API KEY")
// You MUST have a UNUserNotificationCenterDelegate implementation.
// Batch provides BatchUNUserNotificationCenterDelegate as a default one: if you have your own, integrate Batch into it.
// See "Intercepting notifications" for more info.
// Available from Batch 1.16
BatchUNUserNotificationCenterDelegate.registerAsDelegate()
// Ask for the permission to display notifications
// The push token will automatically be fetched by the SDK
BatchPush.requestNotificationAuthorization()
// Alternatively, you can call requestNotificationAuthorization later
// But, you should always refresh your token on each application start
// This will make sure that even if your user's token changes, you still get notifications
// BatchPush.refreshToken();
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
BatchPush.handleDeviceToken(deviceToken)
}Actions are defined by:
An identifier. Your app will be called back with this identifier once the user tapped on the action so you can perform the action.
A label. It is the text that the user will see.
Optional behavior options such as:
Destructive (the button will appear red)
Touch ID/Passcode requirement
Foreground/Background action (whether tapping the button will open your app or perform the action in the background)
...
Once you've declared your actions and put them into categories, you can register them to Batch:
You can also use the native UIKit APIs to register them, as per Apple's documentation.
iOS 10 (UserNotifications)
If you're using the UserNotifications framework, iOS will call you back in your UNUserNotificationCenterDelegate instance you've set as the UNUserNotificationCenter delegate.
For that, you'll need to implement userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
You'll also need to make sure you don't accidentally try to run your own code for actions that are not linked to action buttons:
Earlier iOS versions
As most legacy notifications callbacks, iOS will call you back on your app delegate.
You'll need to implement application:handleActionWithIdentifier:forRemoteNotification:withResponseInfo:completionHandler:.
A great way to clean up your code is to use Custom Actions and link them to your action buttons. It allows you to share code between the legacy and new callbacks, but also make your actions available to Mobile Landings and any future feature that will support calling actions you've defined remotely.
Once you've created your Custom Actions, make sure you register your UNNotificationAction instances with the same identifier as the ones you've picked for your Batch Custom Actions.
Then, you can trigger them manually from the callbacks:
Starting with iOS 10, Apple has deprecated UIUserNotificationAction and related classes in favor of UNNotificationAction. Applications compatible with iOS version lower than iOS 10 will have to deal with compatibility.
There are three ways of dealing with this:
The way is the recommended one. You can use Objective-C/Swift feature detection and register accordingly:
Note: A full example of this implementation can be found in our BatchCasts iOS Sample
If you're using Batch to register for notifications rather than UIKit methods, switching to the new UserNotifications framework has already been done for you.
Calling BatchPush.registerForRemoteNotifications(<Categories set>) with legacy (UI*UserNotification) actions and categories will cause Batch to convert them to UNNotificationAction and UNNotificationCategory instances and use the new APIs transparently.
If you define categories with both Default and Minimal contexts for your action sets, Batch will complain in the logs, as this doesn't exist anymore with the new APIs. A long term fix is to migrate to the right API according to the iOS version you're running on, as described earlier.
Registering notifications this way is supported by iOS, but should not be used: You should use the UserNotifications framework on iOS 10, since the old APIs have been deprecated.
You'll also have better callback support for anything related to notifications in your app.
You can now add actions to your iOS notifications by adding a category key to the payload of your push. Here is how it looks:

BatchSDK.start(withAPIKey: "YOUR_API_KEY")[BatchSDK startWithAPIKey:@"MY_API_KEY"];BatchSDK.updateAutomaticDataCollection { config in
config.setGeoIPEnabled(true) // Enable GeoIP resolution on server side
config.setDeviceModelEnabled(true) // Enable automatic collection of the device model information
}[BatchSDK updateAutomaticDataCollection:^(BatchDataCollectionConfig * _Nonnull config) {
[config setGeoIPEnabled:true]; // Enable GeoIP resolution on server side
[config setDeviceModelEnabled:true]; // Enable automatic collection of the device model information
}];let editor = BatchUser.editor()
editor.setIdentifier("john.doe")
editor.setLanguage("en")
editor.setRegion("US")
try? editor.setEmail("john.doe@batch.com")
editor.setEmailMarketingSubscriptionState(BatchEmailSubscriptionState.subscribed)
editor.setAttribute(26, forKey:"age")
editor.removeAttribute(key:"firstname")
editor.addTag("has_bought", inCollection: "actions")
editor.removeTag("has_bought", fromCollection: "actions")
editor.clearTagCollection("actions")
editor.save()
BatchUserDataEditor *editor = [BatchUser editor];
[editor setIdentifier:@"john.doe"];
[editor setLanguage:@"en"];
[editor setRegion:@"US"];
[editor setEmail:@"john.doe@batch.com" error:nil];
[editor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed];
[editor setIntegerAttribute:@26 forKey:@"age" error:nil];
[editor removeAttributeForKey:@"firstname"];
[editor addTag:@"has_bought" inCollection:@"actions"];
[editor removeTag:@"has_bought" fromCollection:@"actions"];
[editor clearTagCollection:@"actions"];
[editor save];BatchProfile.identify("john.doe")
BatchProfile.editor { editor in
try? editor.setLanguage("en")
try? editor.setRegion("US")
try? editor.setEmailAddress("john.doe@batch.com")
editor.setEmailMarketingSubscriptionState(BatchEmailSubscriptionState.subscribed)
try? editor.set(attribute: 26, forKey: "age")
try? editor.removeAttribute(key:"firstname")
try? editor.addToStringArray(item: "has_bought", forKey: "actions")
try? editor.removeFromStringArray(item: "has_bought", forKey: "actions")
try? editor.removeAttribute(key:"actions")
// Don't forget to use `editor.save()` if you use the editor in a local variable and not a closure like here.
}[BatchProfile identify:@"john.doe"];
[BatchProfile editWithBlock:^(BatchProfileEditor * _Nonnull editor) {
[editor setLanguage:@"en" error:nil];
[editor setRegion:@"US" error:nil];
[editor setEmailAddress:@"john.doe@batch.com" error:nil];
[editor setEmailMarketingSubscriptionState:BatchEmailSubscriptionStateSubscribed];
[editor setIntegerAttribute:26 forKey:@"age" error:nil];
[editor removeAttributeForKey:@"firstname" error:nil];
[editor addItemToStringArrayAttribute:@"has_bought" forKey:@"has_bought" error:nil];
[editor removeItemFromStringArrayAttribute:@"has_bought" forKey:@"has_bought" error:nil];
[editor removeAttributeForKey:@"actions" error:nil];
// Don't forget to use `[editor save]' if you use the editor in a local variable and not a closure like here.
}];import Batch
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Disable profile's migration
BatchSDK.setDisabledMigrations([
// Whether Batch should automatically identify logged-in user when running the SDK for the first time.
// This mean user with a custom_user_id will be automatically attached a to a Profile and could be targeted within a Project scope.
.customID,
// Whether Batch should automatically attach current installation's data (language/region/customDataAttributes...)
// to the User's Profile when running the SDK for the first time.
.customData
])
// Then start Batch SDK.
BatchSDK.start(withAPIKey: "YOUR_API_KEY")
}@import Batch;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Disable profile's migration
[BatchSDK setDisabledMigrations:
// Whether Batch should automatically identify logged-in user when running the SDK for the first time.
// This mean user with a custom_user_id will be automatically attached a to a Profile and could be targeted within a Project scope.
BatchMigrationCustomID |
// Whether Batch should automatically attach current installation's data (language/region/customDataAttributes...)
// to the User's Profile when running the SDK for the first time.
BatchMigrationCustomData
];
// Then start Batch SDK.
[BatchSDK startWithAPIKey:@"MY_API_KEY"];
return YES;
}let data = BatchEventData()
data.add(tag: "squash")
data.add(tag: "daily_digest")
data.put(true, forKey: "premium")
data.put("123456", forKey: "id")
BatchUser.trackEvent("read_article", withLabel: "sports", data: data)BatchEventData *data = [BatchEventData new];
[data addTag:@"squash"];
[data addTag:@"daily_digest"];
[data putBool:@(YES) forKey:@"premium"];
[data putString:@"123456" forKey:@"id"];
[BatchUser trackEvent:@"read_article" withLabel:@"sports" associatedData:data];let attributes = BatchEventAttributes { data in
data.put("sports", forKey: "$label")
data.put(["squash", "daily_digest"], forKey: "$tags")
data.put("123456", forKey: "id")
data.put(true, forKey: "premium")
}
BatchProfile.trackEvent(name: "read_article", attributes: attributes)BatchEventAttributes *attributes = [BatchEventAttributes new];
[attributes putString:@"sports" forKey:@"$label"];
[attributes putStringArray:@[@"squash", @"daily_digest"] forKey:@"$tags"];
[attributes putString:@"123456" forKey:@"id"];
[attributes putBool:YES forKey:@"premium"];
[BatchProfile trackEventWithName:@"read_article" attributes:attributes];- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[BatchPush disableAutomaticIntegration];
[BatchSDK startWithAPIKey:@"KEY"];
// You MUST have a UNUserNotificationCenterDelegate implementation.
// Batch provides BatchUNUserNotificationCenterDelegate as a default one: if you have your own, integrate Batch into it.
// See "Intercepting notifications" for more info.
// Available from Batch 1.16
[BatchUNUserNotificationCenterDelegate registerAsDelegate];
// Ask for the permission to display notifications
// The push token will automatically be fetched by the SDK
[BatchPush requestNotificationAuthorization];
// Alternatively, you can call requestNotificationAuthorization later
// But, you should always refresh your token on each application start
// This will make sure that even if your user's token changes, you still get notifications
// [BatchPush refreshToken];
return YES;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[BatchPush handleDeviceToken:deviceToken];
}func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
BatchPush.handleRegister(notificationSettings)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
BatchPush.handleNotification(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
BatchPush.handleNotification(userInfo)
completionHandler(.newData) // Adjust the result accordingly
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[BatchPush handleRegisterUserNotificationSettings:notificationSettings];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[BatchPush handleNotification:userInfo];
}
// Alternatively, implement this one:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[BatchPush handleNotification:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
}BatchPush.setNotificationsCategories(<your categories Set>)
BatchPush.registerForRemoteNotifications()[BatchPush setNotificationsCategories:<your categories NSSet>];
[BatchPush registerForRemoteNotifications];import UserNotifications
import Batch
@available(iOS 10.0, *)
@objc
class NotificationCenterDelegate: NSObject, UNUserNotificationCenterDelegate {
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
if response.actionIdentifier != UNNotificationDefaultActionIdentifier &&
response.actionIdentifier != UNNotificationDismissActionIdentifier {
// Perform your action here
}
BatchPush.handle(userNotificationCenter: center, didReceive: response)
completionHandler()
}
}@import UserNotifications;
@import Batch;
@interface NotificationCenterDelegateObjc : NSObject <UNUserNotificationCenterDelegate>
@end
@implementation NotificationCenterDelegateObjc
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
if (![UNNotificationDefaultActionIdentifier isEqualToString:response.actionIdentifier] &&
![UNNotificationDismissActionIdentifier isEqualToString:response.actionIdentifier]) {
// Handle your action here
}
[BatchPush handleUserNotificationCenter:center didReceiveNotificationResponse:response];
completionHandler();
}
@endfunc application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
// Handle the action here
completionHandler()
}- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler
{
// Handle your action here
completionHandler();
}// iOS 8/9
// In your application delegate
func application(_ application: UIApplication,
handleActionWithIdentifier identifier: String?,
forRemoteNotification userInfo: [AnyHashable : Any],
completionHandler: @escaping () -> Void) {
if let identifier = identifier {
var args: [String : AnyObject] = [:]
if let payloadArgs = userInfo["action_args"] as? [String : AnyObject] {
args = payloadArgs
}
BatchActions.perform(actionIdentifier: identifier, arguments: args)
}
completionHandler()
}
// iOS 10
import UserNotifications
import Batch
@available(iOS 10.0, *)
@objc
class NotificationCenterDelegate: NSObject, UNUserNotificationCenterDelegate {
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
if response.actionIdentifier != UNNotificationDefaultActionIdentifier &&
response.actionIdentifier != UNNotificationDismissActionIdentifier {
// If you want to add arguments to your action, this sample code will read from the "action_args" key of your custom payload
var args: [String : AnyObject] = [:]
if let payloadArgs = response.notification.request.content.userInfo["action_args"] as? [String : AnyObject] {
args = payloadArgs
}
BatchActions.perform(actionIdentifier: response.actionIdentifier, arguments: args)
}
BatchPush.handle(userNotificationCenter: center, didReceive: response)
completionHandler()
}
}// iOS 8/9
// In your application delegate
- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)userInfo
completionHandler:(void (^)())completionHandler
{
if (identifier) {
// If you want to add arguments to your action, this sample code will read from the "action_args" key of your custom payload
NSDictionary *args = @{};
NSObject *payloadArgs = userInfo[@"action_args"];
if ([payloadArgs isKindOfClass:[NSDictionary class]]) {
args = (NSDictionary*)payloadArgs;
}
[BatchActions performActionIdentifiedBy:identifier withArguments:args];
}
completionHandler();
}
// iOS 10
@import UserNotifications;
@import Batch;
@interface NotificationCenterDelegateObjc : NSObject <UNUserNotificationCenterDelegate>
@end
@implementation NotificationCenterDelegateObjc
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
if (![UNNotificationDefaultActionIdentifier isEqualToString:response.actionIdentifier] &&
![UNNotificationDismissActionIdentifier isEqualToString:response.actionIdentifier]) {
// If you want to add arguments to your action, this sample code will read from the "action_args" key of your custom payload
NSDictionary *args = @{};
NSObject *payloadArgs = response.notification.request.content.userInfo[@"action_args"];
if ([payloadArgs isKindOfClass:[NSDictionary class]]) {
args = (NSDictionary*)payloadArgs;
}
[BatchActions performActionIdentifiedBy:response.actionIdentifier withArguments:args];
}
[BatchPush handleUserNotificationCenter:center didReceiveNotificationResponse:response];
completionHandler();
}
@endif #available(iOS 10, *) {
// We're on iOS 10
registerActions()
} else {
// We're on iOS 8/9
registerLegacyActions()
}if ([UNNotificationAction class]) {
// We're on iOS 10
[self registerActions];
} else {
// We're on iOS 8/9
[self registerLegacyActions];
}{"aps":{"category":"CATEGORY_NAME"}}Batch Actions is a module allowing you to register remotely-configurable runnable code to the SDK, when simple deeplinks wouldn't be enough. They can be triggered at any time by the SDK, allowing you to focus on the action code rather than when to trigger it.
Batch comes with builtin actions (deeplinking, user data edition, etc...)
An action has two components:
An identifier (case-unsensitive string), which will allow you to reference this action
While the identifier string is up to you, it cannot start with "batch.": these identifiers are reserved for built-in actions.
An implementation block
Registering them is easy, and should be done every time your app starts, right before starting Batch:
BatchActions.register(BatchUserAction(identifier: "<YOUR_ACTION_NAME>",
actionBlock: { (identifier: String, arguments: [String : Any], source: BatchUserActionSource?) in
// Your action code here
BatchUserActionBlock alertActionBlock = ^(NSString * _Nonnull identifier, NSDictionary<NSString *,NSObject *> * _Nonnull arguments, id<BatchUserActionSource> _Nullable source) {
// Your action code here
};
[BatchActions registerAction
The source argument represents what caused the action to be triggered. You can use isKindOfClass (or a swift cast using as?) to check what source it comes from, and read what you need.
Two sources classes are currently used: BatchPushMessage and BatchManualUserActionSource. More will be added in the future.
Simply call the unregister method with the previously set identifier:
You might want to re-use the code you've already registered to Batch from your own code by triggering an action.
Simply give Batch the action identifier and arguments, and it will call your action:
Batch provide a set of pre-defined actions, allowing you to easily trigger a specific behavior without implementing them yourself.
Simply dismiss the notification and exit
Arguments
N/A
Open the provided deeplink (will call the Deeplink Interceptor if one is set).
Arguments (required)
l
String - Required
The deeplink to open
E.g.{"l":"https://google.com"}
li
Boolean - Optional - Default false
If true the Batch SDK will try to open your deeplink inside the app
E.g.{"li":false}
Show the notification permissions pop-up.
Arguments
N/A
Open the notifications settings of the current application.
Arguments
N/A
Checks if the user has already been asked for notifications, if not it shows the notification permissions pop-up, otherwise it opens the notifications settings of the current application.
Arguments
N/A
Add or remove a tag associated with the current user.
Arguments (required)
a
String - Required
The action to perform.
Acceptable values are add and remove
E.g.{"a":"remove"}
c
String - Required
The collection to use when updating the tag
E.g.{"c":"actions"}
t
String - Required
The tag to update
E.g.{"t":"has_bought"}
Send an event with associated tags and data.
Arguments (required)
e
String - Required
The name of the event to send
E.g.{"e":"my_awesome_event"}
l
String - Optional - default null
The label associated with the event
E.g.{"l":"label1"}
t
Array - Optional - default empty list
A list of tags to be send with the event
E.g.{"t":["tag1","tag2","tag3"]}
a
Object - Optional - default empty object
The data to send with the event
E.g.{"a":{"key":"value","key2":12,"key3":true}}
Execute a list of up to 10 nested actions successively.
Arguments (required)
actions
Array - Required
A list of actions to perform. This list must not be longer than 10 elements and can't contains batch.group actions
E.g.{"actions":[["batch.deeplink",{"l":"https://google.com"}],["batch.user.tag",{"add":"..."}]]}
On iOS 14, asks for Tracking consent using the AppTrackingTransparency framework. If the user has already been asked and refused to consent, opens the app's settings where tracking can be enabled. Does nothing on iOS 13 and earlier, or if tracking has been restricted by the device's manager. Your application needs to have a 'NSUserTrackingUsageDescription' key in its Info.plist or else iOS will crash it. Available since Batch 1.16.
Arguments
N/A
Copy a text to the device's clipboard.
Arguments (required)
t
String - Required
The text to copy
E.g.{"t":"My awesome text !"}
On iOS 10.3+, asks for the user to rate the app using SKStoreReviewController (this API's restrictions apply). Available since Batch 1.17.
Arguments
N/A
It is possible to get the raw payload of a notification (which includes your 'custom payload'), would you wish to do something with it. This is done using standard iOS APIs:
It's recommended to implement the UNUserNotificationCenterDelegate in a class.
It allows you to:
Unify local and remote notifications callbacks
BatchActions.unregister(actionIdentifier: "<YOUR_ACTION_NAME>")[BatchActions unregisterActionIdentifier:@"<YOUR_ACTION_NAME>"];BatchActions.perform(actionIdentifier: "alert", arguments: ["title": "Hello", "body": "How are you doing?"])[BatchActions performActionIdentifiedBy:@"alert" withArguments:@{@"title":@"Hello", @"body":@"How are you doing?"}];Get the same callback for all user interactions with a push (open, dismiss and actions), even for a cold start
Get notified of notifications received while your app is in the foreground. This allows you to take immediate action or to tell iOS to display the push as if your app was opened in background.
You'll also need to call Batch in its two methods to make sure all of the SDK and dashboard's features work correctly. Keep in mind that being a delegate, it will need to be retained by a variable, since iOS only weakly retains it.
Here's a sample implementation:
@objc
class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// NotificationDelegate.h
@import Foundation;
@import UserNotifications;
@interface NotificationDelegate : NSObject <UNUserNotificationCenterDelegate>
@end
// NotificationDelegate.m
#import "NotificationDelegate.h"
@import Batch;
Finally, set this class as your default UNUserNotificationCenter delegate:
Handling a custom payload
The custom payload is merged at the root of the userInfo you get when called back by iOS:
If your app supports background refresh, it's recommended to implement this method:
Don't forget to call the completionHandler with an appropriate value. Batch will only do so for you when it encounters a deeplink.
Otherwise, if you support iOS 6 devices or don't implement background refresh, please implement the older notification delegate method. Note that both can be implemented for backward-compatibility, you'll only be called on one of them.
Your custom payload will be in the userInfo dictionary.
Handling a custom payload
The custom payload is merged at the root of the userInfo you get when called back by iOS:
By default, Batch will automatically try to open the deeplink you've set in your push campaigns.
If you'd like to prevent Batch from doing that while still being able to use deeplinks in push campaigns, you can call the following method in applicationDidFinishLaunchingWithOptions:
Then, you can ask Batch to give you the deeplink from the notification when you get it:
Be careful, this method will return nil if a deeplink could not be found.
class AppDelegate: UIResponder, UIApplicationDelegate {
let notificationDelegate = NotificationDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10, *) {
UNUserNotificationCenter.current().delegate = notificationDelegate
}
}
}@interface AppDelegate ()
{
NotificationDelegate *notificationDelegate;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UNUserNotificationCenter class]) {
notificationDelegate = [NotificationDelegate new];
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:notificationDelegate];
}
}
@end// Works with both methods
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// When reading the custom payload, you should perform extensive type checking to prevent crashes if you
// ever change a type, be it intentionally or accidentally.
// Root keys will be of the type you used in your source JSON, unlike Android.
// Please see NSJSONSerialization for more info about how the JSON will be interpreted by iOS
// Here we'll read the "article_id" key of the following custom payload : {"article_id": 2}
if let articleID = userInfo["article_id"] as? Int {
// Handle your article ID
}
// If you have more complex objets, they also should be parsed correctly
// Matching custom payload: {"user_data": {"id": 2}}
if let userData = userInfo["user_data"] as? [AnyHashable : Any],
let userID = userData["id"] as? Int {
// Handle your user ID
}
}// Works with both methods
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
{
NSDictionary *userInfo = response.notification.request.content.userInfo
// When reading the custom payload, you should perform extensive type checking to prevent crashes if you
// ever change a type, be it intentionally or accidentally.
// Root keys will be of the type you used in your source JSON, unlike Android.
// Please see NSJSONSerialization for more info about how the JSON will be interpreted by iOS
// Here we'll read the "article_id" key of the following custom payload : {"article_id": 2}
NSNumber *articleID = userInfo[@"article_id"];
if ([articleID isKindOfClass:[NSNumber class]]) {
// Handle your article ID
}
// If you have more complex objets, they also should be parsed correctly
// Matching custom payload: {"user_data": {"id": 2}}
NSDictionary *userData = userInfo[@"user_data"];
if ([userData isKindOfClass:[NSDictionary class]]) {
NSNumber userID = userData[@"id"];
if ([userID isKindOfClass:[NSNumber class]]) {
// Handle your user ID
}
}
} func application(application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;func application(application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any])- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;// Works with both methods
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
// When reading the custom payload, you should perform extensive type checking to prevent crashes if you
// ever change a type, be it intentionally or accidentally.
// Root keys will be of the type you used in your source JSON, unlike Android.
// Please see NSJSONSerialization for more info about how the JSON will be interpreted by iOS
// Here we'll read the "article_id" key of the following custom payload : {"article_id": 2}
if let articleID = userInfo["article_id"] as? Int {
// Handle your article ID
}
// If you have more complex objets, they also should be parsed correctly
// Matching custom payload: {"user_data": {"id": 2}}
if let userData = userInfo["user_data"] as? [AnyHashable : Any],
let userID = userData["id"] as? Int {
// Handle your user ID
}
}// Works with both methods
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
// When reading the custom payload, you should perform extensive type checking to prevent crashes if you
// ever change a type, be it intentionally or accidentally.
// Root keys will be of the type you used in your source JSON, unlike Android.
// Please see NSJSONSerialization for more info about how the JSON will be interpreted by iOS
// Here we'll read the "article_id" key of the following custom payload : {"article_id": 2}
NSNumber *articleID = userInfo[@"article_id"];
if ([articleID isKindOfClass:[NSNumber class]]) {
// Handle your article ID
}
// If you have more complex objets, they also should be parsed correctly
// Matching custom payload: {"user_data": {"id": 2}}
NSDictionary *userData = userInfo[@"user_data"];
if ([userData isKindOfClass:[NSDictionary class]]) {
NSNumber userID = userData[@"id"];
if ([userID isKindOfClass:[NSNumber class]]) {
// Handle your user ID
}
}
}BatchPush.enableAutomaticDeeplinkHandling(false)[BatchPush enableAutomaticDeeplinkHandling:NO];func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
let deeplink = BatchPush.deeplink(fromUserInfo: userInfo)
}- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSString *deeplink = [BatchPush deeplinkFromUserInfo:userInfo];
}Batch SDK v3 is a major release, which introduces breaking changes from 2.x. This guide describes how to update your application when using a previous version.
If your application is still using Batch SDK v1 please follow our migration guide from V1 beforehand.
⚠️ Batch SDK 3.0 now requires Xcode 16.3 and iOS 15.0 or higher.
To upgrade from v2 to v3, you need to change the SDK version according to your package manager:
Update by using the "update package" option from Xcode or updating your package.swift.
Update your Podfile as following and run pod update.
Update your Cartfile if necessary and run carthage update Batch.
Batch SDK v3 adds compatibility for Mobile Landings with Push v2 which can be created from the Batch Dashboard's drag & drop composer.
The method batchInAppMessageReady has been removed from the BatchMessagingDelegate protocol. Please replace its usage with the new BatchInAppDelegate protocol.
Use the property access BatchMessaging.inAppDelegate to set your custom delegate.
So if you were doing:
You should now do:
For more information, please see the In-App messaging section.
The following methods in BatchMessagingDelegate have been removed:
batchMessageWasCancelledByAutoclose
batchMessageWasCancelledByUserAction
batchMessageWasCancelledByError
Please update your implementation to use the batchMessageDidDisappear:(NSString *_Nullable)messageIdentifier reason:(BatchMessagingCloseReason)reason; method. The new BatchMessagingCloseReason enum will provide the context about why the message was closed.
WebView actions will now trigger the updated batchMessageDidTriggerAction method, with the analyticsID of the action being passed as the ctaIdentifier.
The index (NSInteger) parameter in batchMessageDidTriggerAction has been replaced by ctaIdentifier (NSString). The method signature is now
For older MEP (Mobile Engagement Platform) messages, ctaIdentifier will be a string in the format "mepCtaIndex:" + index.
The constant BatchMessageGlobalActionIndex now returns a NSString instead of an NSInteger. Update any comparisons or usage accordingly.
So if you were doing:
You should now do:
For more information, please see the section.
To see in details what's precisely changed since V2 please consult our or visit the .
batchWebViewMessageDidTriggerAction.package(url: "https://github.com/BatchLabs/Batch-iOS-SDK", from: "3.0.1")pod 'Batch', '~> 3.0'github "BatchLabs/Batch-iOS-SDK" ~> 3.0// Application delegate
var inAppMsgDelegate = InAppMsgDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchMessaging.delegate = inAppMsgDelegate
}
// InAppMsgDelegate implementation
@objc
class InAppMsgDelegate: NSObject, BatchMessagingDelegate {
func batchInAppMessageReady(message: BatchInAppMessage) {
// Your implementation
}
}
// Application delegate
@property InAppMsgDelegate *inAppMsgDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.inAppMsgDelegate = [InAppMsgDelegate new];
BatchMessaging.delegate = self.inAppMsgDelegate;
}
// InAppMsgDelegate implementation
@interface InAppMsgDelegate : NSObject <BatchMessagingDelegate>
@end
@implementation InAppMsgDelegate
- (void)batchInAppMessageReady:(nonnull BatchInAppMessage*)message
{
// Your implementation
}
@end
// Application delegate
var inAppMsgDelegate = InAppMsgDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchMessaging.inAppDelegate = inAppMsgDelegate
}
// InAppMsgDelegate implementation
@objc
class InAppMsgDelegate: NSObject, BatchInAppDelegate {
func batchInAppMessageReady(message: BatchInAppMessage) {
// Your implementation
}
}
// Application delegate
@property InAppMsgDelegate *inAppMsgDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.inAppMsgDelegate = [InAppMsgDelegate new];
BatchMessaging.inAppDelegate = self.inAppMsgDelegate;
}
// InAppMsgDelegate implementation
@interface InAppMsgDelegate : NSObject <BatchInAppDelegate>
@end
@implementation InAppMsgDelegate
- (void)batchInAppMessageReady:(nonnull BatchInAppMessage*)message
{
// Your implementation
}
@end
batchMessageDidTriggerAction:(BatchMessageAction *_Nonnull)action
messageIdentifier:(NSString *_Nullable)identifier
ctaIdentifier:(NSString *_Nonnull)ctaIdentifier;// Application delegate
var messagingDelegate = MsgDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchMessaging.delegate = inAppMsgDelegate
}
// BatchMessagingDelegate implementation
class SampleBatchMessagingDelegate: NSObject, BatchMessagingDelegate {
public func batchMessageDidAppear(messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageDidAppear: \(messageIdentifier)")
}
public func batchMessageDidTriggerAction(_ action: BatchMessageAction, messageIdentifier identifier: String?, actionIndex index: Int) {
print("SampleBatchMessagingDelegate - batchMessageDidTriggerAction: \(messageIdentifier)")
}
public func batchWebViewMessageDidTriggerAction(_ action: BatchMessageAction?, messageIdentifier: String?, analyticsIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchWebViewMessageDidTriggerAction \(String(describing:action)), tracking ID: \(messageIdentifier ?? "<nil>"), analyticsIdentifier: \(analyticsIdentifier ?? "<nil>")")
}
public func batchMessageWasCancelledByAutoclose(_ messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: \(messageIdentifier)")
}
public func batchMessageWasCancelledByUserAction(_ messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: \(messageIdentifier)")
}
public func batchMessageWasCancelledByError(_ messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByError: \(messageIdentifier)")
}
public func batchMessageDidDisappear(messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageDidDisappear: \(messageIdentifier)")
}
}// AppDelegate.m
@property SampleBatchMessagingDelegate *messagingDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.messagingDelegate = [SampleBatchMessagingDelegate new];
BatchMessaging.delegate = self.messagingDelegate;
}
// Header file (.h)
@interface SampleBatchMessagingDelegate : NSObject <BatchMessagingDelegate>
@end
// Implementation file (.m)
@implementation SampleBatchMessagingDelegate
- (void)batchMessageDidAppear:(NSString* _Nullable)messageIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidAppear: %@", messageIdentifier);
}
- (void)batchMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier actionIndex:(NSInteger)index
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidTriggerAction: %@", messageIdentifier);
}
- (void)batchWebViewMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier analyticsIdentifier:(NSString *)analyticsIdentifierex
{
NSLog(@"SampleBatchMessagingDelegate - batchWebViewMessageDidTriggerAction: %@", messageIdentifier);
}
- (void)batchMessageWasCancelledByAutoclose:(NSString * _Nullable)messageIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchWebVbatchMessageWasCancelledByAutocloseiewMessageDidTriggerAction: %@", messageIdentifier);
}
- (void)batchMessageWasCancelledByUserAction:(NSString * _Nullable)messageIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: %@", messageIdentifier);
}
- (void)batchMessageDidDisappear:(NSString* _Nullable)messageIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidDisappear: %@", messageIdentifier);
}
@end// Application delegate
var messagingDelegate = MsgDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
BatchMessaging.delegate = messagingDelegate
}
// BatchMessagingDelegate implementation
class SampleBatchMessagingDelegate: NSObject, BatchMessagingDelegate {
public func batchMessageDidAppear(messageIdentifier: String?) {
print("SampleBatchMessagingDelegate - batchMessageDidAppear: \(messageIdentifier)")
}
public func batchMessageDidTriggerAction(_ action: BatchMessageAction, messageIdentifier identifier: String?, ctaIdentifier: String) {
print("SampleBatchMessagingDelegate - batchMessageDidTriggerAction: \(messageIdentifier)")
// For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
}
public func batchMessageDidDisappear(_ messageIdentifier: String?, reason: BatchMessagingCloseReason) {
switch(reason) {
case .action:
print("SampleBatchMessagingDelegate - batchMessageDidDisappear: \(messageIdentifier)")
case .auto:
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: \(messageIdentifier)")
case .user:
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: \(messageIdentifier)")
case .error:
print("SampleBatchMessagingDelegate - batchMessageWasCancelledByError: \(messageIdentifier)")
}
}
}// AppDelegate.m
@property SampleBatchMessagingDelegate *messagingDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.messagingDelegate = [SampleBatchMessagingDelegate new];
BatchMessaging.delegate = self.messagingDelegate;
}
// Header file (.h)
@interface SampleBatchMessagingDelegate : NSObject <BatchMessagingDelegate>
@end
// Implementation file (.m)
@implementation SampleBatchMessagingDelegate
- (void)batchMessageDidAppear:(NSString* _Nullable)messageIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidAppear: %@", messageIdentifier);
}
- (void)batchMessageDidTriggerAction:(BatchMessageAction * _Nonnull)action messageIdentifier:(NSString *)identifier ctaIdentifier:(NSString *_Nonnull)ctaIdentifier
{
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidTriggerAction: %@", messageIdentifier);
// For MEP messages, ctaIdentifier might be "mepCtaIndex:0", "mepCtaIndex:1", etc.
}
- (void)batchMessageDidDisappear:(NSString* _Nullable)messageIdentifier reason:(BatchMessagingCloseReason)reason
{
switch (reason) {
case BatchMessagingCloseReasonAction:
NSLog(@"SampleBatchMessagingDelegate - batchMessageDidDisappear: %@", messageIdentifier ?: @"<nil>");
break;
case BatchMessagingCloseReasonAuto:
NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByAutoclose: %@", messageIdentifier ?: @"<nil>");
break;
case BatchMessagingCloseReasonUser:
NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByUserAction: %@", messageIdentifier ?: @"<nil>");
break;
case BatchMessagingCloseReasonError:
NSLog(@"SampleBatchMessagingDelegate - batchMessageWasCancelledByError: %@", messageIdentifier ?: @"<nil>");
break;
}
}
@end