🔥 Branch deep links help mobile apps grow. Use our deep links to navigate from web to app, display content within your app, track users, track events, and track attribution.
Objective-C JavaScript Java HTML Shell C CSS
Latest commit ed40bb2 Aug 10, 2018

README.md

Branch for Cordova/PhoneGap/Ionic

Travis npm downloads npm version npm version

URLs can navigate to your website, but not to your app. Branch fixes this with deep links.

Branch will grow your app by allowing users to install, open, and navigate to content inside your app.

Increase discovery of your app by sharing its content, converting web users to app users, enabling user-to-user sharing, personalizing user experiences, tracking users, tracking referrals, tracking campaigns, tracking conversions, and increasing overall engagement.

Branch for Cordova, PhoneGap, and Ionic

Questions? Contact us

Getting Started

  • Configure Branch

  • Configure App

    • Cordova and Ionic

      <!-- sample config.xml -->
      <widget id="com.eneff.branch.cordovatestbed" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
        <!-- Branch -->
        <plugin name="branch-cordova-sdk" spec="^2.6.0" />
        <branch-config>
          <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
          <uri-scheme value="branchcordova" />
          <link-domain value="cordova.app.link" />
          <ios-team-release value="PW4Q8885U7" />
        </branch-config>
    • PhoneGap

      <!-- sample config.xml -->
      <widget id="com.eneff.branch.cordovatestbed" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
        <!-- Branch -->
        <plugin name="branch-cordova-sdk" spec="^2.6.0" />
        <branch-config>
          <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
          <uri-scheme value="branchcordova" />
          <link-domain value="cordova.app.link" />
          <ios-team-release value="PW4Q8885U7" />
        </branch-config>
    • Change the following values to match your Branch Dashboard

      • com.eneff.branch.cordovatestbed
      • key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3
      • branchcordova
      • cordova.app.link
      • PW4Q8885U7
  • Initialize Branch

    • Cordova and PhoneGap

      // sample index.js
      var app = {
        initialize: function() {
          app.bindEvents();
        },
        bindEvents: function() {
          document.addEventListener("deviceready", app.onDeviceReady, false);
          document.addEventListener("resume", app.onDeviceResume, false);
        },
        onDeviceReady: function() {
          app.branchInit();
        },
        onDeviceResume: function() {
          app.branchInit();
        },
        branchInit: function() {
          // Branch initialization
          Branch.initSession().then(function(data) {
            if (data["+clicked_branch_link"]) {
              // read deep link data on click
              alert("Deep Link Data: " + JSON.stringify(data));
            }
          });
        }
      };
      
      app.initialize();
    • Ionic 1

      // sample app.js
      angular
        .module("starter", ["ionic", "starter.controllers", "starter.services"])
      
        .run(function($ionicPlatform) {
          $ionicPlatform.ready(function() {
            if (
              window.cordova &&
              window.cordova.plugins &&
              window.cordova.plugins.Keyboard
            ) {
              cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
              cordova.plugins.Keyboard.disableScroll(true);
            }
            if (window.StatusBar) {
              StatusBar.styleDefault();
            }
      
            // Branch
            $ionicPlatform.on("deviceready", function() {
              branchInit();
            });
      
            $ionicPlatform.on("resume", function() {
              branchInit();
            });
      
            function branchInit() {
              // Branch initialization
              Branch.initSession().then(function(data) {
                if (data["+clicked_branch_link"]) {
                  // read deep link data on click
                  alert("Deep Link Data: " + JSON.stringify(data));
                }
              });
            }
          });
        });
      // ...
    • Ionic 2/3

      // sample app.component.js
      import { Component } from "@angular/core";
      import { Platform } from "ionic-angular";
      import { StatusBar, Splashscreen } from "ionic-native";
      
      import { TabsPage } from "../pages/tabs/tabs";
      
      @Component({
        template: `<ion-nav [root]="rootPage"></ion-nav>`
      })
      export class MyApp {
        rootPage = TabsPage;
      
        constructor(platform: Platform) {
          platform.ready().then(() => {
            StatusBar.styleDefault();
            Splashscreen.hide();
            branchInit();
          });
      
          platform.resume.subscribe(() => {
            branchInit();
          });
      
          // Branch initialization
          const branchInit = () => {
            // only on devices
            if (!platform.is("cordova")) {
              return;
            }
            const Branch = window["Branch"];
            Branch.initSession().then(data => {
              if (data["+clicked_branch_link"]) {
                // read deep link data on click
                alert("Deep Link Data: " + JSON.stringify(data));
              }
            });
          };
        }
      }
  • Test Deep Link iOS

    • Create a deep link from the Branch Marketing Dashboard

    • Delete your app from the device

    • Compile your app (cordova run ios phonegap run ios ionic cordova run ios)

    • Paste deep link in Apple Notes

    • Long press on the deep link (not 3D Touch)

    • Click Open in "APP_NAME" to open your app (example)

  • Test Deep Link Android

    • Create a deep link from the Branch Marketing Dashboard

    • Delete your app from the device

    • Compile your app (cordova run android phonegap run android ionic cordova run android)

    • Paste deep link in Google Hangouts

    • Click on the deep link to open your app

Features

  • Initialize Branch Features

    • Loads Branch into your app

    • Must be called on deviceready and resume

      // for development and debugging only
      Branch.setDebug(true);
      
      // for GDPR compliance (can be called at anytime)
      Branch.disabledTracking(false);
      
      // for better Android matching
      Branch.setCookieBasedMatching("cordova.app.link");
      
      // Branch initialization
      Branch.initSession().then(function(data) {
        if (data["+clicked_branch_link"]) {
          // read deep link data on click
          alert("Deep Link Data: " + JSON.stringify(data));
        }
      });
  • Create Content Reference

    • The Branch Universal Object encapsulates the thing you want to share (content or user)

    • Link Data: Universal Object Properties

      // only canonicalIdentifier is required
      var properties = {
        canonicalIdentifier: "content/123",
        canonicalUrl: "https://example.com/content/123",
        title: "Content 123 Title",
        contentDescription: "Content 123 Description " + Date.now(),
        contentImageUrl: "http://lorempixel.com/400/400/",
        price: 12.12,
        currency: "GBD",
        contentIndexingMode: "private",
        contentMetadata: {
          custom: "data",
          testing: 123,
          this_is: true
        }
      };
      
      // create a branchUniversalObj variable to reference with other Branch methods
      var branchUniversalObj = null;
      Branch.createBranchUniversalObject(properties)
        .then(function(res) {
          branchUniversalObj = res;
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
  • Create Deep Link

    • Creates a deep link URL with encapsulated data

    • Needs a Branch Universal Object

    • Link Data: Deep Link Properties

    • Verify on the Branch Dashboard

      // optional fields
      var analytics = {
        channel: "facebook",
        feature: "onboarding",
        campaign: "content 123 launch",
        stage: "new user",
        tags: ["one", "two", "three"]
      };
      
      // optional fields
      var properties = {
        $desktop_url: "http://www.example.com/desktop",
        $android_url: "http://www.example.com/android",
        $ios_url: "http://www.example.com/ios",
        $ipad_url: "http://www.example.com/ipad",
        $deeplink_path: "content/123",
        $match_duration: 2000,
        custom_string: "data",
        custom_integer: Date.now(),
        custom_boolean: true
      };
      
      branchUniversalObj
        .generateShortUrl(analytics, properties)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res.url));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
  • Share Deep Link

    • Will generate a Branch deep link and tag it with the channel the user selects

    • Needs a Branch Universal Object

    • Link Data: Deep Link Properties

      // optional fields
      var analytics = {
        channel: "facebook",
        feature: "onboarding",
        campaign: "content 123 launch",
        stage: "new user",
        tags: ["one", "two", "three"]
      };
      
      // optional fields
      var properties = {
        $desktop_url: "http://www.example.com/desktop",
        custom_string: "data",
        custom_integer: Date.now(),
        custom_boolean: true
      };
      
      var message = "Check out this link";
      
      // optional listeners (must be called before showShareSheet)
      branchUniversalObj.onShareSheetLaunched(function(res) {
        // android only
        console.log(res);
      });
      branchUniversalObj.onShareSheetDismissed(function(res) {
        console.log(res);
      });
      branchUniversalObj.onLinkShareResponse(function(res) {
        console.log(res);
      });
      branchUniversalObj.onChannelSelected(function(res) {
        // android only
        console.log(res);
      });
      
      // share sheet
      branchUniversalObj.showShareSheet(analytics, properties, message);
  • Read Deep Link

    • Retrieve Branch data from a deep link

    • Best practice to receive data from the listener

    • Listener

      // Branch initialization within your deviceready and resume
      Branch.initSession()
        .then(function success(res) {
          if (res["+clicked_branch_link"]) {
            alert("Open app with a Branch deep link: " + JSON.stringify(res));
            // Branch quick link: https://cordova.app.link/uJcOH1IFpM
            // Branch web link: https://cordova-alternate.app.link/uJcOH1IFpM
            // Branch dynamic link: https://cordova.app.link?tags=one&tags=two&tags=three&channel=Copy&feature=onboarding&stage=new+user&campaign=content+123+launch&type=0&duration=0&source=android&data
            // Branch uri scheme: branchcordova://open?link_click_id=link-500015444967786346
            // Branch android intent: intent://open?link_click_id=518106399270344237#Intent;scheme=looprocks;package=com.eneff.branch.cordovatestbed;S.browser_fallback_url=https%3A%2F%2Fcordova.app.link%2FuJcOH1IFpM%3F__branch_flow_type%3Dchrome_deepview%26__branch_flow_id%3D518106399312287278;S.market_referrer=link_click_id-518106399270344237%26utm_source%3DCopy%26utm_campaign%3Dcontent%20123%20launch%26utm_feature%3Donboarding;S.branch_data=%7B%22~feature%22%3A%22onboarding%22%2C%22this_is%22%3A%22true%22%2C%22custom_string%22%3A%22data%22%2C%22testing%22%3A%22123%22%2C%22%24publicly_indexable%22%3A%22false%22%2C%22%24desktop_url%22%3A%22http%3A%2F%2Fwww.example.com%2Fdesktop%22%2C%22%24one_time_use%22%3Afalse%2C%22custom_object%22%3A%22%7B%5C%5C%5C%22random%5C%5C%5C%22%3A%5C%5C%5C%22dictionary%5C%5C%5C%22%7D%22%2C%22~id%22%3A%22517795540654792902%22%2C%22~campaign%22%3A%22content%20123%20launch%22%2C%22%2Bclick_timestamp%22%3A1524764418%2C%22%2Burl%22%3A%22https%3A%2F%2Fcordova.app.link%2FuJcOH1IFpM%22%2C%22custom_boolean%22%3A%22true%22%2C%22custom%22%3A%22data%22%2C%22source%22%3A%22android%22%2C%22%24og_image_url%22%3A%22http%3A%2F%2Florempixel.com%2F400%2F400%2F%22%2C%22%2Bdomain%22%3A%22cordova.app.link%22%2C%22custom_integer%22%3A%221524690301794%22%2C%22~tags%22%3A%5B%22one%22%2C%22two%22%2C%22three%22%5D%2C%22custom_array%22%3A%22%5B1%2C2%2C3%2C4%2C5%5D%22%2C%22~channel%22%3A%22Copy%22%2C%22~creation_source%22%3A2%2C%22%24canonical_identifier%22%3A%22content%2F123%22%2C%22%24og_title%22%3A%22Content%20123%20Title%22%2C%22%24og_description%22%3A%22Content%20123%20Description%201524690296449%22%2C%22%24identity_id%22%3A%22453670943617990547%22%2C%22~stage%22%3A%22new%20user%22%2C%22%2Bclicked_branch_link%22%3Atrue%2C%22%2Bmatch_guaranteed%22%3Atrue%2C%22%2Bis_first_session%22%3Afalse%7D;B.branch_intent=true;end
            // Branch android app link (device controlled): https://cordova.app.link/uJcOH1IFpM
            // Branch ios universal link (device controlled): https://cordova.app.link/uJcOH1IFpM
          } else if (res["+non_branch_link"]) {
            alert("Open app with a non Branch deep link: " + JSON.stringify(res));
            // Competitor uri scheme: anotherurischeme://hello=world
          } else {
            alert("Open app organically");
            // Clicking on app icon or push notification
          }
        })
        .catch(function error(err) {
          logger(err, true);
        });
    • First data

      Branch.getFirstReferringParams()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
    • Latest data

      Branch.getLatestReferringParams()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
  • Display Content

    • List content on iOS Spotlight

    • Needs a Branch Universal Object

      branchUniversalObj
        .listOnSpotlight()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
  • Track Content

    • Track how many times a user views a particular piece of content

    • Needs a Branch Universal Object

    • Verify on the Branch Dashboard

      branchUniversalObj
        .registerView()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
  • Track User

    • Sets the identity of a user (email, ID, UUID, etc) for events, deep links, and referrals

    • Verify on the Branch Dashboard

      var userId = "123456";
      Branch.setIdentity(userId)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err.message));
        });
    • Removes the identity of a user

      Branch.logout()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err.message));
        });
  • Track Event

    • Registers a custom event

    • Events named open, close, install, and referred session are Branch restricted

    • Recommended to Track User before Track Event to associate custom events with a user

    • Verify on the Branch Dashboard

      var eventName = "clicked_on_this";
      var metadata = { custom_dictionary: 123, anything: "everything" };
      Branch.userCompletedAction(eventName, metadata)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err.message));
        });
      var eventName = "clicked_on_this";
      Branch.userCompletedAction(eventName)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err.message));
        });
  • Track Commerce

    • Registers a custom commerce event

    • Link Data: Track commerce properties for Currency and Category

    • Verify on the Branch Dashboard

      // only revenue is required
      var event = {
        revenue: 50.29,
        currency: 148, // USD
        transactionID: "transaction id",
        coupon: "coupon",
        shipping: 2.22,
        tax: 5.11,
        affiliation: "affiliation",
        products: [
          {
            sku: "u123",
            name: "cactus",
            price: 4.99,
            quantity: 2,
            brand: "brand",
            category: 17, // Software
            variant: "variant"
          },
          {
            sku: "u456",
            name: "grass",
            price: 0.0,
            quantity: 1
          }
        ]
      };
      
      // optional fields
      var metadata = {
        custom_dictionary: 123,
        anything: "everything"
      };
      
      Branch.sendCommerceEvent(event, metadata)
        .then(function(res) {
          console.log(res);
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          console.error(err);
          alert("Error: " + JSON.stringify(err.message));
        });
  • Handle Referrals

    • Referral points are obtained from events triggered by users from rules created on the Branch Dashboard

    • Verify on the Branch Dashboard

    • Get credits

    • Spend credits

      var amount = 10;
      var bucket = "this_bucket";
      Branch.redeemRewards(amount, bucket)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
      var amount = 10;
      Branch.redeemRewards(amount)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
    • Load credits

      var bucket = "this_bucket";
      Branch.loadRewards(bucket)
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
      Branch.loadRewards()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });
    • Load history

      Branch.creditHistory()
        .then(function(res) {
          alert("Response: " + JSON.stringify(res));
        })
        .catch(function(err) {
          alert("Error: " + JSON.stringify(err));
        });

Troubleshooting

  • Testing: Key Points

    • Need to select "app uses IDFA and GAID" when publishing your app

    • Best to enable Deepviews (Testing: Supported Platforms)

    • Mobile browser capability: Android 4.4.4+, Safari 8+, Chrome 32+, Firefox 29+

  • Testing: Optional App Config

    <!-- sample config.xml -->
    <widget id="com.eneff.branch.cordovatestbed" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
      <!-- Branch -->
      <plugin name="branch-cordova-sdk" spec="~2.4.2" /> <!-- optional spec -->
      <branch-config>
        <branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
        <uri-scheme value="branchcordova" />
        <link-domain value="yourcustomdomain.com" />
        <link-domain value="cordova.app.link" />  <!-- optional previous link domain -->
        <link-domain value="bnc.lt" />  <!-- optional previous link domain -->
        <ios-team-release value="PW4Q8885U7" /> <!-- required if iOS app -->
        <ios-team-debug value="FG35JLLMXX" /> <!-- optional -->
        <android-prefix value="/WSuf" /> <!-- optional (for bnc.lt link domains) -->
        <android-testmode value="true" /> <!-- optional (simulate installs) -->
      </branch-config>
    <widget ios-CFBundleIdentifier="com.eneff.branch.cordovatestbedios" android-packageName="com.eneff.branch.cordovatestbedandroid" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  • Testing: Branch Analytics

    • Whenever a user clicks on a deep link and opens the app, and will trigger either an install or an open

    • installs represent Branch recognizing the app_id and device_id for the first time

    • installs represent new app users and the success rate of your Branch deep links

    • installs do not represent App Store downloads

    • non-Branch installs are installs outside of Branch deep link clicks

    • opens are non-installs

    • If a user uninstalls and reinstalls the app, this will be an open because Branch recognizes the device

    • If a user has the app and clicks a Branch deep link, this will be an open because the user is not new

  • Testing: Simulating an Install

    • Delete your app

    • [iOS] iPhone Device -> Settings -> Privacy -> Advertising -> Reset Advertising Identifier -> Reset Identifier

    • [Android] Add <android-testmode value="true" /> to your Config.xml (Testing: Optional App Config)

    • Add Branch.setDebug(true); before Branch.initSession(); (Initialize Branch Features)

    • Click on a deep link to navigate to your $fallback_url because your app is not installed

    • Install your app

    • Open your app

    • Read from Branch.initSession(data) for +is_first_session = true

  • Testing: Supported Platforms

    • Apps which support Branch deep links

      iOS Details Android Details
      Facebook NewsFeed Works when DeepViews are enabled
      Facebook Messanger Works when DeepViews are enabled
      Twitter
      Pinterest Works when DeepViews are enabled
      Slack
      Chrome address bar 🅾️ 🅾️
      Chrome web page
      FireFox address bar 🅾️ 🅾️
      FireFox web page
      Safari address bar 🅾️
      Safari web page
      WeChat Works when DeepViews are enabled
      WhatsApp app.link requires https/http to be clickable app.link requires https/http to be clickable
      Hangouts
      iMessage
      Apple Mail
      Gmail
  • Testing: Sample Testing App

  • Link Data: Universal Object Properties

    • For Create Content Reference

    • Properties

      Key Default Usage Link Property
      canonicalIdentifier (Required) This is the unique identifier for content that will help Branch dedupe across many instances of the same thing. Suitable options: a website with pathing, or a database with identifiers for entities $canonical_identifier
      canonicalUrl The canonical URL, used for SEO purposes $canonical_url
      title The name for the piece of content $og_title
      contentDescription A description for the content $og_description
      contentImageUrl The image URL for the content. Must be an absolute path $og_image_url
      price The price of the item $amount
      currency The currency representing the price in ISO 4217 currency code $currency
      contentIndexingMode "public" Can be set to either "public" or "private". Public indicates that you’d like this content to be discovered by other apps. $publicly_indexable
      contentMetadata Any custom key-value data e.g. { "custom": "data" }
  • Link Data: Deep Link Properties

    • For Create Deep Link and Share Deep Link

    • Analytics

      Key Default Usage
      channel Use channel to tag the route that your link reaches users. For example, tag links with "Facebook" or "LinkedIn" to help track clicks and installs through those paths separately
      feature This is the feature of your app that the link might be associated with. For example, if you had built a referral program, you would label links with the feature ‘referral’
      campaign Use this field to organize the links by actual campaign. For example, if you launched a new feature or product and want to run a campaign around that
      stage Use this to categorize the progress or category of a user when the link was generated. For example, if you had an invite system accessible on level 1, level 3 and 5, you could differentiate links generated at each level with this parameter
      tags This is a free form entry with unlimited values ["string"]. Use it to organize your link data with labels that don’t fit within the bounds of the above
      alias Specify a link alias in place of the standard encoded short URL e.g. yourdomain.com/youralias. Link aliases are unique, immutable objects that cannot be deleted. You cannot change the alias of existing links. Aliases on the legacy bnc.lt domain are incompatible with Universal Links and Spotlight
      type 0 Set to 1 to limit deep linking behavior of the generated link to a single use. Set type to 2 to make the link show up under Marketing Dashboard while adding $marketing_title to data. Must be an int. Does not work with the Cordova SDK (limitation of native SDKs)
    • Properties

      • Custom Data

        Key Value Usage
        random 123 Any key-value pair
        hello "world" Any key-value pair
        custom_data true Any key-value pair
      • Redirection

        Key Default Usage
        $fallback_url Change the redirect endpoint for all platforms - so you don’t have to enable it by platform. Note that Branch will forward all robots to this URL, which overrides any OG tags entered in the link. System-wide Default URL (set in Link Settings)
        $desktop_url Change the redirect endpoint on desktops Text-Me-The-App page (set in Link Settings)
        $ios_url Change the redirect endpoint for iOS App Store page for your app (set in Link Settings)
        $ipad_url Change the redirect endpoint for iPads $ios_url value
        $android_url Change the redirect endpoint for Android Play Store page for your app (set in Link Settings)
        $windows_phone_url Change the redirect endpoint for Windows OS Windows Phone default URL (set in Link Settings)
        $blackberry_url Change the redirect endpoint for Blackberry OS BlackBerry default URL (set in Link Settings)
        $fire_url Change the redirect endpoint for Amazon Fire OS Fire default URL (set in Link Settings)
        $ios_wechat_url Change the redirect endpoint for WeChat on iOS devices $ios_url value
        $android_wechat_url Change the redirect endpoint for WeChat on Android devices $android_url value
        $after_click_url URL redirect to after the main click redirect has completed
        $web_only false Force to open the $fallback_url instead of the app
      • Deep Link

        Key Default Usage
        $deeplink_path open?link_click_id=1234 Set the deep link path for all platforms - so you don’t have to enable it by platform. When the Branch SDK receives a link with this parameter set, it will automatically load the custom URI path contained within
        $android_deeplink_path Set the deep link path for Android apps When the Branch SDK receives a link with this parameter set, it will automatically load the custom URI path contained within
        $ios_deeplink_path Set the deep link path for iOS apps. When the Branch SDK receives a link with this parameter set, it will automatically load the custom URI path contained within
        $match_duration 7200 Lets you control the fingerprinting match timeout (the time that a click will wait for an app open to match) also known as attribution window. Specified in seconds
        $always_deeplink true Set to false to make links always fall back to your mobile site. Does not apply to Universal Links or Android App Links.
        $ios_redirect_timeout 750 Control the timeout that the client-side JS waits after trying to open up the app before redirecting to the App Store. Specified in milliseconds
        $android_redirect_timeout 750 Control the timeout that the clientside JS waits after trying to open up the app before redirecting to the Play Store. Specified in milliseconds
        $one_time_use false Set to true to limit deep linking behavior of the generated link to a single use. Can also be set using type
        $custom_sms_text Text for SMS link sent for desktop clicks to this link. Must contain {{ link }} Value of Text me the app page in Settings
        $marketing_title The Marketing Title for the deep link in the Marketing Dashboard
      • Content

        Key Default Usage
        $publicly_indexable 1 Cannot modify here. Needs to be set by the Branch Universal Object
        $keywords Keywords for which this content should be discovered by. Just assign an array of strings with the keywords you’d like to use
        $canonical_identifier This is the unique identifier for content that will help Branch dedupe across many instances of the same thing. Suitable options: a website with pathing, or a database with identifiers for entities
        $exp_date 0 Cannot modify here. Needs to be set by the Branch Universal Object. Must be epoch timestamp with milliseconds
        $content_type This is a label for the type of content present. Apple recommends that you use uniform type identifier as described here
      • DeepView

        Key Default Usage
        $ios_deepview default_template The name of the deepview template to use for iOS
        $android_deepview default_template The name of the deepview template to use for Android
        $desktop_deepview default_template The name of the deepview template to use for the Desktop
      • Open Graph

        Key Default Usage
        $og_title Set the title of the link as it will be seen in social media displays
        $og_description Set the description of the link as it will be seen in social media displays
        $og_image_url Set the image of the link as it will be seen in social media displays
        $og_image_width Set the image’s width in pixels for social media displays
        $og_image_height Set the image’s height in pixels for social media displays
        $og_video Set a video as it will be seen in social media displays
        $og_url Set the base URL of the link as it will be seen in social media displays
        $og_type Set the type of custom card format link as it will be seen in social media displays
        $og_redirect (Advanced, not recommended) Set a custom URL that we redirect the social media robots to in order to retrieve all the appropriate tags
        $og_app_id (Rarely used) Sets the app id tag
      • Twitter

        Key Default Usage
        $twitter_card Set the Twitter card type of the link
        $twitter_title Set the title of the Twitter card
        $twitter_description Set the description of the Twitter card
        $twitter_image_url Set the image URL for the Twitter card
        $twitter_site Set the site for Twitter
        $twitter_app_country Set the app country for the app card
        $twitter_player Set the video player’s URL. Defaults to the value of $og_video.
        $twitter_player_width Set the player’s width in pixels
        $twitter_player_height Set the player’s height in pixels
  • Link Data: Commerce Properties

    • For Track Commerce

    • Categories

      Value Category
      0 Animals & Pet Supplies
      1 Apparel & Accessories
      2 Arts & Entertainment
      3 Baby & Toddler
      4 Business & Industrial
      5 Camera & Optics
      6 Electronics
      7 Food, Beverage & Tobacco
      8 Furniture
      9 Hardware
      10 Health & Beauty
      11 Home & Garden
      12 Luggage & Bags
      13 Mature
      14 Media
      15 Office Supplies
      16 Religious & Ceremonial
      17 Software
      18 Sporting Goods
      19 Toys & Games
      20 Vehicles & Parts
    • Currencies

      Value Currency
      0 AED
      1 AFN
      2 ALL
      3 AMD
      4 ANG
      5 AOA
      6 ARS
      7 AUD
      8 AWG
      9 AZN
      10 BAM
      11 BBD
      12 BDT
      13 BGN
      14 BHD
      15 BIF
      16 BMD
      17 BND
      18 BOB
      19 BOV
      20 BRL
      21 BSD
      22 BTN
      23 BWP
      24 BYN
      25 BYR
      26 BZD
      27 CAD
      28 CDF
      29 CHE
      30 CHF
      31 CHW
      32 CLF
      33 CLP
      34 CNY
      35 COP
      36 COU
      37 CRC
      38 CUC
      39 CUP
      40 CVE
      41 CZK
      42 DJF
      43 DKK
      44 DOP
      45 DZD
      46 EGP
      47 ERN
      48 ETB
      49 EUR
      50 FJD
      51 FKP
      52 GBP
      53 GEL
      54 GHS
      55 GIP
      56 GMD
      57 GNF
      58 GTQ
      59 GYD
      60 HKD
      61 HNL
      62 HRK
      63 HTG
      64 HUF
      65 IDR
      66 ILS
      67 INR
      68 IQD
      69 IRR
      70 ISK
      71 JMD
      72 JOD
      73 JPY
      74 KES
      75 KGS
      76 KHR
      77 KMF
      78 KPW
      79 KRW
      80 KWD
      81 KYD
      82 KZT
      83 LAK
      84 LBP
      85 LKR
      86 LRD
      87 LSL
      88 LYD
      89 MAD
      90 MDL
      91 MGA
      92 MKD
      93 MMK
      94 MNT
      95 MOP
      96 MRO
      97 MUR
      98 MVR
      99 MWK
      100 MXN
      101 MXV
      102 MYR
      103 MZN
      104 NAD
      105 NGN
      106 NIO
      107 NOK
      108 NPR
      109 NZD
      110 OMR
      111 PAB
      112 PEN
      113 PGK
      114 PHP
      115 PKR
      116 PLN
      117 PYG
      118 QAR
      119 RON
      120 RSD
      121 RUB
      122 RWF
      123 SAR
      124 SBD
      125 SCR
      126 SDG
      127 SEK
      128 SGD
      129 SHP
      130 SLL
      131 SOS
      132 SRD
      133 SSP
      134 STD
      135 SYP
      136 SZL
      137 THB
      138 TJS
      139 TMT
      140 TND
      141 TOP
      142 TRY
      143 TTD
      144 TWD
      145 TZS
      146 UAH
      147 UGX
      148 USD
      149 USN
      150 UYI
      151 UYU
      152 UZS
      153 VEF
      154 VND
      155 VUV
      156 WST
      157 XAF
      158 XAG
      159 XAU
      160 XBA
      161 XBB
      162 XBC
      163 XBD
      164 XCD
      165 XDR
      166 XFU
      167 XOF
      168 XPD
      169 XPF
      170 XPT
      171 XSU
      172 XTS
      173 XUA
      174 XXX
      175 YER
      176 ZAR
      177 ZMW
  • Link data: Mixpanel Integration

    • Sync with Mixpanel if plugin is installed

      Branch.setRequestMetadata("$mixpanel_distinct_id", "123");
  • Compiling: Cordova Dependencies

    • Node

      /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)";
      brew update;
      brew install node;
    • Xcode

      • Install Xcode

      • Open Xcode -> agree to SDK license agreement

      • Open Xcode -> Create new Xcode project -> Run simulator -> Agree to developer mode on mac

    • Android Studio

      • Read instructions

      • Install JVM

      • Install Android Studio

      • Open Android Studio -> configure -> appearance/system settings/android sdk -> android 6.0 -> Okay

      • Open Android Studio -> New project -> ... -> Run -> Create new emulator -> Nexus 6p 23 -> Finish

        # add to ~/.bash_profile
        export ANDROID_HOME=$HOME/Library/Android/sdk
        export PATH=$ANDROID_HOME/tools:$PATH
        export PATH=$ANDROID_HOME/platform-tools:$PATH
        source ~/.bash_profile;
        android update sdk;
      • Install Android SDK build-tools 24.0.1

      • Generate Android Keystore

        keytool -genkeypair -dname "cn=Full Name, ou=Business Unit, o=Company, c=US" -alias release -keypass aaa111 -keystore release.keystore -storepass aaa111 -validity 10000
        keytool -list -v -keystore release.keystore
    • Genymotion [optional]

      • Install Virtual Box

      • Install Genymotion

      • Genymotion -> Add virtual device -> Google Nexus 6P - 6.0.0 - API 23 -> Next

  • Compiling: Show Console Logs

    • iOS Simulator

      • cordova run ios;

      • Safari -> Preferences -> Advance -> Show Develop menu in menu bar

      • Safari -> Develop -> Simulator -> index.html -> Console

      • May need to unplug and replug device

      • May need to open Xcode and update provisioning profile

    • iOS Xcode

      • cordova plugin add cordova-plugin-console;

      • cordova build ios;

      • Xcode -> APP_LOCATION/platforms/ios/APP_NAME.Xcodeproj

      • Xcode -> App -> General -> Signing -> Team

      • Xcode -> Product -> Run

      • Xcode -> View -> Debug Area -> Activate Console

    • Android Device

      • Plug device in

      • cordova run android;

      • Chrome -> chrome://inspect/#devices -> Console

    • Android Genymotion

      • Genymotion -> Start

      • cordova run android;

      • Chrome -> chrome://inspect/#devices -> Console

  • Compiling: Updating the Branch SDK

    # terminal
    cordova plugin remove io.branch.sdk
    cordova plugin remove branch-cordova-sdk
    <!-- config.xml -->
    <plugin name="branch-cordova-sdk" spec="^2.6.0" />
  • Compiling: Incompatible Plugins

  • Compiling: Errors

    • Migrating Branch Cordova SDK from v2.5+ to v3.0+
      // Branch initialization
      - Branch.initSession(function(data) {
      + Branch.initSession().then(function(data) {
        if (data["+clicked_branch_link"]) {
          // read deep link data on click
          alert("Deep Link Data: " + JSON.stringify(data));
        }
      });
    • error

      ORIGINAL EXCEPTION: Branch is not defined
      ReferenceError: Branch is not defined
      • Branch opens and installs your app. You cannot simulate Branch in the desktop browser

        // Ionic 2/3 - running on browser instead of device
        if (!platform.is("cordova")) {
          return;
        }
        Branch.userCompletedAction("did_this");
        // Ionic 2/3 - missing Branch import
        declare var Branch;
    • error

      ** ARCHIVE FAILED **
      
      The following build commands failed:
        Check dependencies
      (1 failure)
      Error: Error code 65 for command: xcodebuild with args: -xcconfig,cordova/build-debug.xcconfig,-workspace,Branch Testing.xcworkspace,-scheme,Branch Testing,-configuration,Debug,-destination,generic/platform=iOS,-archivePath,Branch Testing.xcarchive,archive,CONFIGURATION_BUILD_DIR=build/device,SHARED_PRECOMPS_DIR=build/sharedpch
      • Open app in Xcode and launch from there (to select a Provisioning Profile)
    • error

      An invalid value 'XC com eneff branch cordova_testbed' was provided for the parameter 'appIdName'.
      No profiles for 'com.eneff.branch.cordova_testbed' were found
      • Don't use cordova, hyphens (Android), or underscores (iOS) in your bundle id (widget id)
      Error: Error code 1 for command: /gradlew with args: cdvBuildDebug,-b,/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true
      • Add <preference name="android-minSdkVersion" value="16" /> to your config.xml