iOS Advanced Features

Create 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 링크를 생성하거나 다른 사용 사례를 갖고 싶다면 다음 호출을 통해 직접 딥링크(Deep 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에 게시하도록 (이 예제에서) 도와줍니다.

공유 이메일 제목 지정

대부분의 공유 옵션에는 제목과 본문이 있는 이메일을 제외하고 하나의 텍스트 스트링만 포함됩니다. 공유 텍스트가 본문에 채워지며 아래와 같이 링크 속성에서 이메일 제목을 지정할 수 있습니다.

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")

Create Link Reference

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]];

Create Deep Link

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

Share Deep Link

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

Read Deep Link

  • Retrieve Branch data from a deep link

  • Best practice to receive data from the listener (to prevent a 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 = Int(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;
}

Navigate to Content

  • Handled within 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];
  }
}];

Display

buo.automaticallyListOnSpotlight = true
buo.automaticallyListOnSpotlight = YES;

Track ATT Opt-In and Opt-Out

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

Track content

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

Track Events

  • All events related to a customer purchasing are bucketed into a "Commerce" class of data items

  • All events related to users interacting with your in-app content are bucketed to a "Content" class of data items.

  • All events related to users progressing in your app are bucketed to a "Lifecycle" class of data items.

  • To track custom events - not found in the table below - please see Track Custom Events

  • Validate with the Branch Dashboard

Use the table below to quickly find the event you want to track.

Event NameEvent CategoryiOS
Add To CartCommerce EventBranchStandardEventAddToCart
Add To WishlistCommerce EventBranchStandardEventAddToWishlist
View CartCommerce EventBranchStandardEventViewCart
Initiate PurchaseCommerce EventBranchStandardEventInitiatePurchase
Add Payment InfoCommerce EventBranchStandardEventAddPaymentInfo
PurchaseCommerce EventBranchStandardEventPurchase
Spend CreditsCommerce EventBranchStandardEventSpendCredits
SearchContent EventBranchStandardEventSearch
View ItemContent EventBranchStandardEventViewItem
View ItemsContent EventBranchStandardEventViewItems
RateContent EventBranchStandardEventRate
ShareContent EventBranchStandardEventShare
Complete RegistrationLifecycle EventBranchStandardEventCompleteRegistration
Complete TutorialLifecycle EventBranchStandardEventCompleteTutorial
Achieve LevelLifecycle EventBranchStandardEventAchieveLevel
Unlock AchievementLifecycle EventBranchStandardEventUnlockAchievement

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

Handle Push Notifications

  • Allows you to track Branch deep links in your push notifications

  • Include the Branch push notification handler in Initialize Branch

  • Add a Branch deep link in your push notification payload

    • Replace https://example.app.link/u3fzDwyyjF with your deep link
{
  "aps": {
    "alert": "Push notification with a Branch deep link",
    "badge": "1"
  },
  "branch": "https://example.app.link/u3fzDwyyjF"
}

Handle Links in Your Own App

  • Allows you to deep link into your own from your app itself
Branch.getInstance().handleDeepLink(withNewSession: URL(string: "https://example.app.link/u3fzDwyyjF"))
[[Branch getInstance] handleDeepLinkWithNewSession:[NSURL URLWithString:@"https://example.app.link/u3fzDwyyjF"]];

❗️

Handling a new deep link in your app

Handling a new deep link in your app will clear the current session data and a new referred "open" will be attributed.

Delay Branch Initialization

Delay the Branch initialization on Installs in order to request tracking permission from the user.

  1. Create a boolean flag to represent an Install session and set it to true (e.g. firstOpen)
  2. Before the Branch init in didFinishLaunchingWithOptions
    a. if false continue with Branch SDK init
    b. if true:
    i. Persist launchOptions throughout onboarding flow or store locally when firstOpen is true
    ii. Continue with onboarding flow
  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. Set Install boolean (firstOpen) to false

Track Apple Search Ads

  • Allows Branch to track Apple Search Ads deep linking analytics

  • Analytics from Apple's API have been slow which will make our analytics lower. Additionally, Apple's API does not send us all the data of an ad every time which will make ads tracked by us to show a generic campaign sometimes.

  • Add before initSession Initialize Branch

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

Enable 100% Matching

  • Use the SFSafariViewController to increase the attribution matching success

  • The 100% match is a bit of a misnomer, as it is only 100% match from when a user clicks from the Safari browser. According to our analysis, clicking through Safari happens about 50-75% of the time depending on the use case. For example, clicking from Facebook, Gmail or Chrome won’t trigger a 100% match here. However, it’s still beneficial to the matching accuracy, so we recommend employing it.

  • When using a custom domain, add a branch_app_domain string key in your Info.plist with your custom domain
    to enable 100% matching.

  • By default, cookie-based matching is enabled on iOS 9 and 10 if the SafariServices.framework
    is included in an app's dependencies, and the app uses an app.link subdomain or sets the branch_app_domain
    in the Info.plist. It can be disabled with a call to the SDK.

  • Add before initSession Initialize Branch

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

Enable / Disable User Tracking

If you need to comply with a user's request to not be tracked for GDPR purposes, or otherwise determine that a user should not be tracked, utilize this field to prevent Branch from sending network requests. This setting can also be enabled across all users for a particular link, or across your Branch links.

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

You can choose to call this throughout the lifecycle of the app. Once called, network requests will not be sent from the SDKs. Link generation will continue to work, but will not contain identifying information about the user. In addition, deep linking will continue to work, but will not track analytics for the user.

Share to Email Options

  • Change the way your deep links behave when shared to email

  • 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"];

Share Message Dynamically

  • Change the message you share based on the source the users chooses

  • 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];
}

continueUserActivity에 YES를 반환합니다.

유저가 Universal Link를 통해 앱에 들어가면 Link URL에 app.link이 포함되어 있는지 확인합니다. 그렇다면 Branch.getInstance().continue(userActivity)YES를 리턴합니다. 그렇지 않은 경우 Branch.getInstance().continue(userActivity)NO를 리턴합니다. 이를 통해 서버 호출 없이 들어오는 링크는 Branch에서 왔음을 명시적으로 확인할 수 있습니다.

대부분의 구현에서는 딥링크(Deep Link)가 어느 쪽이든 올바르게 라우팅되므로 이는 문제가 되지 않습니다. 하지만 커스텀 링크 도메인을 사용하면서 모든 인커밍 Branch-생성 유니버셜 링크에 대해 YES 을 리턴하기 위해 Branch.getInstance().continue(userActivity) 에 의존한다면, 다음 단계를 준수하여 Branch SDK에 알릴 수 있습니다:

  1. Info.plist 파일에서 branch_universal_link_domains 이라는 새 키를 만듭니다.
  2. 커스텀 도메인(들)을 스트링으로 추가합니다. imageimage
  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. imageimage

웹 전용 콘텐츠에 대한 링크 처리

🚧

범용 이메일 만

웹에만 있고 앱에 없는 콘텐츠에 대한 링크가 있는 경우 (예: 앱에 없는 임시 마케팅 웹 페이지) 이 코드 스니펫은 딥링킹(Deep Linking) 스크립트가 적용되지 않은 모든 링크가 브라우저에서 열리도록 보장합니다.

이 코드 스 니펫을 딥 링크 핸들러 코드 블록 안에 추가해야합니다. 이것은 쿼리 매개 변수 $web_only=true 사용합니다. 이것은 이메일에 입력 한 웹 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)
            }
        })

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.

Set initialization metadata

🚧

Data Integration Only

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: […]];

Replace {ANALYTICS_ID} with your Data Integration Partner's key.

App Clips

👍

App Clip Analytics

We will automatically attribute App Clip touches (like a QR Code scan) and sessions.
Touch:

  • Event Name: Click
  • last_attributed_touch_data_tilde_customer_placement: APP_CLIP
  • last_attributed_touch_data_tilde_creative_name: Set as $app_clip_id value if it is present in the App Clip link.

Session:

  • Event Name: Install/Open
  • user_data_environment: APP_CLIP
  • last_attributed_touch_data_tilde_creative_name: Set as $app_clip_id value if it is present.

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 the App Clip's 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")

Branch Links as App Clip Invocation URLs

You can configure Branch links to be associated with App Clips. When creating a link, you specify which App Clip the Branch link should open. You do this via a Branch link parameter called $app_clip_id.

For example, let's say you have two App Clips, one for Stores and one for Products.

On the iTunesConnect Dashboard, you'd register the following two as advanced App Clip Experiences:

  • your.app.link/ac/s/* -- for Store links
  • your.app.link/ac/p/* -- for Product links

Then when creating a Branch link, you set $app_clip_id: s, as seen below:

Then Branch will automatically create a link with the App Clip ID as part of the path: https://your.app.link/ac/s/QfJ2H7c7jcb.

Additionally, you can specify an alias for these links. If you set $app_clip_url = s and alias to 12345, you'll get the following link: https://your.app.link/ac/s/12345. This would be a great way to create a link to Store with ID 12345!

Note that 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 URLs have a short character length limit

Unlike most App Clips, App Clip Code has a short URL limit. The length limit varies, but is about 35 characters. It is possible your Branch Link will be too long to be used in this situation. Use the shortest placement identifier possible to increase the odds your generated link will be short enough. We recommend specifying a short $app_clip_id and a short alias.

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

Invoking App Clips on iOS Channels

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

Branch Links will automatically register and display your App Clip CTA on iMessage by default if they are registered as App Clip Invocation URLs.

Safari Banner

You can also display an App Clip banner on your website yourself. In order to do this, you need to add the standard Apple meta tag to your website:

<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.

Include Apple's ATTrackingManager

🚧

Requires the inclusion of AdSupport Framework

In order for the ATTrackingManager to function, you must also ensure you've added the AdSupport framework in your iOS SDK implementation.

By default, the Branch SDK does not include the ATTrackingManager which is required by Apple if you want to collect the IDFA for attribution purposes.

Learn more about Apple's App Transparency Tracking Manager.

If you wish to use the IDFA, you will need to display the ATTrackingManager prompt at an appropriate time in your app flow. This sample code demonstrates displaying the prompt and logging the 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);
    }
}

Starting from Branch iOS SDK 1.39.1, the SDK will see the authorization status if it is granted by the end-user. There is no additional work on your end to inform the Branch SDK.

On older versions of the SDK, the server infers the authorization status by the presence of the IDFA. Again there is no additional work on your end to inform the Branch SDK.

4일 전에 업데이트됨


iOS Advanced Features


제안된 편집은 API 참조 페이지에서 제한됩니다.

Markdown 본문 콘텐츠에 대한 편집만 제안할 수 있지만 API 사양에는 제안할 수 없습니다.


필터