iOS 高级功能

创建内容引用 (Content Reference)

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 Link 或有另一个用例,则可以通过以下调用直接创建深度链接:

[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(在此示例中)。

Specifying a shared email subjects

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

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");
}];

Share with LPLinkMetadata

  • Create a BranchShareLink instance with a BranchUniversalObject and LinkProperties.
  • Set the BranchShareLink's LPLinkMetadata by using the addLPLinkMetadata() function.
  • Present the BranchShareLink's Share Sheet.
//Initialize a BranchShareLink with a BranchUniversalObject and BranchLinkProperties.
//Then set the BranchShareLink's LPLinkMetadata with a preview title and icon.

let bsl = BranchShareLink(universalObject: buo, linkProperties: lp)
bsl.addLPLinkMetadata("LPLinkMetaData Link Title", icon: iconImg)
bsl.presentActivityViewController(from: self, anchor: nil)
//Initialize a BranchShareLink with a BranchUniversalObject and BranchLinkProperties.
//Then set the BranchShareLink's LPLinkMetadata with a preview title and icon.

BranchShareLink *bsl = [[BranchShareLink alloc] initWithUniversalObject:buo linkProperties:lp];
[bsl addLPLinkMetadata:@"LPLinkMetadata Link Title" icon:iconImg];
[bsl presentActivityViewControllerFromViewController:self anchor:nil];

读取深度链接

  • 从深度链接中提取 Branch 数据
  • listener 接收数据的最佳实践(以防止出现 race condition)
  • Returns deep link properties
// 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];

NativeLink™ Deferred Deep Linking

  • Use iOS pasteboard to enable deferred deep linking via Branch NativeLink™

🚧

先决条件

Minimum SDK Version: v1.39.4

To use this feature you must:

or

Options for Implementation

  • Enable in the AppDelegate by calling checkPasteboardOnInstall() before the Branch initialization in didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // enable pasteboard check  
    Branch.getInstance().checkPasteboardOnInstall()
    
    // listener for Branch Deep Link data
    Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
        // do stuff with deep link data (nav to page, display content, etc)
        print(params as? [String: AnyObject] ?? {})
    }
  return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // enable pasteboard check
        [[Branch getInstance] checkPasteboardOnInstall];

        // listener for Branch Deep Link data
    [[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
        // do stuff with deep link data (nav to page, display content, etc)
            NSLog(@"%@", params);
    }];
    return YES;
}
  • Enable in the AppDelegate for iOS 15+ Only
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // enable pasteboard check for iOS 15+ only
    if let currentIOSVersion = Double(UIDevice.current.systemVersion), currentIOSVersion >= 15.0
            Branch.getInstance().checkPasteboardOnInstall()
        
    
    // listener for Branch Deep Link data
    Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
        // do stuff with deep link data (nav to page, display content, etc)
        print(params as? [String: AnyObject] ?? {})
    }
  return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // enable pasteboard check for iOS 15+ only
        if ([[[UIDevice currentDevice] systemVersion] compare:@"15.0" options:NSNumericSearch] != NSOrderedAscending)
        [[Branch getInstance] checkPasteboardOnInstall];
    

        // listener for Branch Deep Link data
    [[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
        // do stuff with deep link data (nav to page, display content, etc)
            NSLog(@"%@", params);
    }];
    return YES;
}
  • Enable in the AppDelegate with check notification
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // enable pasteboard check  
    Branch.getInstance().checkPasteboardOnInstall()
  
    // check if pasteboard toast will show
    if Branch.getInstance().willShowPasteboardToast(){
        // devlopers can notify the user of what just occurred here if they choose
        
    }
  
    // listener for Branch Deep Link data
    Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
        // do stuff with deep link data (nav to page, display content, etc)
        print(params as? [String: AnyObject] ?? {})
    }
  return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // enable pasteboard check
        [[Branch getInstance] checkPasteboardOnInstall];
  
    // check if pasteboard toast will show
    if ([[Branch getInstance] willShowPasteboardToast]) {
        // developers can notify the user of what just occurrred here if they choose
        
    }

        // listener for Branch Deep Link data
    [[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
        // do stuff with deep link data (nav to page, display content, etc)
            NSLog(@"%@", params);
    }];
    return YES;
}

Create QR Code

  • Create a BranchQRCode object and set the properties
  • Create a BranchUniversalObject and BranchLinkProperties
  • Use getQRCodeAsImage() or getQRCodeAsData() to create a QR code
  • Use showShareSheetWithQRCodeFromViewController() to create a QR code and share it via the Share Sheet.
let qrCode = BranchQRCode()
qrCode.codeColor = UIColor.white
qrCode.backgroundColor = UIColor.blue
qrCode.centerLogo = "https://cdn.branch.io/branch-assets/1598575682753-og_image.png"
qrCode.width = 1024
qrCode.margin = 1
qrCode.imageFormat = .JPEG

let buo = BranchUniversalObject()
let lp = BranchLinkProperties()

qrCode.getAsImage(buo, linkProperties: lp) { qrCodeImage, error in
    //Do something with your QR code here...
}

//Or display the QR code directly in a share sheet
qrCode.showShareSheetWithQRCode(from: self, anchor: nil, universalObject: buo, linkProperties: lp) { error in
    //Showing a share sheet with the QR code
}
BranchQRCode *qrCode = [BranchQRCode new];
qrCode.codeColor = [[UIColor new] initWithRed:0.1 green:0.8392 blue:0.8667 alpha:1.0];
qrCode.backgroundColor = [UIColor whiteColor];
qrCode.width = @700;
qrCode.margin = @1;
qrCode.centerLogo = @"https://cdn.branch.io/branch-assets/1598575682753-og_image.png";
qrCode.imageFormat = BranchQRCodeImageFormatPNG;
    
BranchUniversalObject *buo = [BranchUniversalObject new];
BranchLinkProperties *lp = [BranchLinkProperties new];

[qrCode getQRCodeAsImage:buo linkProperties:lp completion:^(UIImage * _Nonnull qrCode, NSError * _Nonnull error) {
    //Do something with the QR code here...
}];

//Or display the QR code directly in a share sheet
[qrCode showShareSheetWithQRCodeFromViewController:self anchor:nil universalObject:buo linkProperties:lp completion:^(NSError * _Nullable error) {
    //Showing a share sheet with the QR code
}];

前往内容

  • 在此方法中处理 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;

追踪 ATT 选择加入和选择退出

if (ATTrackingManager.trackingAuthorizationStatus == .notDetermined) {
    ATTrackingManager.requestTrackingAuthorization { (status) in
        Branch.getInstance().handleATTAuthorizationStatus(status.rawValue)
    }
}
if (ATTrackingManager.trackingAuthorizationStatus == ATTrackingManagerAuthorizationStatusNotDetermined) {
    [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        [[Branch getInstance] handleATTAuthorizationStatus:status];
    }];
}

📘

Second install

  • After we see user opt-in via ATT, we are tracking an additional analytics event we call a “second install” for ad-driven installs, which will be deduped from "first install" on our Dashboard.
  • All conversion events will be attributed to that "second install".
  • More information

追踪内容

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

追踪事件

  • 与客户购买有关的所有事件都会归类到数据项的 “Commerce” 类别中
  • 与用户与应用中内容交互相关的所有事件都会归类到数据项的 “Content” 类别中。
  • 与用户在应用中的进展相关的所有事件都会归类到数据项的 “Lifecycle” 类别中。
  • To track custom events - not found in the table below - please see Track Custom Events
  • Validate with the Branch Dashboard

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

Event 名称

事件类别

iOS

添加到购物车

Commerce Event

BranchStandardEventAddToCart

加到收藏夹

Commerce Event

BranchStandardEventAddToWishlist

查看购物车

Commerce Event

BranchStandardEventViewCart

发起购买

Commerce Event

BranchStandardEventInitiatePurchase

添加付款信息

Commerce Event

BranchStandardEventAddPaymentInfo

购买

Commerce Event

BranchStandardEventPurchase

消费积分

Commerce Event

BranchStandardEventSpendCredits

搜索

Content 事件

BranchStandardEventSearch

查看商品

Content 事件

BranchStandardEventViewItem

查看商品

Content 事件

BranchStandardEventViewItems

频率

Content 事件

BranchStandardEventRate

分享

Content 事件

BranchStandardEventShare

完成注册

Lifecycle Event

BranchStandardEventCompleteRegistration

完成教程

Lifecycle Event

BranchStandardEventCompleteTutorial

达标级别

Lifecycle Event

BranchStandardEventAchieveLevel

解锁成就

Lifecycle Event

BranchStandardEventUnlockAchievement

Handle Branch Links when using Branch & Firebase SDK

There is a known issue with Firebase where it will call the following Instance Methods:

To account for this, you must check the link first to determine if it should be handled by the Branch SDK:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
  //check for link_click_id
  if url.absoluteString.contains("link_click_id") == true{
    return Branch.getInstance().application(app, open: url, options: options)
  }
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  //check for app.link or appropriate Branch custom domain
  if userActivity.webpageURL?.absoluteString.contains("app.link"){
    return Branch.getInstance().continue(userActivity)
  }
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  if ([url.absoluteString containsString:@"link_click_id"])  {
    return [[Branch getInstance] application:app openURL:url options:options];
  }
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
  if ([userActivity.webpageURL.absoluteString containsString:@"app.link"]) {
    return [[Branch getInstance] continueUserActivity:userActivity];
  }
}

处理推送通知

  • 可让您在推送通知中追踪 Branch 深度链接
  • Include the Branch push notification handler in Initialize 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"]];

❗️

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

在应用中处理新的深度链接将清除当前会话数据,并将新引用的 “open” 归因于此。

延迟 Branch 初始化

延迟 Install 的 Branch 初始化,以向用户请求追踪许可。

  1. 创建一个表示 Install session 的布尔值标记并将其设置为 true (例如firstOpen)
  2. didFinishLaunchingWithOptions 初始化 Branch 之前
    a. 如果为 false,则继续 Branch SDK 初始化
    b. 如果为 true
    i. 当 firstOpen 为 true 时,在整个用户引导流程中坚持使用 launchOptions 或在本地存储
    ii. 继续用户引导流程
  3. After determining User's tracking preference
    a. Set tracking in Branch SDK per User's preference
    b. Initilialize the Branch SDK utilizing the persisted launchOptions
  4. 将 Install boolean ( firstOpen) 设置为 false

启用100%匹配

To enable 100% Matching on iOS through Installs, please utilize our NativeLink™ feature.

启用/禁用用户追踪

如果您需要按照 GDPR 的目的遵循用户不被追踪的请求,或者认为用户不应该被追踪,请利用此字段来防止 Branch 发送网络请求。此设置也可以在所有用户的特定链接或 Branch Link 中被启用。

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

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

分享到电子邮件选项

  • 更改当分享到电子邮件时深度链接的行为
  • Needs a Share deep link
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"];

动态分享消息

  • 根据用户选择的来源更改您分享的消息
  • Needs a Share deep link
// 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

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

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

  1. 在您的 Info.plist 文件中,创建一个名为 branch_universal_link_domains 的新 Key。
  2. 将您的自定义域添加为 string。 图片图片
  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-only 内容的链接

🚧

仅通用电子邮件

If you have links to content that exists only on the web and not in the app (for example, a temporary marketing webpage that isn't in the app), then this code snippet will ensure all links that have not had the deep linking script applied will open in a browser.

You should add this code snippet inside the deep link handler code block.

📘

注意

This uses query parameter $web_only=true. This should match the query parameter on the web URL you enter in the email.

[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)
            }
        })

Universal Links with Web-Only Content

Web-only Branch links that redirect to a site that hosts its own AASA file where Universal Links (UL) is enabled will cause unexpected behavior. Since Branch does not have a way to bypass UL (via JavaScript, delays, etc.), you must add a query param exclusion in the AASA file to persist web-only behavior when redirecting to a website. This only applies if you are trying to redirect via $web_only=true to their own website.

Add the following filter to the AASA File:

{
  "/": "*",
  "?": { "$web_only": "true" },
  "exclude": true,
  "comment": "Matches any URL which has a query item with name '$web_only' and a value of exactly true"
}

Now if $web_only=true is appended to the final fallback URL / redirect, iOS will not attempt to launch the App even if it is installed. ex. https://myhomepage.com/?$web_only=true
This link with the query parameter can now be used as the fallback of a web-only Branch link and persist the behavior all the way to myhomepage.com.

设置初始化 metadata

🚧

仅限数据集成

If you are using a 3rd Party Data Integration Partner that requires setting certain identifiers before initializing the Branch SDK, you should add this code snippet:

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

{ANALYTICS_ID}替换为您的数据集成伙伴的 key。

App Clip

👍

App Clip 分析

我们将自动为 App Clip 触点(例如 QR 码扫描)和会话进行归因。
触点:

  • 事件名称:Click
  • last_attributed_touch_data_tilde_customer_placement: APP_CLIP
  • last_attributed_touch_data_tilde_creative_name:如果在 App Clip 链接内,则设置为$app_clip_id

会话:

  • 事件名称:Install/Open
  • user_data_environment: APP_CLIP
  • last_attributed_touch_data_tilde_creative_name :设置为$app_clip_id值(如果存在)。

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 to note

  • 关联域 (Associated Domains)权利具有新的appclips类型,如果要实现 app clip,则必须使用它。
    • 必须更新 AASA 文件以支持 app clip;通过 Branch 数据库更新。
      • 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:

  • 您不需要 App Clip 的关联域 (Associated Domains)权利中的applinks设置。
  • Cocoapods 不会将 Branch SDK 安装到您的 App Clip 中。

如何将 App Clip 安装数据持久保存到后续 Full App Install 中

  1. 添加 App Groups 权利。
  2. 选择一个组,它将用于在 App Clip 和后续 Full App Install 之间分享数据。
25602560
  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")

将 Branch Link 作为 App Clip Invocation URL

您可以配置 App Clip 相关 Branch Link。创建链接时,您可以指定 Branch Link 需要打开的 App Clip。您可以通过叫做$app_clip_id的 Branch Link 参数来执行此操作。

比方说您有两个 App Clip,一个用于 Store,一个用于 Product。

在 iTunesConnect 操作后台 (Dashboard)上,您需要将以下两项注册为高级 App Clip Experience:

  • your.app.link/ac/s/*-- 用于 Store 链接
  • your.app.link/ac/p/* -- 用于 Product 链接

然后,在创建 Branch Link 时,您设置$app_clip_id: s,如下所示:

14681468

接着,Branch 将自动创建一个 App Clip ID 的链接,并将其作为路径的一部分: https://your.app.link/ac/s/QfJ2H7c7jcb

此外,您可以为这些链接指定别名。如果把 $app_clip_url = s和别名设置为12345 ,您将获得以下链接: https://your.app.link/ac/s/12345。这将是一个很好的方法来创建一个 ID 12345的 Store 的链接!

📘

注意

https://your.app.link/ac/s/12345 returns the same payload as https://your.app.link/12345. The path elements are only to ease registering App Clip experiences.

🚧

App Clip Code invocation URL 的字符长度限制较短

与大多数 App Clip 不同,App Clip 代码对 URL 长度限制较短。长度限制有所不同,但大约为35个字符。您的 Branch Link 可能太长,无法在这种情况下使用。尽可能使用最短的展示位置标识符(placement identifier)来增加生成足够短的链接的几率。我们建议指定一个简短的 $app_clip_id 和别名。

https://developer.apple.com/documentation/app_clips/creating_app_clip_codes

在 iOS 渠道上调用 App Clip

Once you have registered your Branch App Clip with Apple, Apple allows you to invoke App Clips on a few channels. Here's an example: https://branchster.app.link/6ZfIMUrDzbb#appclip

iMessage

200200

默认情况下,如果 Branch Links 被注册为 App Clip Invocation URL,它们将自动在 iMessage 上注册并显示您的 App Clip CTA。

Safari 广告横幅

200200

您也可以自己在网站上显示 App Clip 广告横幅。为此,您需要将标准的 Apple 元标签添加到您的网站:

<meta name="apple-itunes-app" content="app-id=myAppStoreID, app-clip-bundle-id=appClipBundleID>

If you want to display the banner on a Branch Deepview, add it to the HTML code in the Branch dashboard Deepview Manager.

For more information, please refer to Apple's documentation.

包括 Apple 的 ATTrackingManager

🚧

需要包含 AdSupport 框架

为了使 ATTrackingManager 起作用,您还必须确保在 iOS SDK 实现 AdSupport

默认情况下,Branch SDK 不包含 ATTrackingManager ,如果您想收集 IDFA 以进行归因这是必须项。

Learn more about Apple's App Transparency Tracking Manager.

如果您想使用 IDFA,则需要在您应用程序流中的适当时间显示 ATTrackingManager 提示符。此示例代码演示了如何显示提示符并记录 IDFA。

func requestIDFAPermission() {
        if #available(iOS 14, *) {
            DispatchQueue.main.async {
                ATTrackingManager.requestTrackingAuthorization { (status) in
                    if (status == .authorized) {
                        let idfa = ASIdentifierManager.shared().advertisingIdentifier
                        print("IDFA: " + idfa.uuidString)
                    } else {
                        print("Failed to get IDFA")
                    }
                }
            }
        }
    }
- (void)requestIDFAPermission {
    if (@available(iOS 14.0, *)) {
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        dispatch_async(dispatch_get_main_queue(), ^{
            [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
                if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
                    NSUUID *idfa = [[ASIdentifierManager sharedManager] advertisingIdentifier];
                    NSLog(@"IDFA: %@", idfa);
                } else {
                    NSLog(@"Failed to get IDFA permission");
                }
                dispatch_semaphore_signal(semaphore);
            }];
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
}

从 Branch iOS SDK 1.39.1 开始,在最终用户授予的情况下,SDK 将看到授权状态。您无需再进行其他额外操作来通知 Branch SDK。

在较早版本的 SDK 上,服务器会通过是否存在 IDFA 来推断授权状态。同样,您无需再进行其他额外操作来通知 Branch SDK。

Set Hashed Information for Facebook Advanced Matching

You can pass additional hashed information to the SDK before initSession() for Facebook Advanced Matching.

...
//set hash parameters for Facebook Advanced Matching
Branch.getInstance().addFacebookPartnerParameter(withName: "em", value: "11234e56af071e9c79927651156bd7a10bca8ac34672aba121056e2698ee7088")
...
//initialize Branch session
Branch.getInstance().initSession(...)

这个页面对您有帮助吗?