mParticle Android
Integrate Branch¶
This documentation explains how to send mParticle events to your Branch dashboard. If you'd like to send Branch installs to your mParticle dashboard, please review the Branch/mParticle Data Integration.
These instructions apply to any integration below mParticle SDK version 5
mParticle introduced a new attribution & deep linking API in v5 of their SDK (http://docs.mparticle.com/developers/sdk/android/getting-started/#upgrade-to-version-5-of-the-sdk), so please contact your Branch or mParticle Account Managers for more details, if you have mParticle SDK v5+ installed in your app.
-
Configure Branch¶
-
Complete your Branch Dashboard
-
-
Install Branch¶
-
Import the Branch SDK to your
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.eneff.branchandroid" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.2.0' compile 'com.android.support:design:25.2.0' compile 'com.mparticle:android-core:4.+' compile 'com.mparticle:android-branch-kit:4+' }
-
-
Enable Branch on mParticle¶
- Retrieve your Branch Key on the App Settings page of the Branch dashboard.
- From your mParticle dashboard navigate to the Services page. (The paper airplane icon on the left side)
- Scroll down to the Branch tile, or enter Branch in the search bar.
- Click on the Branch tile and then select "Activate a Platform".
- Click on the Android icon, then toggle the status ON.
- Enter your Branch key in the marked field and click "Save".
-
Configure app¶
-
Add Branch to your
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.eneff.branchandroid"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:name="com.eneff.branchandroid.CustomApplicationClass" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:launchMode="singleTask" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- Branch URI Scheme --> <intent-filter> <data android:scheme="branchandroid" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> <!-- Branch App Links (optional) --> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="uobg.app.link" /> </intent-filter> </activity> </application> </manifest>
-
Replace the following with values from your Branch Dashboard
branchandroid
uobg.app.link
-
-
Handle Incoming Links¶
Open the
Activity
for which you registered theIntent Filter
in the previous section, and hook into theonStart
lifecycle method by adding this override:@Override public void onStart() { MParticle.getInstance().checkForDeepLink(new DeepLinkListener() { @Override public void onResult(DeepLinkResult result) { // Check for the existence of a given key in the link data and route accordingly. try { if ((result.getParameters().has("my_custom_key")) && (result.getParameters().get("my_custom_key").equals("custom value"))) { // Send user to intended path } } catch (JSONException e) { } } @Override public void onError(DeepLinkError error) { // If an error occurred, it will be surfaced via a DeepLinkError. Log.d("my log tag", error.toString()); } }); }
-
Initialize Branch¶
As with any kit, mParticle will automatically handle initializing Branch sessions. However, to ensure all possible use cases are accounted for, ensure MParticle.start() is called in your Application class (this should already be accounted for in your base mParticle integration). At this point you should start seeing your Branch session data - including installs, re-opens, and any custom events - in your Branch dashboard.
-
Test deep link¶
-
Create a deep link from the Branch Dashboard
-
Delete your app from the device
-
Compile your app to your device
-
Paste deep link in
Google Hangouts
-
Click on the deep link to open your app
-
Implement features¶
-
Create content reference¶
BranchUniversalObject branchUniversalObject = new BranchUniversalObject() // The identifier is what Branch will use to de-dupe the content across many different Universal Objects .setCanonicalIdentifier("item/12345") // The canonical URL for SEO purposes (optional) .setCanonicalUrl("https://branch.io/deepviews") // This is where you define the open graph structure and how the object will appear on Facebook or in a deepview .setTitle("My Content Title") .setContentDescription("My Content Description") .setContentImageUrl("https://example.com/mycontent-12345.png") // You use this to specify whether this content can be discovered publicly - default is public .setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC) // Here is where you can add custom keys/values to the deep link data .setContentMetadata(new ContentMetadata().addCustomMetadata("property1", "blue") .addCustomMetadata("property2", "red"));
-
Create deep link¶
LinkProperties linkProperties = new LinkProperties() .setChannel("facebook") .setFeature("sharing") .addControlParameter("$desktop_url", "http://example.com/home") .addControlParameter("$ios_url", "http://example.com/ios"); branchUniversalObject.generateShortUrl(this, linkProperties, new BranchLinkCreateListener() { @Override public void onLinkCreate(String url, BranchError error) { if (error == null) { Log.i("MyApp", "got my Branch link to share: " + url); } } });
-
Share deep link¶
ShareSheetStyle shareSheetStyle = new ShareSheetStyle(MainActivity.this, "Check this out!", "This stuff is awesome: ") .setCopyUrlStyle(getResources().getDrawable(android.R.drawable.ic_menu_send), "Copy", "Added to clipboard") .setMoreOptionStyle(getResources().getDrawable(android.R.drawable.ic_menu_search), "Show more") .addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK) .addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL) .setAsFullWidthStyle(true) .setSharingTitle("Share With"); branchUniversalObject.showShareSheet(this, linkProperties, shareSheetStyle, new Branch.BranchLinkShareListener() { @Override public void onShareLinkDialogLaunched() { } @Override public void onShareLinkDialogDismissed() { } @Override public void onLinkShareResponse(String sharedLink, String sharedChannel, BranchError error) { } @Override public void onChannelSelected(String channelName) { } });
-
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
@Override public void onStart() { MParticle.getInstance().checkForDeepLink(new DeepLinkListener() { @Override public void onResult(DeepLinkResult result) { try { Log.d("BRANCH SDK", result.getParameters.toString()); } catch (JSONException e) { } } @Override public void onError(DeepLinkError error) { // If an error occurred, it will be surfaced via a DeepLinkError. Log.d("BRANCH SDK", error.toString()); } }); }
-
-
Navigate to content¶
-
Do stuff with the Branch deep link data.
@Override public void onStart() { MParticle.getInstance().checkForDeepLink(new DeepLinkListener() { @Override public void onResult(DeepLinkResult result) { try { JSONObject referringParams = result.getParameters(); // Option 1: Log data Log.i("BRANCH SDK", referringParams.toString()); // Option 2: Save data to be used later SharedPreferences preferences = .getSharedPreferences("MyPreferences", Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); editor.putString("branchData", referringParams.toString(2)); editor.commit(); // Option 3: Navigate to page Intent intent = new Intent(MainActivity.this, OtherActivity.class); intent.putExtra("branchData", referringParams.toString(2)); startActivity(intent); // Option 4: Display data Toast.makeText(this, referringParams.toString(2), Toast.LENGTH_LONG).show(); } catch (JSONException e) { } } @Override public void onError(DeepLinkError error) { // If an error occurred, it will be surfaced via a DeepLinkError. Log.d("BRANCH SDK", error.toString()); } }); }
-
-
Display content¶
-
List content on
Google Search
withApp Indexing
-
Enable App Indexing on the Branch Dashboard
-
Validate with the App indexing validator
-
Needs a Branch Universal Object
-
Needs
build.gradle
librarycompile 'com.google.android.gms:play-services-appindexing:9.+'
-
Call method on Branch Universal Object
buo.listOnGoogleSearch(this);
-
-
Track content¶
-
Track how many times a piece of content is viewed
-
Needs a Branch Universal Object
-
Validate with the Branch Dashboard
buo.userCompletedAction(BranchEvent.VIEW);
-
-
Track users¶
// Your user ID should not exceed 127 characters. // The IdentityType CustomerId will automatically propagate to Branch. MParticle.getInstance().setUserIdentity(MParticle.IdentityType.CustomerId, "your_user_id");
MParticle.getInstance().logout();
-
Track events¶
-
Registers a custom event
-
Events named
open
,close
,install
, andreferred session
are Branch restricted -
63
character max for event name -
Best to Track users before Track events to associate a custom event to a user
-
Validate with the Branch Dashboard
// Option 1: MParticle.logEvent("your_custom_event", MParticle.EventType.YourEventType); // Option 2: with metadata Map<String, String> metaData = new HashMap<>(); metaData.put("key", "value"); MParticle.logEvent("your_custom_event", MParticle.EventType.YourEventType, metaData);
-
-
Track commerce¶
-
Registers a custom commerce event
-
Uses Commerce properties for
Currency
-
Uses Commerce properties for
Category
-
Validate with the Branch Dashboard
-
Ensure to add
revenue
field to track purchase. All other fields are optional// Add details about each product associated with the purchase (optional) Product product1 = new Product(); product1.setSku("u123"); product1.setName("cactus"); product1.setPrice(45.00); product1.setQuantity(2); product1.setBrand("brand1"); product1.setCategory(ProductCategory.ELECTRONICS); product1.setVariant("variant1"); Product product2 = new Product(); product2.setSku("u456"); product2.setName("grass"); product2.setPrice(9.00); product2.setQuantity(1); product2.setBrand("brand2"); product2.setCategory(ProductCategory.CAMERA_AND_OPTICS); product2.setVariant("variant2"); // Create a list of products associated with the particular purchase (optional) List<Product> productList = new ArrayList<Product>(); productList.add(product1); productList.add(product2); // Create the commerce event (only revenue is required) CommerceEvent commerceEvent = new CommerceEvent(); commerceEvent.setRevenue(50.29); commerceEvent.setCurrencyType(CurrencyType.USD); commerceEvent.setTransactionID("TRANS-1111"); commerceEvent.setShipping(4.50); commerceEvent.setTax(110.90); commerceEvent.setAffiliation("AFF-ID-101"); commerceEvent.setProducts(productList); // Add metadata (optional) JSONObject metadata = new JSONObject(); try { metadata.put("custom_dictionary", 123); metadata.put("testVar", "abc"); } catch (Exception e) { e.printStackTrace(); } // Fire the commerce event by calling Branch directly. Branch.getInstance().sendCommerceEvent(commerceEvent, metadata, null);
-
-
Handle referrals¶
-
Referral points are obtained from referral rules on the Branch Dashboard
-
Validate on the Branch Dashboard
-
Reward credits
-
Redeem credits
Branch.getInstance().redeemRewards(5);
-
Load credits
Branch.getInstance().loadRewards(new BranchReferralStateChangedListener() { @Override public void onStateChanged(boolean changed, Branch.BranchError error) { int credits = branch.getCredits(); } });
-
Load history
Branch.getInstance().getCreditHistory(new BranchListResponseListener() { public void onReceivingResponse(JSONArray list, Branch.BranchError error) { if (error != null) { Log.i("BRANCH SDK", "Branch load rewards failed. Caused by -" + error.message) } else { Log.i("BRANCH SDK", list); } } });
-
Troubleshoot issues¶
-
Sample testing apps¶
-
Simulate an install¶
-
Need to bypass the device's hardware_id
-
Set
true
in yourAndroidManifest.xml
<meta-data android:name="io.branch.sdk.TestMode" android:value="true" />
-
Do not use
TestMode
in production or in the Google Play Store
-
-
Uninstall your app from the device
-
Click on any Branch deep link (will navigate to the fallback URL since the app is not installed)
-
Reinstall your app
-
Read deep link data from
MParticle.getInstance().checkForDeepLink()
for+is_first_session=true
-
-
Track content properties¶
-
Used for Track content
Key Value BNCRegisterViewEvent User viewed the object BNCAddToWishlistEvent User added the object to their wishlist BNCAddToCartEvent User added object to cart BNCPurchaseInitiatedEvent User started to check out BNCPurchasedEvent User purchased the item BNCShareInitiatedEvent User started to share the object BNCShareCompletedEvent User completed a share
-
-
Using bnc.lt or a custom link domain¶
-
bnc.lt link domain
<activity android:name="com.yourapp.your_activity"> <!-- App Link your activity to Branch links--> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="bnc.lt" android:pathPrefix="/LVeu" /> <data android:scheme="https" android:host="bnc.lt" android:pathPrefix="/eVeu" /> </intent-filter> </activity>
-
custom link domain
<activity android:name="com.yourapp.your_activity"> <!-- App Link your activity to Branch links--> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="your.app.com" android:pathPrefix="/LVeu" /> <data android:scheme="https" android:host="your.app.com" android:pathPrefix="/eVeu" /> </intent-filter> </activity>
-
Change the following values to match your Branch Dashboard
/LVeu
(live)/eVeu
(test)your.app.com
-
-
Generate signing certificate¶
-
Used for Android
App Link
deep linking -
Navigate to your keystore file
-
Run
keytool -list -v -keystore my-release-key.keystore
-
Will generate a value like
AA:C9:D9:A5:E9:76:3E:51:1B:FB:35:00:06:9B:56:AC:FB:A6:28:CE:F3:D6:65:38:18:E3:9C:63:94:FB:D2:C1
-
Copy this value to your Branch Dashboard
-
-
Enable multidexing¶
-
Adding additional dependencies may overrun the dex limit and lead to
NoClassDefFoundError
orClassNotFoundException
-
Add to your
build.gradle
defaultConfig { multiDexEnabled true }
-
Add to your
Application class
and make sure it extendsMultiDexApplication
-
Java
@Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); }
-
Kotlin
override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) MultiDex.install(this) }
-
-
InvalidClassException, ClassLoadingError or VerificationError¶
- Often caused by a
Proguard
bug. Try the latest Proguard version or disable Proguard optimization by setting-dontoptimize
- Often caused by a
-
Proguard warning or errors with AppIndexing module¶
- The Branch SDK has an optional dependency on Firebase app indexing classes to provide new Firebase content listing
features. This may cause a proguard warning depending on your proguard settings. Please add the following to your
proguard file to solve this issue
-dontwarn com.google.firebase.appindexing.**
.
- The Branch SDK has an optional dependency on Firebase app indexing classes to provide new Firebase content listing
features. This may cause a proguard warning depending on your proguard settings. Please add the following to your
proguard file to solve this issue
-
Unable to open this link error¶
- Happens whenever URI Scheme redirection fails.
- Make sure you do not have
$deeplink_path
or you have a$deeplink_path
which yourAndroidManifest.xml
can accept