Android SDK
You can get started with using Taplytics on Android in minutes. Just follow the steps below:
Installation
Android Studio
- In your module’s build.gradle, add the url to the sdk.
repositories {
maven { url "https://github.com/taplytics/Taplytics-Android-SDK/raw/master/AndroidStudio/" }
}
- In your module’s build.gradle dependencies (not your project's build.gradle), compile Taplytics and its dependencies. NOTE: You can use EITHER Retrofit2 or Volley.
dependencies {
//Dependencies for Taplytics
implementation 'com.taplytics.sdk:taplytics:+@aar'
//socket.io connections only made on debug devices.
//To make live changes on a release build, remove the `debugcompile` flag
debugImplementation ('io.socket:socket.io-client:+') {
exclude group: 'org.json', module: 'json'
}
//NOTE: You can use either Volley or Retrofit2. Do not use both if you do not have to.
//Volley
implementation 'com.android.volley:volley:+'
//Retrofit2
implementation 'com.squareup.retrofit2:retrofit:+'
//Only include this if you wish to enable push notifications:
implementation("com.google.android.gms:play-services-gcm:9.+")
}
Click here to read more about the recent socket dependency changes.
- Override your Application’s onCreate() method (not your main activity) and call Taplytics.startTaplytics(). If you don't have an Application class, create one. It should look like this:
public class ExampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Taplytics.startTaplytics(this, "YOUR TAPLYTICS SDK KEY");
}
}
- Now, add the proper permissions, and the Application class to your app’s AndroidManifest.xml in the Application tag.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".ExampleApplication"
...
- To be able to connect to Taplytics on a release build, add the following intent-filter tag to the end of your MAIN activity:
First, get your Taplytics URL Scheme from your Project's Settings:
Then, add it to your manifest in its own intent filter (do not merge with another intent filter).
...
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="YOUR URL SCHEME"/>
</intent-filter>
</activity>
Install with Segment
The Taplytics SDK can also be installed via Segment. You can find install instructions here.
Install with mParticle
Check the Taplytics integration for the mParticle Android SDK docs here
Initialization
Initialize the Taplytics SDK by adding the following line of code with your SDK key to your Main Application class. Taplytics can also be started with a few options to help you use it during development. See the start options section for more details.
First, the base method:
Taplytics.startTaplytics(this, "Your SDK Key");
Or, add a map of options.
HashMap<String, Object> options = new HashMap<>();
options.put("optionName", optionValue);
Taplytics.startTaplytics(this, "Your SDK Key", options);
Important Notes
It is highly recommended to initialize Taplytics in the Application’s onCreate()
for several reasons.
- Taplytics uses the information on how your app was launched to support some of our core features. ie. View construction/data for the Visual Editor
- Taplytics should also be started as early as possible to allow time for Taplytics to fetch our config and present the correct experiment and feature data before the first activity starts.
- Taplytics uses the application start as a signal for when the App has been activated. We use this data to accurately track sessions and activity.
Threading
Taplytics will create its own threadpool and operate off the main thread except when making visual modifications as this must occur on the UI thread.
Start Options
Option Name | Values | Default | Explanation |
---|---|---|---|
liveUpdate | boolean: true/false | set by build (enabled in debug) | Disable live update to remove the border, and activity refreshing in your debug builds to test the functionality of your applications as if they were in release mode. Note that this functionality is always disabled by default in release builds. Setting liveUpdate to true on a release build will override this and force the application into debug mode. |
shakeMenu | boolean: true/false | set by build (enabled in debug) | In your debug builds, disable the quick menu that appears when you shake your device. This menu is never present in release builds. |
aggressive | boolean | false | Taplytics has the option to allow for aggressive visual changes. This means that if text or visibility is changed within your app by code outside of Taplytics, Taplytics will force the values to remain what has been set on the dashboard. |
sessionMinutes | int > 0 | 10 | If you do your own analytics alongside Taplytics, it helps to define your sessions to be the same length to reconcile your data. Set this to be the same timing interval that your app counts sessions. |
turnMenu | boolean: true/false | false | If you are doing visual testing on an emulator, or UI automation, many emulators do not have the ability to shake the device. So, to pop up the Taplytics menu on such devices, set turnMenu to true, and simply rotate the device from portrait/landscape twice in a row within 30 seconds and this menu will show. |
disableBorders | boolean: true/false | set by build (enabled in debug) | This will entirely disable the informational borders Taplytics applies during debug mode testing. Useful to disable for UI testing. Note that this border will NOT show in release mode regardless of setting (except for on previously paired phones). |
testExperiments | HashMap | null | See: Testing Specific Experiments. |
retrofit | boolean: true/false | set by build (true if only retrofit present) | Taplytics will default to using Volley if it is present. In the event that you have both enabled, you can use this flag to force the library to use retrofit instead. |
trackingId | string | null | To separate all users devices, Taplytics will use device identifiers by default as an identification tool. However, clients are able to provide their own tracking IDs to Taplytics for user devices, such as google advertising IDs. If this option is used, Taplytics will not collect any device identifiers. |
logging | boolean: true/false | false | This will provide more verbose logging from Taplytics to help with debugging. |
userBucketing | boolean: true/false | false | This will turn on user based bucketing logic for your SDK, creating an anonymous user_id if one is not provided. Otherwise it will take the saved user_id from the device that was saved using setUserAttributes . |
Timeouts
Timeouts have since been removed from individual callbacks and have been added as a starting parameter.
By default the timeout is 4000ms. After this timeout has been reached, Taplytics will use only whatever values were loaded from disk for the remainder of the session. All variableUpdated
callbacks will trigger, all getRunningExperimentsAndVariations
will return with disk values, and the TaplyticsExperimentLoadedListener
will trigger. The new values will still attempt to download and they will be cached and ready to be used for the next session.
Example:
Taplytics.startTaplytics(Context, SDK_KEY, Options, TimeoutInMillis)
or
Taplytics.startTaplytics(Context, SDK_KEY, TimeoutInMillis)
Etc.
The Border / Shake menu.
When connected to an experiment on a debug build, a border will show around your app window. This shows which experiment and variation you are currently viewing.
You can long-press on the top of the border to switch experiments, or shake your device and pick from the menu, or select an experiment from the Taplytics website.
The border and shake menu will NOT appear on release builds.
Showing the menu without shaking or turning
Taplytics offers a Taplytics.showMenu() function that can be used to call up the experiment menu. This is useful for testing environments that cannot shake or turn the device.
Advanced Device Pairing
Link a device (even in release mode) to Taplytics.
NOTE: This is used only for deeplink pairing
Retrieve deeplink through Taplytics deeplink intercepted via either email or SMS device pairing. It contains your Taplytics URL scheme and device token. If you wish to intercept the deeplink and then pair the device yourself in your application's code, call this method in your app's LAUNCH activity or MAIN activity, like so:
private void handleDeepLink(Intent intent) {
String tlDeeplink = intent.getDataString(); //example deep link: 'tl-506f596f://e10651f9ef6b'
if (tlDeeplink == null) {
// No deeplink found
return;
}
Taplytics.deviceLink(tlDeeplink);
}
Do not forget to get your Taplytics URL Scheme from your Project's Settings:
Then, add it to your manifest in its own intent filter:
...
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="YOUR URL SCHEME"/>
</intent-filter>
</activity>
NOTE: The socketIO dependency must be present in the release build (ie not set to debugcompile
) to pair with a release build.
Setting User Attributes
It's possible to send custom user attributes to Taplytics using a JSONObject of user info.
The possible fields are:
Parameter | Type |
---|---|
String | |
user_id | String |
firstname | String |
lastname | String |
name | String |
age | Number |
gender | String |
You can also add anything else you would like to this JSONObject and it will also be passed to Taplytics.
An example with custom data:
JSONObject attributes = new JSONObject();
attributes.put("email", "[email protected]");
attributes.put("name", "John Doe");
attributes.put("age", 25);
attributes.put("gender", "male");
attributes.put("avatarUrl", "https://someurl.com/someavatar.png");
attributes.put("someCustomAttribute", 50);
attributes.put("paidSubscriber", true);
attributes.put("subscriptionPlan", "yearly");
Taplytics.setUserAttributes(attributes);
You can also attach a callback to notify you when user attributes has finished calling:
Taplytics.setUserAttributes(attributes, new TaplyticsSetUserAttributesListener() {
@Override
public void finishedSettingUserAttributes() {
// Finished setting user attributes
}
});
User Attributes on First Launch
User Attributes set before startTaplytics
is called will be used for experiment segmentation on the first session of your app. Any attributes that are set after startTaplytics
is called will not be used for experiment segmentation until the next session of your app.
// These custom data values will be used for segmentation on the first session of the app.
JSONObject attributes = new JSONObject();
attributes.put("example", 1);
Taplytics.setUserAttributes(attributes);
Taplytics.startTaplytics(this, SDK_KEY)
// These custom data values will only take effect on the second session of the app.
JSONObject attributes = new JSONObject();
attributes.put("example", 0);
Taplytics.setUserAttributes(attributes);
Retrieving Session Info
Taplytics also offers a method to retrieve select information of what you know about a session at a given time. This method returns the user's Taplytics identifier (appUser_id
) and current session id (session_id
)
Taplytics.getSessionInfo(new SessionInfoRetrievedListener() {
@Override
public void sessionInfoRetrieved(HashMap sessionInfo) {
//Use your Hashmap of Session Info
}
});
Resetting user attributes or Logging out a user
Once a user logs out of your app, their User Attributes are no longer valid. You can reset their data by calling resetAppUser
, make sure you do not set any new user attributes until you receive the callback.
Taplytics.resetAppUser(new TaplyticsResetUserListener() {
@Override
public void finishedResettingUser() {
//Finished User Reset
}
});
User Opt-In / Opt-Out
Using the User Opt-In / Opt-Out APIs allows you to simplify the process to get user consent for analytics tracking and experimentation. Calling optOutTracking
will disable all Taplytics analytics tracking and experiments, and calling optInTracking
will re-enable all Taplytics analytics tracking and experiments. You can retrieve the current status using: hasUserOptedOutTracking
.
// Opt In
Taplytics.optInTracking(this);
// Opt Out
Taplytics.optOutTracking(this);
// Check if user has opted out
Taplytics.hasUserOptedOutTracking(this, new TaplyticsHasUserOptedOutListener() {
@Override
public void hasUserOptedOutTracking(boolean hasOptedOut) {
// use hasOptedOut:
// true: user has opted out
// false: user has opted in
}
});
Tracking Events
Automatic Events
Some events are automatically tracked by Taplytics and will appear on your dashboard. These events are:
- App Start
- Activity and/or Fragment load
- Activity and/or Fragment destroy
- Activity pause
- App background
- Viewpager changes
App terminate is also tracked, but this is only true when your MAIN activity is at the bottom of your activity stack, and the user exits the app from that activity.
No changes are needed in your code for this event tracking to occur.
Custom Events
To log your own events, simply call:
Taplytics.logEvent("Your Event Name");
You can also log events with numerical values:
Number num = 0;
Taplytics.logEvent("Your Event Name", num);
And with custom object data:
Number num = 0;
JSONObject customInfo = new JSONObject();
customInfo.put("some title", someValue)
Taplytics.logEvent("Your Event Name", num, customInfo);
Revenue Logging
It's also possible to log revenue.
Revenue logging is the same as event logging, only call logRevenue
:
Number someRevenue = 10000000;
Taplytics.logRevenue("Revenue Name", someRevenue);
And similarly, with custom object data:
Number someRevenue = 10000000;
JSONObject customInfo = new JSONObject();
customInfo.put("some rag", someValue)
Taplytics.logRevenue("Revenue Name", someRevenue, customInfo);
Receiving External Analytics
At the moment, Taplytics supports Mixpanel, Google Analytics, Adobe Analytics, Flurry, Localytics and Amplitude as a source of external analytics.
Mixpanel, Adobe, Localytics and Amplitude
When the Taplytics SDK is installed alongside any of these sources, all of your existing and future analytics events will be sent to both the source and Taplytics.
Flurry
To properly support sending Flurry data, you simply need to tell Taplytics whenever a new Flurry session begins. This can be done directly after Flurry initialization.
FlurryAgent.init(this, "your flurry API key");
FlurryAgent.setFlurryAgentListener(new FlurryAgentListener() {
@Override
public void onSessionStarted() {
Taplytics.startFlurrySession();
}
});
Google Analytics 7.0.0-
If you are using Google Analytics 7.0.0 and below, all Google Analytics will automatically be sent to both Google Analytics and Taplytics.
Google Analytics 7.3.0+
If you are using Google Analytics 7.3.0 or above, you have the option of changing things to send your Google Analytics to both Google and Taplytics.
Simply find all instances of tracker.send(new Hitbuilder...)
and replace them with Taplytics.logGAEvent(tracker, new Hitbuilder...)
You can do this with a simple find/replace in your application.
An example:
Tracker t = TrackerManager.getInstance()
.getGoogleAnalyticsTracker(TrackerManager.TrackerName.APP_TRACKER, getApplication());
t.send(new HitBuilders.EventBuilder()
.setCategory("someCategory")
.setAction("someAction")
.setLabel("someLabel")
.setValue(12)
.build());
Would be changed to:
Tracker t = TrackerManager.getInstance()
.getGoogleAnalyticsTracker(TrackerManager.TrackerName.APP_TRACKER, getApplication());
Taplytics.logGAEvent(t, new HitBuilders.EventBuilder()
.setCategory("someCategory")
.setAction("someAction")
.setLabel("someLabel")
.setValue(12)
.build());
Sending to External Analytics
Taplytics can send experiment data to external analytics sources on startup. This integration is automatic with the exception of Google Analytics where the tracker instance must be passed as a startup option to Taplytics.
HashMap<String, Object> options = new HashMap<>();
options.put("gaTracker", tracker);
Taplytics.startTaplytics(this, "YOUR SDK KEY", options);
The experiment data will be sent as a single event to Adobe, Amplitude, Flurry, and Localytics. The event will be named TL_experiments
and have the experiment data as properties.
For both Google Analytics and Mixpanel, the experiment data will be set as properties on all the events (known as super properties in Mixpanel).
The properties for all sources are in the following format:
{
"Experiment One":"Variation One",
"Experiment Two":"baseline"
}
Experiments
Creating experiments is easy using Taplytics. You can either use our visual editor or create code-based experiments. You can find documentation on how to do this below.
Feature Flags
Taplytics feature flags operate in synchronous mode. Synchronous feature flags are guaranteed to have the same value for the entire session and will have that value immediately after construction.
Due to the synchronous nature of feature flags, if it is used before the feature flags have been loaded from Taplytics servers (for example on the first launch of your app), it will default to as if the feature flag is not present. In order to prevent this you can ensure that the feature flag is loaded before using the feature flag. This can be done with either the delayLoad
functionality, the TaplyticsExperimentsLoadedListener
parameter in your startTaplytics
call, or the getRunningExperimentsAndVariations
call:
if (Taplytics.featureFlagEnabled("featureFlagKey")) {
//Put feature code here, or launch feature from here
}
Running Feature Flags
If you would like to see which feature flags are running on a given device, there exists a getRunningFeatureFlags(TaplyticsRunningFeatureFlagsListener listener)
function which provides a callback with a map of the current feature flags. An example:
Taplytics.getRunningFeatureFlags(new TaplyticsRunningFeatureFlagsListener() {
@Override
public void runningFeatureFlags(Map<String, String> featureFlags) {
// TODO: Do something with the map.
}
});
Dynamic Variables & Code Blocks
To see and modify these variables or blocks on the dashboard, the app must be launched and this code containing the variable or block must be navigated to at least once.
The code below is used to send the information of the variable or block to Taplytics, so it will appear on the dashboard.
Dynamic Variables
Taplytics variables are values in your app that are controlled by experiments. Changing the values can update the content or functionality of your app. Variables are reusable between experiments and operate in one of two modes: synchronous or asynchronous.
Synchronous
Synchronous variables are guaranteed to have the same value for the entire session and will have that value immediately after construction.
Due to the synchronous nature of the variable, if it is used before the experiments have been loaded, its value will be the default value rather than the value set for that experiment. This could taint the results of the experiment. In order to prevent this you can ensure that the experiments are loaded before using the variable. This can be done with either the delayLoad
functionality, the TaplyticsExperimentsLoadedListener
parameter in your startTaplytics
call, or the getRunningExperimentsAndVariations
call.
Synchronous variables take two parameters in its constructor:
- Variable name (String)
- Default Value
The type of the variable is defined in the first diamond brackets, and can be a String
, Number
, Boolean
or JSON
.
For example, using a variable of type String
:
TaplyticsVar<String> stringVar = new TaplyticsVar<String>("some name", "default value");
Then when you wish to get the value for the variable, simply call get()
on the Taplytics variable:
String value = stringVar.get();
Asynchronous
Asynchronous variables take care of insuring that the experiments have been loaded before returning a value. This removes any danger of tainting the results of your experiment with bad data. What comes with the insurance of using the correct value is the possibility that the value will not be set immediately. If the variable is constructed before the experiments are loaded, you won't have the correct value until the experiments have finished loading. If the experiments fail to load, then you will be given the default value, as specified in the variables constructor. For the best results with asynchronous varaibles make sure that they are constructed after the StartTaplytics call in your app's lifecycle.
Asynchronous variables take three parameters in its constructor:
- Variable name (String)
- Default Value
- TaplyticsVarListener
Just as for synchronous variables the type of the variable is defined in the first diamond brackets, and can be a String
, Number
, Boolean
or JSON
.
For example, using a variable of type Number
:
TaplyticsVar<Number> var = new TaplyticsVar<>("name", 5, new TaplyticsVarListener() {
@Override
public void variableUpdated(Object value) {
// Do something with the value
}
});
When the variable's value has been updated, the listener will be called with that updated value. You can specify what you want to do with the variable inside the variableUpdated
method.
Note: Default values for dynamic variables cannot be NULL. NULL values may cause default to trigger in all scenarios
Testing Dynamic Variables
When testing dynamic variables in live update mode you can change the values on the fly via the Taplytics interface and you can switch variations with the shake menu on the device.
Important Note: When testing synchronous dynamic variables you must call the constructor again to see the new value, as there are no callbacks which occur when the variable is updated with a new value.
This can be achieved by using an experiments updated listener. Here is an example for updating a TextView:
Taplytics.setTaplyticsExperimentsUpdatedListener(new TaplyticsExperimentsUpdatedListener() {
@Override
public void onExperimentUpdate() {
final TaplyticsVar<String> stringVar = new TaplyticsVar<String>("stringVar", "defaultValue");
updateText(stringVar.get());
}
});
Code Blocks
Similar to Dynamic Variables, Taplytics has an option for 'Code Blocks'. Code blocks are linked to Experiments through the Taplytics website very much the same way that Dynamic Variables are, and will be executed based on the configuration of the experiment through the Taplytics website. A Code Block is a callback that can be enabled or disabled depending on the variation. If enabled, the code within the callback will be executed. If disabled, the variation will not get the callback.
A Code Block can be used alongside as many other Code Blocks as you would like to determine a combination that yields the best results. Perhaps there are three different Code Blocks on one activity. This means there could be 8 different combinations of Code Blocks being enabled / disabled on that activity if you'd like.
For example:
Taplytics.runCodeBlock("name", new CodeBlockListener() {
@Override
public void run() {
// Put your code here!
}
});
By default, a code block will not run unless enabled on the Taplytics Dashboard. It must be enabled for a Variation before it will run.
Testing Specific Experiments
To test/QA specific experiment and variation combinations, add a map to the Taplytics start options containing the experiments and variations you wish to test. The keys should be the experiment names, and values of variation names (or baseline).
For example:
HashMap<String, Object> startOptions = new HashMap<>();
HashMap testExperiments = new HashMap();
testExperiments.put("Big Experiment", "Variation 2");
startOptions.put("testExperiments", testExperiments);
Taplytics.startTaplytics(this, SDK_KEY, startOptions);
Visual Editing
You don't have to do anything else! You can use the Taplytics dashboard to make all your visual changes. See the docs on visual editing here.
Dialogs
Taplytics supports editing elements on dialogFragments (not dialogs). To do this properly, you must use a fragmentTransaction to add the fragment to the backstack. The tag used here should be the same as the tag used to show the fragment, like so:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.show(someDialog);
fragmentTransaction.addToBackStack("fragment_some_dialog");
someDialog.show(fragmentTransaction, "fragment_some_dialog");
Taplytics tracks the appearance/disappearance of the dialog via the backstack manager, which is why it needs to be sent there. The tag is necessary to confirm that the visual edits are being applied to the correct fragment.
This only works with dialogFragments as normal Dialogs do not have any unique identifying tags.
NOTE: dialogFragments exist on an entirely different view hierarchy than traditional view elements. They exist within their own window
and have an entirely different viewRoot than the rest of your application. This makes changes on dialogs very difficult, and this feature is not 100% guaranteed to work for all dialogs.
Delay Load
Taplytics has the option to delay the loading of your main activity while Taplytics gets initial view changes ready. Keep in mind that this initial load will only take some time the very first time, after that, these changes will be saved to disk and will likely not need a delay.
There are two methods to do this, use both at the start of your java onCreate()
after java setContentView()
:
Delay Load With Image
In this instance, Taplytics takes care of the loading for you. Taplytics creates a splash screen with the provided image. The image will fade automatically after the given time, or when Taplytics has successfully loaded visual changes on the provided activity.
Method: Taplytics.delayLoad(Activity activity, Drawable image, int maxTime)
and Taplytics.delayLoad(Activity activity, Drawable image, int maxTime, int minTime)
- Activity: the activity (typically main activity) that will be covered in a splash image.
- Image: A Drawable image that will be the splash screen.
- maxTime: Regardless of the results of Taplytics, the image will fade after this time. Milliseconds.
- minTime: Sometimes Taplytics loads things really fast, and this might make the image show only for a short amount of time. To keep this from happening, there is an optional minimum time option. Regardless of Taplytics loading experiments, the
delayLoad
won't finish until after this minimum time. Milliseconds.
Example:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Taplytics.delayLoad(this, getResources().getDrawable(R.drawable.image5), 2000);
...
With a 1 second minimum time
Taplytics.delayLoad(this, getResources().getDrawable(R.drawable.image5), 2000, 1000);
...
Delay Load with Callbacks
In this instance, Taplytics provides callbacks when the delay load should begin, and when the delay load ends. The callback will also return after the provided timeout time has been reached. This provides you the ability to show a splashscreen that is more than just a simple image.
Method: Taplytics.delayLoad(int maxTime, TaplyticsDelayLoadListener listener)
and Taplytics.delayLoad(int maxTime, int minTime, TaplyticsDelayLoadListener listener)
- maxTime: Regardless of the results of Taplytics, this callback will be triggered if this time is reached.
- minTime: Sometimes Taplytics loads things really fast, and this might make the behavior of the callback undesirable. To keep this from happening, there is an optional minimum time option. Regardless of Taplytics loading experiments, the
delayLoad
won't finish until after this minimum time. - Listener: This listener will provide the necessary callbacks.
Example:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Taplytics.delayLoad(2000, new TaplyticsDelayLoadListener() {
@Override
public void startDelay() {
//Start delaying!
}
@Override
public void delayComplete() {
//Loading completed, or the given time has been reached. Insert your code here.
}
});
...
With a 1 second minimum time:
Taplytics.delayLoad(2000, 1000, ...
List Running Experiments
If you would like to see which variations and experiments are running on a given device, there exists a getRunningExperimentsAndVariations(TaplyticsRunningExperimentsListener listener)
function which provides a callback with a map of the current experiments and their running variation. An example:
Taplytics.getRunningExperimentsAndVariations(new TaplyticsRunningExperimentsListener() {
@Override
public void runningExperimentsAndVariation(Map<String, String> experimentsAndVariations) {
// TODO: Do something with the map.
}
});
NOTE: This function runs asynchronously, as it waits for the updated properties to load from Taplytics' servers before returning the running experiments.
If you want to see when the experiments have been loaded by Taplytics, you can add a TaplyticsExperimentLoadedListener
to your startTaplytics
call. For example:
Taplytics.startTaplytics(this, "YOUR SDK KEY", null, new TaplyticsExperimentsLoadedListener() {
@Override
public void loaded() {
//TODO: Do something now that experiments are loaded
}
});
Sessions
By default, Taplytics defines a session as when a user is using the app with less than 10 minutes of inactivity. If the app has been backgrounded for 10 minutes, the next time the user opens the app it will be considered a new session. Similarly, if the app is entirely force closed, the next time the app is opened, it will be considered a new session.
StartNewSession
To manually force a new user session (ex: A user has logged in / out), there exists Taplytics.startNewSession
If there is an internet connection, a new session will be created, and new experiments/variations will be fetched from Taplytics if they exist.
It can be used as follows:
Taplytics.startNewSession(new TaplyticsNewSessionListener() {
@Override
public void onNewSession() {
// New session here! Only returns if successful.
}
});
Session Listener
To keep track of when Taplytics defines a new session, use a TaplyticsNewSessionListener
as follows.
Taplytics.setTaplyticsNewSessionListener(new TaplyticsNewSessionListener() {
@Override
public void onNewSession() {
//We are in a new session
}
});
Note that this is NOT called the first time Taplytics loads, only on subsequent sessions
Push Notifications
Setting up Push Notifications using Taplytics is simple. Follow the steps below to get started.
Note: Google has changed the way push notifications work from using GCM to FCM, migrate ASAP!
1. Setup
Set up your Firebase certificate on Taplytics by following these docs.
Android Studio
Follow these instructions to add firebase to your project. Then, add the following to your dependencies in your build.gradle
:
implementation 'com.google.firebase:firebase-messaging:17.+'
implementation 'com.google.firebase:firebase-core:16.0.8'
Add the following to the end of your build.gradle
file if you haven't already:
apply plugin: 'com.google.gms.google-services'
Android Manifest
If you wish to use Push Notifications on Taplytics, you must add the following to your AndroidManifest.xml
file under the application tag:
<service
android:name="com.taplytics.sdk.fcm.TLFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Other notes
- Keep in mind Firebase is supported only in API level 14 and up
- Minimum version of firebase-messaging support is
17.0.0
- Minimum version of firebase-core support is
16.0.8
- Minimum version of Taplytics Android SDK is
2.1.0
In order to set the notification icon you must add a meta-tag to your manifest specifying the drawable you want to use as the icon:
<meta-data android:name="com.taplytics.sdk.notification_icon"
android:resource="@drawable/notification_icon"/>
If this isn't set the application's icon will be used instead.
2. Receiving Push Notifications
To send your users Push Notifications, we'll need you to upload your Google Cloud Messaging credentials. Please follow this guide to do so.
Activity Routing
By default, when a notification sent by Taplytics is clicked, it will open up the main activity of the application. However, you may want to route your users to a different Activity. This can be done on the Taplytics Push page.
Simply add a custom data value to the push with the key tl_activity
and with the full (including package name) class name of your activity. For example:
Push Title
By default, the title of a push notification will be the application name.
Currently, the best way to change the title of a push notification is to add a tl_title
custom key. For Example:
Getting the Push Token
Sometimes, it can be useful to have the actual token generated by GCM, to target pushes at specific users.
To get this token, use the following method:
Taplytics.setTaplyticsPushTokenListener(new TaplyticsPushTokenListener() {
@Override
public void pushTokenReceived(String token) {
//Do something with the push token here.
}
});
3. Rich Push Notifications
Implementing rich push notification support can help improve user engagement with your push notifications with image content attached. We currently support JPEG and PNG images sent from the Taplytics dashboard or API.
Android will automatically crop all images to be a 2:1 aspect ratio, scaling if necessary.
The max image size that can be uploaded is 10mb. Note that images are not downscaled and if an image is sent, the full file size of the crop will be used.
Here is an example of a push notification with an image:
4. Custom Data and Tracking Push Interactions
Taplytics has changed as of version 1.9 and push notifications are easier than ever:
To retrieve custom data set in the Taplytics dashboard, as well as to track push interactions (receive, open, dismiss), simply extend the TLBroadcastReceiver and override the function that you need. Then, replace the TLGcmBroadcastReceiver
in your manifest with that one!
Below is an example receiver that explains exactly how this is done. You can put this class directly in your app and start tracking push notifications right away. By default, taplytics will open the LAUNCH activity of your app, but this can be changed by not calling the super (see example below).
Note that Taplytics automatically tracks the following, however if you would like to do so for internal reasons, this is how.
/**
* Example receiver to take action with push notifications.
*
* Make sure to add this to your manifest (see the docs)
*
* Overriding any of these is entirely optional.
*
* By default, taplytics will open the launch activity of your
* app when a push notification is clicked.
*
*/
public class MyBroadcastReceiver extends TLGcmBroadcastReceiver {
@Override
public void pushOpened(Context context, Intent intent) {
//A user clicked on the notification! Do whatever you want here!
/* If you call through to the super,
Taplytics will launch your app's LAUNCH activity.
This is optional. */
super.pushOpened(context, intent);
}
@Override
public void pushDismissed(Context context, Intent intent) {
//The push has been dismissed :(
}
@Override
public void pushReceived(Context context, Intent intent) {
//The push was received, but not opened yet!
/*
If you add the custom data of tl_silent = true to the push notification,
there will be no push notification presented to the user. However, this will
still be triggered, meaning you can use this to remotely trigger something
within the application!
*/
}
}
And then in your manifest:
<receiver
android:name=".MyBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
<intent-filter>
<action android:name="taplytics.push.OPEN" />
<action android:name="taplytics.push.DISMISS" />
</intent-filter>
</receiver>
If you are handling push notifications with custom payloads, the custom data key/values will be added to the custom_keys
object as seen below in an example push payload:
{
"data": {
"message": "Test Push",
"tl_id": "",
"custom_keys": {
"custom_data_key": "custom_data_value"
},
"image_url": ""
}
}
5. Special Push Options (title, priority, icon)
The dashboard allows for custom data to be entered into your push notifications. However there are some options that can be added to the custom data for special functionality.
Name | Values | Explanation |
---|---|---|
tl_title | String | This changes the TITLE of the push notification. By default, it is your application's name. But with this option you can change the title to be anything. |
tl_priority | integer | Set the priority of the push notification. For more info see the section 'Correctly set and manage notification priority' here. The value set must be the integer that is associated with the priorities, which can be found here. |
tl_image_icon | boolean | Will not show a preview image as the notification icon when set to false. Defaults to true. |
tl_large_icon | boolean | Will show the app icon in the notification when set to true. Defaults to false. |
6. Manual Token Registration (Optional)
If you already have a system to receive Firebase push tokens, you can use TLFirebaseMessagingServiceLite
instead of TLFirebaseMessagingService
. Instead of overriding onNewToken
and saving the token to our system automatically, all TLFirebaseMessagingServiceLite
does is process the push notification.
You then must use Taplytics.savePushToken("PUSH_TOKEN")
to enable push notifications through Taplytics.
7. Tracking Self Built Notifications
You may be using Taplytics simply to send push notifications. If you already have a system to build notifications, then extending the Taplytics BroadcastReceiver will cause you to see duplicates.
To avoid this problem, first, do not call super.onReceive()
where super would be the TLGCMBroadcastReceiver
.
Now, Taplytics will not have any push notification tracking if you do this.
To mitigate this, you must use the Taplytics functions provided. In each function, you must pass in the tl_id in the notification attempt.
Push Open
Taplytics.trackPushOpen("tl_id",customKeys);
Where tl_id is retrieved from the notification intent. CustomKeys is the metadata passed into the notification. It is optional/nullable
Push Dismissed
Taplytics.trackPushDismissed("tl_id",customKeys);
Where tl_id is retrieved from the notification intent. CustomKeys is the metadata passed into the notification. It is optional/nullable
Push Received
Taplytics.trackPushReceived("tl_id",customKeys);
Where tl_id is retrieved from the notification intent. CustomKeys is the metadata passed into the notification. It is optional/nullable
8. Troubleshooting
Using the shake menu, you can copy the token to your clipboard, force to save the token to Taplytics, or renew the token.
Taplytics.showMenu(); // Shows the shake menu, exposing some useful items like the push token
Sockets
Usage
Sockets are used in the Taplytics SDK to establish a two way connection to Taplytics' servers. This connection is used for editing experiments, both for visual experiments and dynamic variables. However it is only used in the development versions of the app, or devices which have been explicitly paired with Taplytics using a pairing email or text message.
Inclusion in release builds - as of 1.7.0
Due to experiment editing for the most part being done on internal dev builds sockets are not necessary on release versions of the app. In order to account for this Taplytics does not require the socket dependency for release builds. So instead of using the standard compile
directive when adding the socket dependency the debugCompile
directive can be used instead.
Please note that this will not allow pairing of live versions of the app using text message or email pairing.
debugCompile ('io.socket:socket.io-client:+') {
// excluding org.json which is provided by Android
exclude group: 'org.json', module: 'json'
}
I'm getting a popup saying update my sockets!
There was a recent change (1.7.0) in the package name of the socket library used by Taplytics. Given that the library has continued to improve over time Taplytics makes use of this new library. Unfortunately this means that the dependency that was being used before is no longer valid.
There is a quick change that will fix this issue, simple change:
compile("com.github.nkzawa:socket.io-client:+") {
exclude group: 'org.json'
}
compile("com.github.nkzawa:engine.io-client:+") {
exclude group: 'org.json'
}
to:
debugCompile('io.socket:socket.io-client:+') {
// excluding org.json which is provided by Android
exclude group: 'org.json', module: 'json'
}
as mentioned above you can use debugCompile
instead of compile
if you don't want to include socket-io
in the release version of your app.
Updated about 4 years ago