iOS高级功能

创建内容引用

let buo = BranchUniversalObject.init(canonicalIdentifier: "content/12345")
buo.title = "My Content Title"
buo.contentDescription = "My Content Description"
buo.imageUrl = "https://lorempixel.com/400/400"
buo.publiclyIndex = true
buo.locallyIndex = true
buo.contentMetadata.customMetadata["key1"] = "value1"
BranchUniversalObject *buo = [[BranchUniversalObject alloc] initWithCanonicalIdentifier:@"content/12345"];
buo.title = @"My Content Title";
buo.contentDescription = @"My Content Description";
buo.imageUrl = @"https://lorempixel.com/400/400";
buo.publiclyIndex = YES;
buo.locallyIndex = YES;
buo.contentMetadata.customMetadata[@"key1"] = @"value1";

创建没有共享表的动态链接

如果您'构建了自己的共享表,并且只想为单个共享消息创建Branch链接或具有另一个用例,则可以通过以下调用直接创建深度链接接:

[branchUniversalObject getShortUrlWithLinkProperties:linkProperties andCallback:^(NSString *url, NSError *error) {
        if (!error) {
            NSLog(@"got my Branch invite link to share: %@", url);
        }
    }];
branchUniversalObject.getShortUrl(with: linkProperties) { (url, error) in
        if (error == nil) {
            print("Got my Branch link to share: (url)")
        } else {
            print(String(format: "Branch error : %@", error! as CVarArg))
        }
    }

您可以在上面找到linkProperties 示例。接下来,您将使用返回的链接,并帮助用户将其发布到Facebook(在此示例中)。

指定共享的电子邮件主题

大多数共享选项仅包含一串文本,但电子邮件除外,该电子邮件具有主题和正文。共享文本将填充在正文中,您可以在链接属性中指定电子邮件主题,如下所示。

BranchLinkProperties *linkProperties = [[BranchLinkProperties alloc] init];
    linkProperties.feature = @"share";
    linkProperties.channel = @"facebook";
    [linkProperties addControlParam:@"$email_subject" withValue:@"Your Awesome Deal"];
let linkProperties: BranchLinkProperties = BranchLinkProperties()
    linkProperties.feature = "share"
    linkProperties.channel = "facebook"
    linkProperties.addControlParam("$email_subject", withValue: "Your Awesome Deal")

创建链接引用

let lp: BranchLinkProperties = BranchLinkProperties()
lp.channel = "facebook"
lp.feature = "sharing"
lp.campaign = "content 123 launch"
lp.stage = "new user"
lp.tags = ["one", "two", "three"]

lp.addControlParam("$desktop_url", withValue: "http://example.com/desktop")
lp.addControlParam("$ios_url", withValue: "http://example.com/ios")
lp.addControlParam("$ipad_url", withValue: "http://example.com/ios")
lp.addControlParam("$android_url", withValue: "http://example.com/android")
lp.addControlParam("$match_duration", withValue: "2000")

lp.addControlParam("custom_data", withValue: "yes")
lp.addControlParam("look_at", withValue: "this")
lp.addControlParam("nav_to", withValue: "over here")
lp.addControlParam("random", withValue: UUID.init().uuidString)
BranchLinkProperties *lp = [[BranchLinkProperties alloc] init];
lp.feature = @"facebook";
lp.channel = @"sharing";
lp.campaign = @"content 123 launch";
lp.stage = @"new user";
lp.tags = @[@"one", @"two", @"three"];

[lp addControlParam:@"$desktop_url" withValue: @"http://example.com/desktop"];
[lp addControlParam:@"$ios_url" withValue: @"http://example.com/ios"];
[lp addControlParam:@"$ipad_url" withValue: @"http://example.com/ios"];
[lp addControlParam:@"$android_url" withValue: @"http://example.com/android"];
[lp addControlParam:@"$match_duration" withValue: @"2000"];

[lp addControlParam:@"custom_data" withValue: @"yes"];
[lp addControlParam:@"look_at" withValue: @"this"];
[lp addControlParam:@"nav_to" withValue: @"over here"];
[lp addControlParam:@"random" withValue: [[NSUUID UUID] UUIDString]];

创建深度链接

buo.getShortUrl(with: lp) { url, error in
        print(url ?? "")
    }
[buo getShortUrlWithLinkProperties:lp andCallback:^(NSString* url, NSError* error) {
    if (!error) {
        NSLog(@"@", url);
    }
}];

分享深度链接

let message = "Check out this link"
buo.showShareSheet(with: lp, andShareText: message, from: self) { (activityType, completed) in
  print(activityType ?? "")
}
buo showShareSheetWithLinkProperties:lp andShareText:@"Super amazing thing I want to share!" fromViewController:self completion:^(NSString* activityType, BOOL completed) {
    NSLog(@"finished presenting");
}];

读取深度链接

  • 从深度链接中提取 Branch 数据

  • 最佳做法是从listener 接收数据(以防止出现race condition)

  • 返回深度链接属性

// listener (within AppDelegate didFinishLaunchingWithOptions)
Branch.getInstance().initSession(launchOptions: launchOptions) { params, error in
  print(params as? [String: AnyObject] ?? {})
}

// latest
let sessionParams = Branch.getInstance().getLatestReferringParams()

// first
let installParams = Branch.getInstance().getFirstReferringParams()
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions
                        andRegisterDeepLinkHandler:^(NSDictionary * _Nullable params,
                                                     NSError * _Nullable error) {
    if (!error) {
        //Referring params
        NSLog(@"Referring link params %@",params);
    }
}];

// latest
NSDictionary *sessionParams = [[Branch getInstance] getLatestReferringParams];

// first
NSDictionary *installParams =  [[Branch getInstance] getFirstReferringParams];

导航至内容

  • 在此方法中处理 Branch.initSession()
// within AppDelegate application.didFinishLaunchingWithOptions
Branch.getInstance().initSession(launchOptions: launchOptions) { params , error in
  // Option 1: read deep link data
  guard let data = params as? [String: AnyObject] else { return }

  // Option 2: save deep link data to global model
  SomeCustomClass.sharedInstance.branchData = data

  // Option 3: display data
  let alert = UIAlertController(title: "Deep link data", message: "\(data)", preferredStyle: .alert)
  alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
  self.window?.rootViewController?.present(alert, animated: true, completion: nil)

  // Option 4: navigate to view controller
  guard let options = data["nav_to"] as? String else { return }
  switch options {
      case "landing_page": self.window?.rootViewController?.present( SecondViewController(), animated: true, completion: nil)
      case "tutorial": self.window?.rootViewController?.present( SecondViewController(), animated: true, completion: nil)
      case "content": self.window?.rootViewController?.present( SecondViewController(), animated: true, completion: nil)
      default: break
  }
}
// within AppDelegate application.didFinishLaunchingWithOptions
[[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
  // Option 1: read deep link data
  NSLog(@"%@", params);

  // Option 2: save deep link data to global model
  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  [defaults setObject:params.description forKey:@"BranchData"];
  [defaults synchronize];

  // Option 3: display data
  UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Title" message:params.description preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *button = [UIAlertAction actionWithTitle:@"Deep Link Data" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:button];
  [self.window.rootViewController presentViewController:alert animated:YES completion:nil];

  // Option 4: navigate to view controller
  if ([params objectForKey:@"navHere"]) {
    ViewController *anotherViewController = [[ViewController alloc] initWithNibName:@"anotherViewController" bundle:nil];
    [self.window.rootViewController presentViewController:anotherViewController animated:YES completion:nil];
  }
}];

展示

buo.automaticallyListOnSpotlight = true
buo.automaticallyListOnSpotlight = YES;

跟踪内容

BranchEvent.standardEvent(.viewItem, withContentItem: buo).logEvent()
[[BranchEvent standardEvent:BranchStandardEventViewItem withContentItem:buo] logEvent];

跟踪事件

  • 与客户购买相关的所有事件都属于商业活动(Commerce)类事件

  • 与用户与应用程序中内容交互相关的所有事件都属内容(Content)类事件。

  • 与用户在应用程序中的进展相关的所有事件都属于生命周期(Lifecycle)类事件。

  • 要跟踪自定义事件(在下表中没有的),请参见跟踪自定义事件

  • 使用 Branch 控制面板进行验证

使用下表快速找到您要跟踪的事件。

活动名称活动类别iOS
Add To Cart商业活动BranchStandardEventAddToCart
Add To Wishlist商业活动BranchStandardEventAddToWishlist
View Cart商业活动BranchStandardEventViewCart
Initiate Purchase商业活动BranchStandardEventInitiatePurchase
Add Payment Info商业活动BranchStandardEventAddPaymentInfo
Purchase商业活动BranchStandardEventPurchase
Spend Credits商业活动BranchStandardEventSpendCredits
Search内容事件BranchStandardEventSearch
View Item内容事件BranchStandardEventViewItem
View Items内容事件BranchStandardEventViewItems
Rate内容事件BranchStandardEventRate
Share内容事件BranchStandardEventShare
Complete Registration生命周期事件BranchStandardEventCompleteRegistration
Complete Tutorial生命周期事件BranchStandardEventCompleteTutorial
Achieve Level生命周期事件BranchStandardEventAchieveLevel
Unlock Achievement生命周期事件BranchStandardEventUnlockAchievement

处理推送通知

  • 允许您在推送通知中跟踪Branch深度链接

  • 将Branch推送处理代码包括在Branch初始化代码中

  • 在您的推送通知中添加Branch深度链接 payload

    • 用您的深度链接替换https://example.app.link/u3fzDwyyjF
{
  "aps": {
    "alert": "Push notification with a Branch deep link",
    "badge": "1"
  },
  "branch": "https://example.app.link/u3fzDwyyjF"
}

处理您自己的应用程序中的深度链接

  • 允许您从应用内深度链接到应用本身
Branch.getInstance().handleDeepLink(withNewSession: URL(string: "https://example.app.link/u3fzDwyyjF"))
[[Branch getInstance] handleDeepLinkWithNewSession:[NSURL URLWithString:@"https://example.app.link/u3fzDwyyjF"]];

❗️

在您的应用中处理新的深层链接

在您的应用程序中处理新的深度链接接将清除当前会话数据,并将新引用的"设为" 。

追踪Apple搜索广告

  • 允许Branch跟踪Apple Search Ads深度链接分析

  • Apple API的分析数据生成速度很慢,这会影响到我们的分析数据。此外,Apple的API不会每次都向我们发送广告的所有数据,这有时会导致我们跟踪的广告只显示为通用的广告系列。

  • initSession 之前初始化Branch

Branch.getInstance().delayInitToCheckForSearchAds()
[[Branch getInstance] delayInitToCheckForSearchAds];

启用100%匹配

  • 使用SFSafariViewController 来增加归因匹配成功率

  • 100%匹配有点用词不当,因为与用户从Safari浏览器点击时相比,只有100%匹配。根据我们的分析,通过Safari浏览器点击的大约有50-75%,具体取决于用例。例如,从Facebook或Chrome浏览器点击不会触发100%的匹配。不过此技术仍然对匹配精度有利,所以我们建议采用它。

  • 使用自定义域时,请在Info.plist中添加带有自定义域的branch_app_domain字符串键
    启用100%匹配。

  • 默认情况下,如果设置为SafariServices.framework ,则在iOS 9和10上启用基于cookie的匹配
    包含在应用程序的依赖项中,并且该应用程序使用app.link子域或设置branch_app_domain
    在Info.plist中。可以通过调用SDK来禁用它。

  • initSession 之前初始化Branch

Branch.getInstance().disableCookieBasedMatching()
[[Branch getInstance] disableCookieBasedMatching];

启用/禁用用户跟踪

如果您出于GDPR的目的需要遵循用户的请求而不被跟踪,或者以其他方式确定不应当跟踪用户,请利用此字段来防止Branch发送网络请求。也可以在所有用户的特定链接或Branch链接中启用此设置。

Branch.setTrackingDisabled(true)
[Branch setTrackingDisabled:YES];

您可以选择在应用程序的整个生命周期中调用它。调用后,将不会从SDK发送网络请求。链接生成将继续起作用,但将不包含有关用户的标识信息。此外,深度链接接将继续起作用,但不会为用户跟踪分析。

共享到电子邮件选项

lp.addControlParam("$email_subject", withValue: "Your Awesome Deal")
lp.addControlParam("$email_html_header", withValue: "<style>your awesome CSS</style>\nOr Dear Friend,")
lp.addControlParam("$email_html_footer", withValue: "Thanks!")
lp.addControlParam("$email_html_link_text", withValue: "Tap here")
[lp addControlParam:@"$email_subject" withValue:@"This one weird trick."];
[lp addControlParam:@"$email_html_header" withValue:@"<style>your awesome CSS</style>\nOr Dear Friend,"];
[lp addControlParam:@"$email_html_footer" withValue:@"Thanks!"];
[lp addControlParam:@"$email_html_link_text" withValue:@"Tap here"];

动态分享讯息

// import delegate
class ViewController: UITableViewController, BranchShareLinkDelegate

func branchShareLinkWillShare(_ shareLink: BranchShareLink) {
  // choose shareSheet.activityType
  shareLink.shareText = "\(shareLink.linkProperties.channel)"
}
// import delegate
@interface ViewController () <BranchShareLinkDelegate>

  - (void) branchShareLinkWillShare:(BranchShareLink*)shareLink {
  // choose shareSheet.activityType
  shareLink.shareText = [NSString stringWithFormat:@"@%", shareLink.linkProperties.channel];
}

返回YES继续continueUserActivity

当用户通过通用链接进入您的应用时,我们将检查链接URL是否包含app.link 。如果是这样,则Branch.getInstance().continue(userActivity) 将返回YES 。如果不是,则Branch.getInstance().continue(userActivity) 将返回NO 。这使我们可以明确确认传入的链接来自Branch,而无需进行服务器调用。

对于大多数实现而言,这永远不会成为问题,因为您的深度链接接将以任何一种方式正确路由。但是,如果您使用自定义链接域 ,则依靠Branch.getInstance().continue(userActivity) 为每个传入的Branch生成的通用链接返回YES ,可以按照以下步骤通知Branch SDK:

  1. 在您的Info.plist 文件中,创建一个名为branch_universal_link_domains的新密钥。
  2. 将您的自定义域添加为字符串。 图像图像
  3. 保存文件。

📘

多个自定义域

If you have an unusual situation with multiple custom link domains, you may also configure branch_universal_link_domains as an array of strings. 图像图像

处理仅网络内容的链接

🚧

仅通用电子邮件

如果您具有仅存在于Web而非应用程序中的内容的链接(例如,应用程序中不为' t的临时营销网页),则此代码段将确保所有未应用深度链接接脚本的链接将在浏览器中打开。

您应该在深度链接处理程序代码块内添加此代码段。请注意,这使用查询参数$web_only=true 。这应该与您在电子邮件中输入的Web URL上的查询参数匹配。

[branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
  // params are the deep linked params associated with the link that the user clicked before showing up.
  if (params[@"$3p"] && params[@"$web_only"]) {
            NSURL *url = [NSURL URLWithString:params[@"$original_url"]];
            if (url) {
                [application openURL:url]; // check to make sure your existing deep linking logic, if any, is not executed, perhaps by returning early
            }
  } else {
    // it is a deep link
    GDLog(@"branch deep link: %@", [params description]);
    [self handleBranchDeeplink:params];
  }
}];
branch.initSession(launchOptions: launchOptions, andRegisterDeepLinkHandler: { (params, error) in
            if (params?["$3p"] != nil && params?["$web_only"] != nil) {
                if let urlString = params?["$original_url"] as? String {
                    if let url = URL(string: urlString) {
                        application.openURL(url)
                    }
                }
            } else {
                self.handleBranchDeeplink(params)
            }
        })

初始化元数据

🚧

仅限数据整合

如果您使用第三方数据整合伙伴,在初始化 Branch SDK 前需要特定标识符设定,您需要添加此代码段:

//Inside *didFinishLaunchingWithOptions*
[[Branch getInstance] setRequestMetadataKey:@"{ANALYTICS_ID}" value: […]];

{ANALYTICS_ID}替换为您的数据整合伙伴键钥。

App Clips

An App Clip is a lightweight version of your app that offers users some of its functionality when and where they need it.

Follow Apple's developer documentation on creating an app clip with xcode

Important thing to note:

  • The Associated Domains entitlement has a new appclips type, which is required if you’re implementing app clips.
  • The AASA file must be updated to support app clips; via a Branch database update.
    • Please Submit a Ticket to make this request. Make sure to include your App Clip bundle ID and team ID in your request.

The Branch iOS SDK must be integrated into an App Clip in the same way as the Full App; with the following caveats:

  • You do not need the applinks setting in your Associated Domains entitlement.
  • Cocoapods does not install the Branch SDK into your App Clip.

How to Persist App Clip Install Data to Subsequent Full App Install

  1. Add an App Groups entitlement.
  2. Choose a group will be used to share data between the App Clip and subsequent Full App install.
  1. In both your Full App and App Clip, inform the Branch SDK of the App Group name prior to calling initSession. See Apple's developer doc for more information.
[[Branch getInstance] setAppClipAppGroup:@"group.io.branch"];
Branch.getInstance().setAppClipAppGroup("group.io.branch")

12 天前更新


iOS高级功能


建议的编辑仅限于API参考页

您只能建议对Markdown正文内容进行修改,而不能建议对API规范进行修改。