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
<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">
<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
<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">
<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
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.initSession().then(function(data) {
if (data["+clicked_branch_link"]) {
alert("Deep Link Data: " + JSON.stringify(data));
}
});
}
};
app.initialize();
-
Ionic 1
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();
}
$ionicPlatform.on("deviceready", function() {
branchInit();
});
$ionicPlatform.on("resume", function() {
branchInit();
});
function branchInit() {
Branch.initSession().then(function(data) {
if (data["+clicked_branch_link"]) {
alert("Deep Link Data: " + JSON.stringify(data));
}
});
}
});
});
-
Ionic 2/3
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();
});
const branchInit = () => {
if (!platform.is("cordova")) {
return;
}
const Branch = window["Branch"];
Branch.initSession().then(data => {
if (data["+clicked_branch_link"]) {
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
Branch.setDebug(true);
Branch.disabledTracking(false);
Branch.setCookieBasedMatching("cordova.app.link");
Branch.initSession().then(function(data) {
if (data["+clicked_branch_link"]) {
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
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
}
};
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
-
All function's parameters are mandatory
var analytics = {
channel: "facebook",
feature: "onboarding",
campaign: "content 123 launch",
stage: "new user",
tags: ["one", "two", "three"]
};
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
-
All function's parameters are mandatory
var analytics = {
channel: "facebook",
feature: "onboarding",
campaign: "content 123 launch",
stage: "new user",
tags: ["one", "two", "three"]
};
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";
branchUniversalObj.onShareSheetLaunched(function(res) {
console.log(res);
});
branchUniversalObj.onShareSheetDismissed(function(res) {
console.log(res);
});
branchUniversalObj.onLinkShareResponse(function(res) {
console.log(res);
});
branchUniversalObj.onChannelSelected(function(res) {
console.log(res);
});
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.initSession()
.then(function success(res) {
if (res["+clicked_branch_link"]) {
alert("Open app with a Branch deep link: " + JSON.stringify(res));
} else if (res["+non_branch_link"]) {
alert("Open app with a non Branch deep link: " + JSON.stringify(res));
} else {
alert("Open app organically");
}
})
.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
var event = {
revenue: 50.29,
currency: 148,
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,
variant: "variant"
},
{
sku: "u456",
name: "grass",
price: 0.0,
quantity: 1
}
]
};
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
<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">
<plugin name="branch-cordova-sdk" spec="~2.4.2" />
<branch-config>
<branch-key value="key_live_ndqptlgXNE4LHqIahH1WIpbiyFlb62J3" />
<uri-scheme value="branchcordova" />
<link-domain value="yourcustomdomain.com" />
<link-domain value="cordova.app.link" />
<link-domain value="bnc.lt" />
<ios-team-release value="PW4Q8885U7" />
<ios-team-debug value="FG35JLLMXX" />
<android-prefix value="/WSuf" />
<android-testmode value="true" />
</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
-
Testing: Sample Testing App
-
Link Data: Universal Object Properties
-
Link Data: Deep Link Properties
-
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
-
Compiling: Cordova Dependencies
-
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
-
Android Genymotion
-
Compiling: Updating the Branch SDK
cordova plugin remove io.branch.sdk
cordova plugin remove branch-cordova-sdk
<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
-
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