You can send VWO's campaign information to third-party analytics platforms by using notification listeners. You can then segment the analytics report by using VWO's campaign id, campaign name, variation id, or name.
Next, you will find suggested implementations for some common analytics platforms. Feel free to use these as showcased or adapt these to meet your specific needs.
Broadcast Receiver also allows for flexibility to implement an integration with a platform that is not listed here.
Broadcast Receiver
The code can listen to a local Broadcast by using LocalBroadcastManager on the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
.
Broadcast Data
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import com.vwo.mobile.VWO;
public class MainActivity extends AppCompatActivity {
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which the user became part of.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// TODO: Write your analytics code here.
}
};
@Override
protected void onStart() {
super.onStart();
// Create an intent filter for broadcast receiver.
IntentFilter intentFilter = new IntentFilter(VWO.Constants.NOTIFY_USER_TRACKING_STARTED);
// Register your broadcast receiver
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, intentFilter);
}
@Override
protected void onStop() {
super.onStop();
// Unregister your broadcast receiver.
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
}
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.support.v4.content.LocalBroadcastManager
import android.support.v7.app.AppCompatActivity
import com.vwo.mobile.VWO
class MainActivity : AppCompatActivity() {
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which the user became part of.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// TODO: Write your analytics code here.
}
}
override fun onStart() {
super.onStart()
// Create an intent filter for broadcast receiver.
val intentFilter = IntentFilter(VWO.Constants.NOTIFY_USER_TRACKING_STARTED)
// Register your broadcast receiver
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, intentFilter)
}
override fun onStop() {
super.onStop()
// Unregister your broadcast receiver.
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
}
}
It contains the following keys:
VWO.Constants.ARG_CAMPAIGN_ID
: The identifier of the campaign; this is generated by VWO. This is unique for your account.VWO.Constants.ARG_CAMPAIGN_NAME
: The name of the campaign, as set by you. This is not necessarily unique.VWO.Constants.ARG_VARIATION_ID
: The identifier of the variation in the campaign of which the user became the part. A Variation Id is unique for its campaign, but it is not unique across different campaigns.VWO.Constants.ARG_VARIATION_NAME
: The name of the variation in the campaign, as set by you. This is not necessarily unique.
Amplitude
Please refer to the Amplitude android guide if you are getting started with Amplitude.
In the following suggested approach for Amplitude, we use Events.
We add a Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
. When the callback is requested, we send an event to Amplitude when a user becomes a part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.
Events in Amplitude take an event name and event properties in the form of a dictionary.
If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create event properties json object
JSONObject jsonObjectProperties = new JSONObject();
try {
jsonObjectProperties.put("campaignId", campaignId);
jsonObjectProperties.put("campaignName", campaignName);
jsonObjectProperties.put("variationId", variationId);
jsonObjectProperties.put("variationName", variationName);
} catch (JSONException exception) {
Log.e(LOG_TAG, "Unable to create json object", exception);
}
// send event to Amplitude
Amplitude.getInstance().logEvent("campaign_started", jsonObjectProperties);
}
};
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create event properties json object
val jsonObjectProperties = JSONObject()
try {
jsonObjectProperties.put("campaignId", campaignId)
jsonObjectProperties.put("campaignName", campaignName)
jsonObjectProperties.put("variationId", variationId)
jsonObjectProperties.put("variationName", variationName)
} catch (exception: JSONException) {
Log.e(LOG_TAG, "Unable to create json object", exception)
}
// send event to Amplitude
Amplitude.getInstance().logEvent("campaign_started", jsonObjectProperties)
}
}
Flurry
Please refer to the Flurry android guide if you are getting started with Flurry.
In the following suggested approach for Flurry, we use Custom Events.
We add a Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
. When the callback is requested, we send an event to Flurry when a user becomes part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.
Events in Flurry have a two-level structure. The highest level is the specific action, in this case, VWO. The second level in the Event structure is the Event parameter.
If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.
Per Flurry, you must initiate the session with one of the startSession method variants, prior to logging any events. Any events logged prior to session initialization are not recorded.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create event properties map
Map<String, String> mapProperties = new HashMap<>();
mapProperties.put("campaignId", campaignId);
mapProperties.put("campaignName", campaignName);
mapProperties.put("variationId", variationId);
mapProperties.put("variationName", variationName);
// send event to Flurry
FlurryAgent.logEvent("campaign_started", mapProperties);
}
};
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create event properties map
val mapProperties: HashMap<String, String> = HashMap()
mapProperties["campaignId"] = campaignId
mapProperties["campaignName"] = campaignName
mapProperties["variationId"] = variationId
mapProperties["variationName"] = variationName
// send event to Flurry
FlurryAgent.logEvent("campaign_started", mapProperties)
}
}
Google Analytics
Please refer to the Google Analytics Android guide if you are getting started with Google Analytics.
In the following suggested approach for Google Analytics, we use Events.
We add a Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
. When the callback is requested, we send an event to Google Analytics when a user becomes part of a campaign. In the event, we send the campaign name and id, along with the variation name and id.
The next step is to build segments for each variation of your campaign. In the segment-builder user interface, look under Advanced and add a new Condition. Select to filter Users by Event Action and Event Label, type a name for the segment, and then click Save.
Finally, build a report of metrics you are interested in.
public class MainActivity extends AppCompatActivity {
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create data keys
String category = String.format("%s,%s", campaignName, campaignId);
String action = String.format("%s,%s", campaignName, campaignId);
String label = String.format("%s,%s", variationName, variationId);
// send event to Google analytics
Tracker tracker = ((VWOApplication) getApplication()).getDefaultTracker();
tracker.send(new HitBuilders.EventBuilder()
.setCategory(category)
.setAction(action)
.setLabel(label).build());
}
};
}
public class VWOApplication extends Application {
private static GoogleAnalytics sAnalytics;
private static Tracker sTracker;
@Override
public void onCreate() {
super.onCreate();
sAnalytics = GoogleAnalytics.getInstance(this);
}
/**
* Gets the default {@link Tracker} for this {@link Application}.
* @return tracker
*/
synchronized public Tracker getDefaultTracker() {
// To enable debug logging use: adb shell setprop log.tag.GAv4 DEBUG
if (sTracker == null) {
sTracker = sAnalytics.newTracker(R.xml.global_tracker);
}
return sTracker;
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ga_trackingId" translatable="false">${YOUR_TRACKING_ID}</string>
</resources>
class MainActivity : AppCompatActivity() {
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create data keys
val category = String.format("%s,%s", campaignName, campaignId)
val action = String.format("%s,%s", campaignName, campaignId)
val label = String.format("%s,%s", variationName, variationId)
// send event to Google analytics
val tracker = (application as VWOApplication).getDefaultTracker()
tracker.send(HitBuilders.EventBuilder()
.setCategory(category)
.setAction(action)
.setLabel(label).build())
}
}
}
class VWOApplication : Application() {
/**
* Gets the default [Tracker] for this [Application].
* @return tracker
*/
// To enable debug logging use: adb shell setprop log.tag.GAv4 DEBUG
val defaultTracker: Tracker
@Synchronized get() {
if (sTracker == null) {
sTracker = sAnalytics!!.newTracker(R.xml.global_tracker)
}
return sTracker
}
override fun onCreate() {
super.onCreate()
sAnalytics = GoogleAnalytics.getInstance(this)
}
companion object {
private var sAnalytics: GoogleAnalytics? = null
private var sTracker: Tracker? = null
}
}
Google Custom Dimensions
Google also offers Custom Dimensions, which enables association of metadata with hits, users, and sessions in Google Analytics.
As part of the above approach, we only send an event to Google Analytics. You may choose to set custom dimensions. To do this, refer to the Custom Dimensions and Metrics section in Google Analytics and then set custom dimensions in the notification callback.
The next step is to make changes in Google Analytics. Look for the Admin option in the menu bar, and then select the appropriate account and a property. Under Property, select Custom Definitions > New Custom Dimensions. Type a unique name for the dimension, select User for the scope, and then click Create.
You can now see the reports according to the custom dimension.
Localytics
Please refer to the Localytics android guide if you are getting started with Localytics.
In the following suggested approach for Localytics, we use the Custom event with attributes.
We add a Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
. When the callback is requested, we send an event to Localytics when a user becomes a part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.
Localytics also offers a way to set user attributes. You can set the user attributes for VWO's campaign data as well.
The custom event in Localytics has an event name and attributes.
If the campaign name is TestSignup and campaign id is 21, we can set the event name as VWO Campaign - TestSignup - 21. We also send event parameters as campaign_name, campaign_id, variation_name, and variation_id.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create event properties map
Map<String, String> mapProperties = new HashMap<>();
mapProperties.put("campaignId", campaignId);
mapProperties.put("campaignName", campaignName);
mapProperties.put("variationId", variationId);
mapProperties.put("variationName", variationName);
// send event to Localytics
Localytics.tagEvent("campaign_started", mapProperties);
}
};
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create event properties map
val mapProperties: HashMap<String, String> = HashMap()
mapProperties["campaignId"] = campaignId
mapProperties["campaignName"] = campaignName
mapProperties["variationId"] = variationId
mapProperties["variationName"] = variationName
// send event to Localytics
Localytics.tagEvent("campaign_started", mapProperties)
}
}
Mixpanel
Please refer to the Mixpanel android guide if you are getting started with Mixpanel.
In the following suggested approach for Mixpanel, we use Events. Mixpanel also offers a way to set super properties and user profiles.
We add Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
. When the callback is requested, we send an event to Mixpanel when a user becomes a part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.
If you wish to use super properties or people properties, please feel free to modify the following code and send appropriate values to Mixpanel.
The next step is to look for VWO events in your Mixpanel account. You can look at the funnels with the VWO event or look at the segment data.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create event properties json object
JSONObject jsonObjectProperties = new JSONObject();
try {
jsonObjectProperties.put("campaignId", campaignId);
jsonObjectProperties.put("campaignName", campaignName);
jsonObjectProperties.put("variationId", variationId);
jsonObjectProperties.put("variationName", variationName);
} catch (JSONException exception) {
Log.e(LOG_TAG, "Unable to create json object", exception);
}
// send event to Mixpanel
MixpanelAPI mixpanel = MixpanelAPI.getInstance(MainActivity.this, "<YOUR_MIXPANEL_TOKEN>");
mixpanel.track("campaign_started", jsonObjectProperties);
}
};
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create event properties json object
val jsonObjectProperties = JSONObject()
try {
jsonObjectProperties.put("campaignId", campaignId)
jsonObjectProperties.put("campaignName", campaignName)
jsonObjectProperties.put("variationId", variationId)
jsonObjectProperties.put("variationName", variationName)
} catch (exception: JSONException) {
Log.e(LOG_TAG, "Unable to create json object", exception)
}
// send event to Mixpanel
val mixpanel = MixpanelAPI.getInstance(this@MainActivity, "<YOUR_MIXPANEL_TOKEN>")
mixpanel.track("campaign_started", jsonObjectProperties)
}
}
Segment
Please refer to the Segment guide if you are getting started with Segment.
Segment has a spec for A/B testing events.
We add a Broadcast Receiver to listen to the Local broadcast with the key VWO.Constants.NOTIFY_USER_TRACKING_STARTED
and when the callback is requested, we send an event to Segment when a user becomes part of a campaign. In the event, we are sending the campaign name and id, along with the variation name and id.
If the campaign name is TestSignup and campaign id is 21, we can set the event name as Experiment Viewed. We also send event parameters as experimentId, experimentName, variationId, and variationName.
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Get the campaign data for which there user has become the part.
Bundle extras = intent.getExtras();
String campaignId = extras.getString(VWO.Constants.ARG_CAMPAIGN_ID);
String campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME);
String variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID);
String variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME);
// Create event properties object
Properties segmentProperties = new Properties();
segmentProperties.put("experimentId", campaignId);
segmentProperties.put("experimentName", campaignName);
segmentProperties.put("variationId", variationId);
segmentProperties.put("variationName", variationName);
// send event to Segment
Analytics.with(context).track("Experiment Viewed", segmentProperties);
}
};
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Get the campaign data for which there user has become the part.
val extras = intent.extras
val campaignId = extras!!.getString(VWO.Constants.ARG_CAMPAIGN_ID)
val campaignName = extras.getString(VWO.Constants.ARG_CAMPAIGN_NAME)
val variationId = extras.getString(VWO.Constants.ARG_VARIATION_ID)
val variationName = extras.getString(VWO.Constants.ARG_VARIATION_NAME)
// Create event properties object
val segmentProperties = Properties()
segmentProperties.put("experimentId", campaignId)
segmentProperties.put("experimentName", campaignName)
segmentProperties.put("variationId", variationId)
segmentProperties.put("variationName", variationName)
// send event to Segment
Analytics.with(context).track("Experiment Viewed", segmentProperties)
}
}