Skip to content

Commit aec38c1

Browse files
Merge pull request #50 from Iterable/feature/mob-177-ddl-doc
[MOB-177] - Add deferred deep linking documentation
2 parents 261a92d + 87e31f5 commit aec38c1

File tree

5 files changed

+67
-19
lines changed

5 files changed

+67
-19
lines changed

README.md

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,51 @@ func application(_ application: UIApplication, continue userActivity: NSUserActi
248248
return [IterableAPI handleUniversalLink:userActivity.webpageURL];
249249
}
250250
```
251+
252+
### Deferred deep linking
253+
254+
[Deferred deep linking](https://en.wikipedia.org/wiki/Deferred_deep_linking) allows a user who does not have a specific app installed to:
255+
256+
- Click on a deep link that would normally open content in that app.
257+
- Install the app from the App Store.
258+
- Open the app and immediately see the content referenced by the link.
259+
260+
As the name implies, the deep link is _deferred_ until the app has been installed.
261+
262+
After tapping a deep link in an email from an Iterable campaign, users without the associated app will be directed to the App Store to install it. If the app uses the IterableSDK and has deferred deep linking enabled, the content associated with the deep link will load on first launch.
263+
264+
#### Enabling deferred deep linking
265+
266+
Set `IterableConfig.checkForDeferredDeeplink = true` to enable deferred deep linking for IterableSDK.
251267
252-
#### In-app messages
268+
### In-app messages
269+
270+
If you are already using in-app messages with IterableSDK, please check out the [migration section](#Migrating-in-app-messages-from-the-previous-version-of-the-SDK).
271+
272+
In-app messages are handled via silent push messages from the server. When your application receives a silent push, you need to call IterableSDK in your AppDelegate as in the following code:
273+
274+
*Swift*
275+
276+
```swift
277+
// In AppDelegate.swift
278+
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
279+
IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
280+
}
281+
```
253282

254-
If you are already using in-app messages with IterableSDK, please check out the [migration section](#Migrating-in-app-messages-from-previous-version-of-SDK).
283+
*Objective-C*
284+
285+
```objc
286+
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
287+
[IterableAppIntegration application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
288+
}
289+
```
255290

256-
##### Default behavior
291+
#### Default behavior
257292

258293
By default, when an in-app message arrives from the server, the SDK automatically shows it if the app is in the foreground. If an in-app message is already showing when the new message arrives, the new in-app message will be shown 30 seconds after the currently displayed in-app message closes ([see how to change this default value below](#Changing-the-display-interval-between-in-app-messages)). Once an in-app message is shown, it will be "consumed" from the server queue and removed from the local queue as well. There is no need to write any code to get this default behavior.
259294

260-
##### Overriding whether to show or skip a particular in-app message
295+
#### Overriding whether to show or skip a particular in-app message
261296

262297
An incoming in-app message triggers a call to the `onNew` method of `IterableConfig.inAppDelegate` (an object of type `IterableInAppDelegate`). To override the default behavior, set `IterableConfig.inAppDelegate` to a custom class that overrides the `onNew` method. `onNew` should return `.show` to show the incoming in-app message or `.skip` to skip showing it.
263298

@@ -302,7 +337,7 @@ config.inAppDelegate = self; // or other class implementing the protocol
302337
[IterableAPI initializeWithApiKey:@"YOUR API KEY" launchOptions:launchOptions config:config];
303338
```
304339
305-
##### Getting the local queue of in-app messages
340+
#### Getting the local queue of in-app messages
306341
Until they are consumed by the app, all in-app messages that arrive from the server are stored in a local queue. To access that local queue, use the read-only `IterableAPI.inAppManager` property (which conforms to the `InAppManager` protocol). By default, all in-app messages in the local queue will be consumed and removed from this queue. To keep in-app messages around after they are shown, override the default behavior (as described above).
307342
308343
*Swift*
@@ -333,7 +368,7 @@ NSArray *messages = [IterableAPI.inAppManager getMessages];
333368

334369
```
335370
336-
##### When user clicks a button/link in the in-app message
371+
#### When user clicks a button/link in the in-app message
337372
338373
Button/link clicks from in-app are handled similar to deep links from notifications and emails. Please see those sections above. If the in-app message's clicked button/link's `href` contains a URL (which is usually the case), tapping that button/link will call the `handle` method of `IterableConfig.urlDelegate` (an object of type `IterableURLDelegate`), if one is set. By default if this delegate is not set, tapping the button/link will open Safari with the `href` of the clicked button/link.
339374
@@ -347,11 +382,11 @@ config.urlDelegate = YourCustomUrlDelegate()
347382
config.customActionDelegate = YourCustomActionDelegate()
348383
```
349384

350-
##### Changing the display interval between in-app messages
385+
#### Changing the display interval between in-app messages
351386

352387
To customize the time delay between successive in-app messages (default value of 30 seconds), set `IterableConfig.inAppDisplayInterval` to an appropriate value (in seconds).
353388

354-
##### Migrating in-app messages from the previous version of the SDK
389+
#### Migrating in-app messages from the previous version of the SDK
355390

356391
If you are already using in-app messages, then you will have to make the following changes to your code:
357392

@@ -360,21 +395,21 @@ If you are already using in-app messages, then you will have to make the followi
360395
3. Remove calls to 'IterableAPI.getInAppMessages()' and use `IterableAPI.inAppManager.getInAppMessages()` instead.
361396

362397

363-
#### Tracking custom events
398+
### Tracking custom events
364399

365400
Custom events can be tracked using `IterableAPI.track(event:...)` calls.
366401

367-
#### Updating user fields
402+
### Updating user fields
368403

369404
User fields can be modified using `IterableAPI.updateUser` call. You also have `updateEmail` and `updateSubscriptions` methods.
370405

371-
#### Disabling push notifications to a device
406+
### Disabling push notifications to a device
372407

373408
When a user logs out, you typically want to disable push notifications to that user/device. This can be accomplished by calling `disableDeviceForCurrentUser`. Please note that it will only attempt to disable the device if you have previously called `registerToken`.
374409

375410
In order to re-enable push notifcations to that device, simply call `registerToken` as usual when the user logs back in.
376411

377-
#### Uninstall tracking
412+
### Uninstall tracking
378413

379414
Iterable will track uninstalls with no additional work by you.
380415

sample-apps/objc-sample-app/objc-sample-app.xcodeproj/project.pbxproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@
270270
AC90809E20E308D1004BC146 /* Project object */ = {
271271
isa = PBXProject;
272272
attributes = {
273-
LastUpgradeCheck = 0940;
273+
LastUpgradeCheck = 1010;
274274
ORGANIZATIONNAME = Iterable;
275275
TargetAttributes = {
276276
AC9080A520E308D1004BC146 = {
@@ -554,6 +554,7 @@
554554
isa = XCBuildConfiguration;
555555
baseConfigurationReference = 75A967E379FC6270DFE2E36D /* Pods-objc-sample-app.debug.xcconfig */;
556556
buildSettings = {
557+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
557558
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
558559
CODE_SIGN_ENTITLEMENTS = "objc-sample-app/objc-sample-app.entitlements";
559560
CODE_SIGN_STYLE = Automatic;
@@ -573,6 +574,7 @@
573574
isa = XCBuildConfiguration;
574575
baseConfigurationReference = DDFF7C4DDD2898BE48245488 /* Pods-objc-sample-app.release.xcconfig */;
575576
buildSettings = {
577+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
576578
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
577579
CODE_SIGN_ENTITLEMENTS = "objc-sample-app/objc-sample-app.entitlements";
578580
CODE_SIGN_STYLE = Automatic;

sample-apps/objc-sample-app/objc-sample-app/AppDelegate.m

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,14 @@ - (void)applicationWillTerminate:(UIApplication *)application {
9191
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
9292
}
9393

94+
#pragma mark - Silent Push
95+
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
96+
[IterableAppIntegration application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
97+
}
98+
9499
#pragma mark - Url handling
95-
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
96-
100+
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
101+
97102
//ITBL:
98103
NSURL *url = userActivity.webpageURL;
99104
if (url == nil) {

sample-apps/objc-sample-app/objc-sample-app/Base.lproj/Main.storyboard

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hgQ-gs-Z8D">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hgQ-gs-Z8D">
33
<device id="retina4_7" orientation="portrait">
44
<adaptation id="fullscreen"/>
55
</device>
66
<dependencies>
77
<deployment identifier="iOS"/>
8-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
8+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
99
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
1010
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1111
</dependencies>
@@ -80,7 +80,7 @@
8080
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="f7k-qy-qxC">
8181
<rect key="frame" x="62.5" y="183" width="250" height="365.5"/>
8282
<subviews>
83-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="E6e-e6-ohw">
83+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="E6e-e6-ohw">
8484
<rect key="frame" x="0.0" y="0.0" width="250" height="20.5"/>
8585
<fontDescription key="fontDescription" type="system" weight="thin" pointSize="17"/>
8686
<nil key="textColor"/>
@@ -186,7 +186,7 @@
186186
<viewLayoutGuide key="safeArea" id="mdt-39-bbJ"/>
187187
</view>
188188
<navigationItem key="navigationItem" id="5BQ-Vo-KB0">
189-
<barButtonItem key="rightBarButtonItem" style="plain" systemItem="done" id="OQ7-S8-j6B">
189+
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="OQ7-S8-j6B">
190190
<connections>
191191
<action selector="doneButtonTapped:" destination="e0v-rS-htn" id="Wsh-gP-9al"/>
192192
</connections>

sample-apps/swift-sample-app/swift-sample-app/AppDelegate.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
8484
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
8585
}
8686

87+
// MARK: Silent Push for in-app
88+
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
89+
IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
90+
}
91+
92+
8793
// MARK: Deep link
8894
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
8995
guard let url = userActivity.webpageURL else {

0 commit comments

Comments
 (0)