Customizing iOS SDK
Integration
- Deep linking
- In-app purchase tracking
- Geozones push notifications
- Creating a Rich Media queue
- Autoplay a video sent in a Rich Notification with force touch
- Custom push sound
- iOS Provisional Push
Deep linking
In your Info.plist file add URL types
array with URL Identifier
and URL Scheme
.
In the example below the URL Scheme
is com.pushwoosh and the URL Identifier
is promotion.

In your App Delegate file (usually AppDelegate.m for iOS 12 and below, or SceneDelegate.m for iOS 13 and above), add the appropriate openURL delegate function as outlined in the example below. The example checks for the correct page, parses the “id” value from the URL, and opens PromoPageViewController in response.
AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let components = URLComponents(url: url, resolvingAgainstBaseURL: false) let page = components?.host var promotionId: String?
if page == "promotion" { return }
let items = components?.queryItems ?? []
for item in items { if item.name == "id" { promotionId = item.value } }
//show PromoPageViewController}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSString *page = components.host; NSString *promotionId = nil;
//return if this is not a promotion deep link if(![page isEqualToString:@"promotion"]) return NO;
for(NSURLQueryItem *item in components.queryItems) { if([item.name isEqualToString:@"id"]) promotionId = item.value; }
PromoPageViewController *vc = [[PromoPageViewController alloc] init]; vc.promotionId = promotionId [self presentViewController:vc animated:YES completion:nil];}
SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let urlContext = URLContexts.first else { return }
let components = URLComponents(url: urlContext.url, resolvingAgainstBaseURL: false) let page = components?.host var promotionId: String?
guard page == "promotion" else { return }
let items = components?.queryItems ?? []
for item in items { if item.name == "id" { promotionId = item.value } }
//show PromoPageViewController}
- (void)scene:(UIWindowScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts { UIOpenURLContext *urlContext = URLContexts.anyObject; if (!urlContext) { return; }
NSURLComponents *components = [NSURLComponents componentsWithURL:urlContext.URL resolvingAgainstBaseURL:NO]; NSString *page = components.host; NSString *promotionId = nil;
if (![page isEqualToString:@"promotion"]) { return; }
for (NSURLQueryItem *item in components.queryItems) { if ([item.name isEqualToString:@"id"]) { promotionId = item.value; } }
//show PromoPageViewController}
In-app purchase tracking
By default, tracking of in-app purchases is disabled. If you want to track in-app purchases when configuring Customer Journeys, set the Pushwoosh_PURCHASE_TRACKING_ENABLED flag to true in the info.plist file. You can find a list of available flags in the table.
If you want to track in-app purchases manually, you can use the code below.
In paymentQueue:updatedTransactions: delegate
method call sendSKPaymentTransactions method
of PushManager
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { // In-Apps Tracking Pushwoosh code here Pushwoosh.sharedInstance().sendSKPaymentTransactions(transactions) // the rest of the code, consume transactions, etc }
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
[[PushNotificationManager pushManager] sendSKPaymentTransactions:transactions];
//the rest of the code, consume transactions, etc}

Geozones push notifications
Geozones push notifications are encapsulated into a separate framework PushwooshGeozones.
- Add PushwooshGeozones.framework to your project
To add PushwooshGeozones.framework to your project using a dependency manager, put the following
lines in your podfile
or cartfile
:
pod 'PushwooshXCFramework/Geozones'
github "Pushwoosh/pushwoosh-ios-sdk"
If you want to use PushwooshGeozones.xcframework, enter the following Package URL:
PushwooshGeozones-XCFramework
Alternatively, you can simply drag and drop the framework into Link Binaries With Libraries in your project’s Build Phases.
- Add the following keys to your Info.plist:
- NSLocationWhenInUseUsageDescription – (required) for the app to track Geozones only while running in the foreground.
- NSLocationAlwaysAndWhenInUseUsageDescription – (required) for the app to track Geozones in both foreground and background and to show a permission request dialog pop-up.
- NSLocationAlwaysUsageDescription – (optional) for the app to track Geozones at all times; should be used if your app targets iOS 10 and earlier versions.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key><string>for app to track Geozones in both conditions and to show a permission request dialog</string><key>NSLocationWhenInUseUsageDescription</key><string>for app to track Geozones only while running in the foreground</string>
- Import the framework
import PushwooshGeozones
#import <PushwooshGeozones/PWGeozonesManager.h>
- Start Geozones tracking
PWGeozonesManager.shared()?.startLocationTracking()
[[PWGeozonesManager sharedManager] startLocationTracking];
Example
override func viewDidLoad() { super.viewDidLoad()
// Start Geozones tracking when needed PWGeozonesManager.shared().startLocationTracking()}
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view.
// Start Geozones tracking when needed [[PWGeozonesManager sharedManager] startLocationTracking];}
Creating a Rich Media queue
In case there are several Rich Media pages to display simultaneously (for example, trigger events for two or more In-Apps take place at one moment, or a Rich Media page is being displayed already at the moment a different trigger event occurs), you can set up a queue for Rich Media pages displaying. To create a queue, follow the steps described below.
- Create a class that implements PWRichMediaPresentingDelegate:
@interface ChainedRichMediaPresentingDelegate () <PWRichMediaPresentingDelegate>
@property (nonatomic) NSMutableArray *queue;
@property (nonatomic) BOOL inAppIsPresenting;
@end
@implementation ChainedRichMediaPresentingDelegate
- (instancetype)init { self = [super init];
if (self) { _queue = [NSMutableArray new]; }
return self;}
- (BOOL)richMediaManager:(PWRichMediaManager *)richMediaManager shouldPresentRichMedia:(PWRichMedia *)richMedia { [_queue addObject:richMedia]; return !_inAppIsPresenting;}
- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didPresentRichMedia:(PWRichMedia *)richMedia { _inAppIsPresenting = YES;}
- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didCloseRichMedia:(PWRichMedia *)richMedia { _inAppIsPresenting = NO;
[_queue removeObject:richMedia];
if (_queue.count) { [[PWRichMediaManager sharedManager] presentRichMedia:_queue.firstObject]; }}
- (void)richMediaManager:(PWRichMediaManager *)richMediaManager presentingDidFailForRichMedia:(PWRichMedia *)richMedia withError:(NSError *)error { [self richMediaManager:richMediaManager didCloseRichMedia:richMedia];}
@end
2. Set the delegate:
[PWRichMediaManager sharedManager].delegate = [ChainedRichMediaPresentingDelegate new];
Autoplay a video sent in a Rich Notification with force touch
To make a video sent as a Rich Notification attachment autoplay when the notification is expanded without any user interaction, follow the steps below:
- Add the Notification Content Extension to your project:
- In Xcode, select File > New > Target.
- Choose Notification Content Extension.
- Assign it a name and complete the setup.

If prompted with the “Activate scheme” message, choose Cancel.

- Adjust the properties and methods in the Content Extension as follows:
import UIKitimport UserNotificationsimport UserNotificationsUIimport AVKit
class NotificationViewController: UIViewController, UNNotificationContentExtension { var playerController: AVPlayerViewController! @IBOutlet weak var playerBackgroundView: UIView!
override func viewDidLoad() { super.viewDidLoad() // Do any required interface initialization here. }
func didReceive(_ notification: UNNotification) { let attachment = notification.request.content.attachments.first
playerController = AVPlayerViewController() // Set height programmatically // preferredContentSize.height = 250
if let url = attachment?.url { setupVideoPlayer(url: url) } else { print("No valid URL...") } }
private func setupVideoPlayer(url: URL) { guard let playerController = self.playerController else { return } let player = AVPlayer(url: url) playerController.player = player playerController.view.frame = self.playerBackgroundView.bounds playerBackgroundView.addSubview(playerController.view) addChild(playerController) playerController.didMove(toParent: self) player.play() }
- Incorporate a UIView into MainInterface.storyboard:

- Link the playerBackgroundView IBOutlet with the UIView you just added:

- Update the info.plist file with the following entry:
UNNotificationExtensionUserInteractionEnabled = true

In order to attach a video to your notification, input a video’s URL to the Media Attachment field in the Control Panel:

When sending a notification via API /createMessage request, include the URL in the “ios_attachment” parameter and ensure the “mutable-content” flag is set to `1`.

Custom push sound
To play a custom sound when on a push notification receiving, first put the audio file into your project’s root folder.

Then, specify the sound file’s name in push parameters – fill in the Sound field of the iOS-specific settings of your message or specify the file name as a value for the “ios_sound” param of the createMessage API request.
Audio file for custom iOS sound has to be in one of the following formats: .aif, .caf, .wav. Make sure to specify the format in the file’s name; otherwise, it will be ignored by Pushwoosh iOS SDK.
iOS Provisional Push
How it works
Provisional push notifications appear silently in the user’s Notification Center but not on the lock screen. This type of pushes doesn’t need to be allowed by a user explicitly: you can start sending them as soon as a user installs and launches your app.
However, users still can subscribe to your prominent push notifications: when opening the Provisional Push, they have two options to choose their experience – to keep pushes in Notification Center without alerts and sounds or allow you to send pushes prominently so that they appear on the lock screen.
Provisional Pushes are designed to let users make informed decisions about whether they’d like to receive notifications from your app. As the APN native subscription request is shown to users only once and to subscribe later, they should go to their phone’s system settings, and some users might not subscribe since they aren’t aware of what value they get with your pushes. Provisional Pushes give users this understanding: they can see what content you deliver in push notifications and decide whether they need to be notified about this content prominently.
How to implement
1. Integrate the Pushwoosh iOS SDK by following the guide.
2. Add the following string to your project’s AppDelegate before calling the registerForPushNotifications()
method:
if #available(iOS 12.0, *) { Pushwoosh.sharedInstance().additionalAuthorizationOptions = UNAuthorizationOptions.provisional}
if (@available(iOS 12.0, *)) { [Pushwoosh sharedInstance].additionalAuthorizationOptions = UNAuthorizationOptionProvisional;}
That’s it! App users will receive messages directly to their Notification Center once they install the app.
Share your feedback with us
Your feedback helps us create a better experience, so we would love to hear from you if you have any issues during the SDK integration process. If you face any difficulties, please do not hesitate to share your thoughts with us via this form.