0

After several days of trying different approaches, we am running out of options. Our aim is to have a Reach Native app, which can be opened/installed using a Branch link. Data of the usage of the user and how they came to be in the app (attribution) is sent eventually to Mixpanel. As we have several other places we would like to analyse usage data, and we would like to keep platform coupling weak, we opted to use Segment.

The key challenge is getting the attribution data has determined by Branch to be applied to the same distinct ID in Mixpanel as the general app usage.

E.g. the event for "Viewed article 123" is assigned to user ABC, while the event from the same person, on the same phone, during the same session, saying "App opened via QR code" is assigned to user DEF. (Those event names are just illustrative and context is actually in the metadata.)

So far I have tried a React Native led setup using

import analytics from '@segment/analytics-react-native';
import branch from '@segment/analytics-react-native-branch';
import mixpanel from '@segment/analytics-react-native-mixpanel';

analytics.setup(WRITE_KEY, {
  using: [branch, mixpanel]
});

We have also tried a more native approach where Segment and Branch are initialized and share ids within MainApplication.java

Analytics analytics = new Analytics.Builder(this, WRITE_KEY).trackApplicationLifecycleEvents().recordScreenViews().build();
Analytics.setSingletonInstance(analytics);
Branch.getInstance().setRequestMetadata(
  "$mixpanel_distinct_id",
  Analytics.with(this).getAnalyticsContext().traits().anonymousId()
);
Branch.getInstance().setRequestMetadata(
  "$segment_anonymous_id",
  Analytics.with(this).getAnalyticsContext().traits().anonymousId()
);

We also tried another version where Mixpanel was also initialized in MainApplication.java and the distinct Id passed from there.

MixpanelAPI mp = MixpanelAPI.getInstance(this, MP_KEY);
Branch.getInstance().setRequestMetadata("$mixpanel_distinct_id", mp.getDistinctId());

While experimenting with these native setups (in several different permutations) we were calling Segments useNativeConfiguration method.

With records to the actual cloud routing, we have also tried every reasonable setup we can imagine. Including:

  • Segment -> MP AND Branch -> MP
  • Segment -> MP AND Segment -> Branch -> MP
  • Segment -> MP AND Segment <-> Branch -> MP (notice Branch is both importing and exporting Segment data)
  • Segment -> Branch -> MP

We have tried many different permutations of the possible configurations and none have created correctly joined-up data. We are open to replacing Segment or Branch with an alternative, but Mixpanel and React Native cannot be replaced due to business constraints.

The latest cloud configuration of "Segment -> Branch -> MP", showed the greatest promise, but even though the documentation says Identify calls are passed to Branch, upon debugging they are not. Meaning the profile of users can never be populated in Mixpanel.

Any help that can be provided would be greatly appreciated.

1 Answers1

0

Ok, we think we have got this working in an acceptable way with the aforementioned technologies.

The setup we ended up with, was to initialise Analytics (Segment) and Branch at the native level. Set both "$mixpanel_distinct_id" and "$segment_anonymous_id" to be the Segment anonymous ID for different stages of the pipeline. And to break the connections between Segment and Branch. So in the end we had the two following paths:

  • App -> Segment -> Mixpanel
  • App -> Branch -> Mixpanel

As only events from Branch (prefixed [BRANCH]) in Mixpanel would have the user's attribution, we then set up a Lambda function to read these events and then call the Mixpanel API to set user properties for UTM medium, campaign and channel. To get this connected we had to reconnect Branch to export events to Segment, using an entirely separate source, to then send on to Lambda as a destination. Something like:

  • Branch -> Lambda -> Mixpanel

Code snippets:

// MainApplication.java
this.initializeSegment();
RNBranchModule.getAutoInstance(this);
RNBranchModule.setRequestMetadata("$segment_anonymous_id",
      Analytics.with(this).getAnalyticsContext().traits().anonymousId()
);
RNBranchModule.setRequestMetadata("$mixpanel_distinct_id",
      Analytics.with(this).getAnalyticsContext().traits().anonymousId()
);
    
private void initializeSegment() {
    Analytics.Builder builder = new Analytics.Builder(this, BuildConfig.SEGMENT_WRITE_KEY)
                .flushQueueSize(20)
                .collectDeviceId(true)
                .trackApplicationLifecycleEvents();

    if (BuildConfig.DEBUG) {
        builder.logLevel(Analytics.LogLevel.VERBOSE);
    }

    Analytics analytics = builder.build();
    Analytics.setSingletonInstance(analytics);
}
import analytics from '@segment/analytics-react-native';
analytics.useNativeConfiguration();