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.

  • Configure Branch

  • 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
  • Open the Activity for which you registered the Intent Filter in the previous section, and hook into the onStart 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. At this point you should start seeing your Branch session data - including installs, re-opens, and any custom events - in your Branch dashboard.

    • 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"));
    
  • 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);
           }
        }
    });
    
  • 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) {
        }
    });
    
    • 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());
          }
        });
      }
      
    • 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 with App Indexing

    • Enable App Indexing on the Branch Dashboard

    • Validate with the App indexing validator

    • Needs a Branch Universal Object

    • Needs build.gradle library

      compile 'com.google.android.gms:play-services-appindexing:9.+'
      
    • Call method on Branch Universal Object

      buo.listOnGoogleSearch(this);
      
  • Track content

  • 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, and referred 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 your AndroidManifest.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
    • 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 or ClassNotFoundException

    • Add to your build.gradle

      defaultConfig {
          multiDexEnabled true
      }
      
    • Add to your Application class and make sure it extends MultiDexApplication

    • 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
  • 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.**.
    • Happens whenever URI Scheme redirection fails.
    • Make sure you do not have $deeplink_path or you have a $deeplink_path which your AndroidManifest.xml can accept

Comments