1. Installing Liquid on your project

Installing Liquid SDK on your project is very easy. Pick one of the following methods:

Install via Gradle Edit

Add Liquid Android SDK to your build.gradle file:

dependencies {
  compile 'io.lqd:liquid-android:2.0.0@aar'
}

Install via Maven Edit

Add Liquid Android SDK to your pom.xml file:

<dependency>
  <groupId>io.lqd</groupId>
  <artifactId>liquid-android</artifactId>
  <version>2.0.0</version>
</dependency>

Install via Eclipse Edit

  • Download/clone the SDK from https://github.com/lqd-io/liquid-sdk-android

  • Import Liquid Android SDK project to Eclipse. Import Liquid Android SDK project to Eclipse

  • Add java folder to build path. Add java folder to build path

  • Remove src folder from build path. Remove src folder from build path

  • Go to Project Properties > Android tick “Is Library”. Go to _Project Properties > Android_ tick "Is Library"

  • Add Liquid Android SDK project Library to your Android Project. Add **Liquid Android SDK** project Library to your Android Project

2. Using Liquid SDK

The following steps will guide you on how to integrate Liquid on your project.

Add permissions to application manifest Edit

The first step is to add the following permissions to your AndroidManifest.xml file:

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">

Initialize Liquid Edit

Important note

For every app you add on Liquid, two versions of the app are created: a production and a development version. These versions have completely distinct environments (i.e., different users, devices, sessions, events, targets and dynamic variables) and each app version has its own API key.

Once you’ve set up the permissions, you must initialize the Liquid singleton (once per app launch) with your App’s API key. Typically, the best place to do this is on the public void onCreate() method in your Application class.

You can find your App API key on the App Settings of Liquid’s dashboard.

// first Activity file
@Override
protected void onCreate(Bundle savedInstanceState) {

  // assuming that you're using a DEBUG flag
  if (BuildConfig.DEBUG) {
    Liquid.initialize(this, "YOUR_DEVELOPMENT_APP_TOKEN", BuildConfig.DEBUG);
  } else {
    Liquid.initialize(this, "YOUR_PRODUCTION_APP_TOKEN");
  }
}

From this moment on, each time you want to call a Liquid method you can do:

Liquid.getInstance();

Note

All interactions using Liquid SDK should be done using this shared instance of Liquid object (and not using LQ* models).

If your application supports Android SDK < 14 follow these instructions.

Android SDK < 14

If your application supports Android SDK < 14, then you have to notify Liquid when your activity lifecycle changes. On the other hand, for Android SDK versions greater or equal than 14, Liquid will automatically do that for you.

@Override
public void onResume() {
  super.onResume();
  Liquid.getInstance().activityResumed(this);
}

@Override
public void onPause() {
  super.onPause();
  Liquid.getInstance().activityPaused(this);
}

@Override
public void onStop() {
  super.onStop();
  Liquid.getInstance().activityStopped(this);
}

@Override
public void onStart() {
  super.onStart();
  Liquid.getInstance().activityStarted(this);
}

@Override
public void onDestroy() {
  super.onDestroy();
  Liquid.getInstance().activityDestroyed(this);
}

Identify your users Edit

In order to keep track of a specific user between different sessions and devices (or different app installations) you must identify it with a unique identifier. This will allow you to use analytics based on their information.

This identifier is usually a strong UUID, e.g: "02318f2cdd156d78fd4431". We recommend using your back-end database ID to identify a user. Alternatively, you can use an email or username, provided they cannot be changed.

/* Only use this method on anonymous users. */

Liquid.getInstance().identifyUser("USER_ID");

Tipically, you know more about your user than only his identifier. Liquid allows you to create analytics based on this information through Key-Value user attributes (on a HashMap<String, Object>).

For each of the above situations, you should identify your user with one of the following two methods, respectively:

Liquid.getInstance().identifyUser("USER_ID", attributes);
Liquid.getInstance().setUserAttributes(attributes);

It is not mandatory to the user attributes at the moment of user identification. You can set their attributes later using setter methods.

Note

Liquid SDK keeps a cache of your previously identified user. This means that you don’t need to identify your user each time your app is open.

Anonymous users Edit

If you never identify your user, all activity will be tracked anonymously. As soon as a user is identified, all that anonymous activity will be automatically aliased to the identified user. This means that you’ll no longer see the anonymous user, but the identified one.

This process of user aliasing is automatic, is the default behavior and is higly recommended that you alias your users. However, if you don’t want this behavior, you may append the prefix alias:false when identifying your user, like shown in the following example:

Liquid.getInstance().identifyUser(identifier, attributes, false);

Note

Our recommendation is to keep your users identified as much as you can, even after they logout. This will ease the analysis of their behaviour. However, if for any reason you really want to turn the SDK back to the anonymous state, you can use the method Liquid.getInstance().resetUser();. This will create a new anonymous user (with a new Unique ID and no custom attributes). If your user is already anonymous, this will only wipe their attributes, leaving the unique_id intact.

Track events Edit

Probably the most important entity of analytics is an event. Events can be anything you want in the context of your application. It can be a click on a button, a product that is bought or any other interaction. Events are identified by a unique name, and can (optionally) have attributes (Key-Value).

Important note

Event names should have a minimum length of 3 characters and a maximum of 50. Also note that Liquid uses the attribute name to store the event name. If you set a custom event attribute with the key name it will be overrided by the SDK.

You can track an event anytime you want on your code, using one of the following methods:

Liquid.getInstance().track("Click Profile Page");
Liquid.getInstance().track("Buy Product", attrs);
Track your Monetization metrics

In order to take advantage of the Monetization section of the Dashboard view, you have to send a price attribute on your events, make sure to check the Monetization settings section for detailed information.

Track user attributes Edit

User attributes are Key-Value objects stored in the form of a HashMap<String,Object>.

Data types of these attributes can be: Integer, String, Float, Boolean, Date and null.

An example that includes all this attributes could be:

HashMap<String,Object> attrs = new HashMap<String,Object>();
attrs.put("age", 30);
attrs.put("name", "John");
attrs.put("frequence", 1.3);
attrs.put("facebook_account", true);
attrs.put("last_activity", new Date());
attrs.put("social_profile", null);

Note

You should not store nothing more than user information on this collection, i.e. do not store information related with the device (like model or carrier). This information is stored on the device entity, as explained below.

Automatic device tracking Edit

Information about the user device is automatically saved by Liquid SDK.

You don’t need to worry about tracking information of the device. The following device attributes are always included on analytics (example):

{
  "App Name": "Wonderful App",
  "App Version": 1.4,
  "App Release Version": 1.4,
  "App Bundle": "io.lqd.wonderfulapp",
  "Vendor": "ZTE",
  "Model": "Blade",
  "Device name": "My Blade",
  "System version": 7.1,
  "System language": "en",
  "Locale": "en-US",
  "Screen size": "640x960",
  "Carrier": "Vodafone",
  "Internet Connectivity": "WiFi"
}

Track device location Edit

If you have information about user geolocation (a Location) you can use Liquid to track device location. All you need to do is to inform Liquid SDK about current device location using the following method:

Liquid.getInstance().setCurrentLocation(Location l);

Liquid doesn’t automatically track location changes. This means you’re responsible to inform Liquid SDK each time device location changes.

From this moment on, all data points sent to Liquid will include latitude and longitude attributes associated to Device entity.

Setup push notifications and in-app messages Edit

To send push notifications and in-app messages to your users through Liquid’s formulas you’ll need to add some code that registers your device with Liquid and GCM (Google Cloud Messaging)

If you don’t have a GCM Sender ID, please visit the tutorial about setting up GCM. The GCM Sender ID is the project number in the Google Console and should look something like “670330094152”.

Then, add it to Liquid’s instance:

// MainActivity.java
Liquid liquid;

@Override
protected void onCreate(Bundle savedInstanceState) {
  liquid = Liquid.initialize(this, "YOUR_APP_TOKEN");
  liquid.setupPushNotifications(this, "YOUR_GCM_SENDER_ID");
}

Install via Gradle

Add the dependency to your project-level build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
dependencies {
  ...
  classpath "com.google.gms:google-services:1.5.0-beta2"
}

Add the plugin and the dependency to your app-level build.gradle file:

// build.gradle file
apply plugin: "com.google.gms.google-services"
...
dependencies {
  ...
  compile "com.google.android.gms:play-services-gcm:8.3.0"
}

Add Permissions to Application Manifest

The following permissions are required, replace YOUR_APP_PACKAGE_NAME with your own app package name.:

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<permission android:name="YOUR_APP_PACKAGE_NAME.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="YOUR_APP_PACKAGE_NAME.permission.C2D_MESSAGE" />

<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE"/>

Next, register the Google receiver and the Liquid’s message handling service adding the following snippet inside the <application> tag:

<!-- AndroidManifest.xml -->
<receiver
  android:name="com.google.android.gms.gcm.GcmReceiver"
  android:permission="com.google.android.c2dm.permission.SEND" >
  <intent-filter>
      <action android:name="com.google.android.c2dm.intent.RECEIVE" />
      <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
      <category android:name="YOUR_APP_PACKAGE_NAME" />
  </intent-filter>
</receiver>

<service
  android:name="io.lqd.sdk.gcm.LQMessageHandler"
  android:exported="false" >
  <intent-filter>
      <action android:name="com.google.android.c2dm.intent.RECEIVE" />
  </intent-filter>
</service>

Important note

Android devices with an SDK version older than 8.0 cannot receive Google Cloud Messaging notifications.

Advanced settings

If you already have your own mechanism to send push notifications, you just need to inform Liquid of your user GCM Registration ID, like this:

public class YourIntentService extends GCMBaseIntentService {

  protected void onRegistered(Context context, String registrationId) {
    Liquid.getInstance().setGCMregistrationID(registrationId);
  }
}
Payload in push notifications

Liquid sends the following payload to Android devices:

  • Title - lqd_title
  • Message - lqd_message
  • Sound - lqd_sound

If add custom JSON, it will be merged to the root of the payload.

Important note

Your JSON will have priority over the default keys (lqd_*).

Custom icon in notifications

If you want to add a custom icon to your notification, add the following meta-data inside the <application> tag and place your custom icon inside the drawable folder.

<!-- AndroidManifest.xml -->
<aplication>
...
  <meta-data android:name="io.lqd.sdk.notification_icon"
    android:resource="@drawable/CUSTOM_ICON"/>
...
</aplication>
Configure GCM Sender ID

To send Push Notifications as your App, Liquid must authenticate with Google GCM, using your App’s GCM Auth Key.

Check Setup push notifications certificates section to know how to import it to Liquid dashboard.

3. Dynamic Variables (Liquid Variables)

A Liquid Variable is a variable that holds a dynamic value which can change depending on rules that you define remotely on Liquid dashboard. You can transform any old-fashioned static variable into a Liquid Dynamic Variable just by replacing them with a Liquid method.

As an example, assume that you want to turn a static background color that was used like:

getResources().getColor(R.color.customColor);

into a dynamic background color. You just need to replace it with something like:

Liquid.getInstance().getColorVariable("bgcolor", fallbackColor);

As soon as you compile your code and use this variable in your app, it will appear on your Liquid dashboard.

Read our default Variables recommendations

Getting values for variables Edit

Based on variable names, Liquid returns values on five different data types: Date, String, int, float and boolean. These methods return the fallbackValue if the value is not present or valid.

Liquid.getInstance().getStringVariable(variableKey, fallbackValue);
Liquid.getInstance().getColorVariable(variableName, fallbackValue);
Liquid.getInstance().getDateVariable(variableKey, fallbackValue);
Liquid.getInstance().getIntVariable(variableKey, fallbackValue);
Liquid.getInstance().getFloatVariable(variableKey, fallbackValue);
Liquid.getInstance().getBooleanVariable(variableKey, fallbackValue);

Fallback values Edit

You should always define fallback values for your dynamic variables. This will avoid strange behaviors in cases where your app is first launched without an Internet connection, but also if you accidentally delete a variable in Liquid dashboard, or define a different data type between your code and Liquid dashboard.

Each time you use a dynamic variable, you can define its fallback value in the methods:

Liquid.getInstance().getColorVariable(loginBgColor, Color.GREEN);
Liquid.getInstance().getDateVariable(promoDay, date);
Liquid.getInstance().getStringVariable(title, "Hello");
Liquid.getInstance().getIntVariable(abTestingLoginVersion, 3);
Liquid.getInstance().getFloatVariable(discount, 0.25);
Liquid.getInstance().getBooleanVariable(showAds, true);

To ease the development process, each time you use a dynamic variable, its fallback value will be sent to Liquid dashboard and stored as default value (only when your app is compiled with Liquid in development mode).

Fallback values vs. Targets Edit

If you use more than a variable for a Target (defined on Liquid dashboard), all variables affected by that target become dependant on each others.

This means that, if a variable value is fallen back, all the other variables on the same Target will be also fallen back.

Situations like these will only occur if you do something really wrong in your variable settings (e.g. data type mismatch between code and Liquid dashboard), but this mechanism will ensure consistency in your app.

Loading values Edit

Each time your app is open or closed/paused, new values are requested to Liquid. However, they are not immediately loaded by the SDK as it could cause strange behaviors in front of user eyes. By default, when new values are available, they will only be loaded the next time your app is open.

You can change this behavior just by setting AutoLoadVariables variable to YES after initializing Liquid singleton:

Liquid.getInstance().setAutoLoadVariables(true);

Asynchronous events Edit

Optionaly, you can be notified of Liquid’s internal events by implementing LiquidOnEventListener interface on your code, to take action when:

  • When values are received from Liquid dashboard (not necessarily loaded)
  • When values are loaded

As an example, let’s assume you want to take action in your activity, then you should implement the LiquidOnEventListener interface like this:

// Your activity
public class MainActivity extends Activity implements LiquidOnEventListener {
  // Define your code here...
}

and your implementation file should be like this:

@Override
public void onValuesReceived() {
  // Do something with new values, e.g: Liquid.getInstance().loadNewValues();
}

@Override
public void onValuesLoaded() {
  bg.setBackgroundColor(Liquid.getInstance().getColorVariable("bgcolor", Color.GRAY));
  // Define your code here...
}

4. Recommendations and Best Practices

Fallback variables organization Edit

Most of the times, it is useful to have all dynamic variables and their fallback values in the same place.

This kind of practice not only improves code organization and readability, but also reutilization of static values in your code.

This way, we recommend you to create a static class file, like:

public class DefaultValues {
  public static final String WELCOME_MESSAGE = "Ahoy!";
  public static final int BG_COLOR = Color.BLUE;
  public static final float DISCOUNT = 0.25f;
  public static final boolean SHOW_ADS = true;
}

By doing that you easily change the default variables without changing all activities, like:

bg.setBackgroundColor(Liquid.getInstance().getColorVariable("bgcolor", DefaultValues.bg_color));

while keeping a list of your dynamic variables and fallback values in one unique place.

Important note

Most of the times, you’ll want to make sure that your default values (in Liquid dashboard) are the same as the fallback values (in your code).

Setup push notifications certificates Edit

Liquid needs to authenticate with the Google Cloud Messaging service in order to send push notifications to your users. We have prepared a step-by-step guide to help you get a GCM key and set it up on your app settings, but if you already have a GCM authentication key go directly to the last step.

Set up your GCM auth key

  • Go to Google Developers Console and create a project for your app if you haven’t already. Setup your GCM key on your app settings view

  • Write your project’s name and click create. Setup your GCM key on your app settings view

  • Then follow this link to enable Google Services for your app and get a configuration file for your project. Choose your app name from your Developer Console. Enter the package name of your application and Continue. Setup your GCM key on your app settings view

  • Select Cloud Messaging and enable it. Setup your GCM key on your app settings view

  • After enabling it you will get your Server API Key and Sender ID. Setup your GCM key on your app settings view

  • Continue to generate configuration file. Download google-service.json and copy it in the app/ or mobile/ module directory in your Android project or in your application’s root folder. Setup your GCM key on your app settings view

  • Finally copy the Server API Key into the Notification Settings in your App Settings page in Liquid. Setup your GCM key on your app settings view

Besides adding your Server API Key to our platform, you need to prepare your Android app to correctly parse Push Notifications sent by us. This is a technical step that involves changing the code on your app; if you haven’t done so, follow the steps on the Setup push notifications and in-app messages section.

Monetization settings Edit

On the Dashboard section (check the demo) you will find your app’s Monetization metrics (Conversions, Purchases and Revenue) for the last 30 days. In order to set these values properly follow the guide bellow.

Conversions

A conversion can be any event (such as a purchase or a sign-up) that you consider important in the context of your app. You can pick up to 5 events and you’ll instantly get insights on how these events performed (converted) in the last 30 days:

  • click on Settings and select up to 5 events that you consider to be a conversion Track a Conversion whenever a user does any of these events

Purchases

Every event that has the attribute price is automatically considered a purchase.

An example would be:

HashMap<String,Object> attrs = new HashMap<String,Object>();

// The price value must be an integer
attrs.put("price", 10);
Liquid.getInstance().track("Buy Product", attrs);

Revenue

The sum of all values (integer) of the attribute price included on all events.

Setup AppsFlyer integration Edit

If you’re already using AppsFlyer in your app, you can view the user acquisition source on Liquid following this guide:

  • On your app, after initializing our SDK set AppsFlyer customer user id to Liquid device unique_id:
AppsFlyerLib.setCustomerUserId(Liquid.getInstance().getDeviceIdentifier());
  • Select Liquid on the AppsFlyer integration menu, they’ll ask for your Liquid App key that is available in your app settings page.