Analytics for Android

Maven Central

Analytics for Android makes it simple to send your data to any tool without having to learn, test or implement a new API every time.

All of Segment’s client sources are open-source, so you can view Analytics for Android on Github, or check out our browser and server-side sources too.

Want to stay updated on releases? Subscribe to the release feed.

Analytics for Android only supports any Android device running API 14 (Android 4.0) and higher. This includes Amazon Fire devices.

Getting Started

About mobile connection modes

Segment defaults to using cloud-based connection mode (“cloud-mode”) for any destination connected to a mobile source, because this can help decrease the size of your final app package. When you use cloud-mode, Segment sends messages to the Segment servers, and then translates and forwards that data on to the downstream tools. This way, you only package the Segment mobile library with your app.

However, many destination tools that specifically deal with mobile interactions require that you use a device-based connection mode (“device-mode”) so that they can collect information directly on the mobile device. (You can check the full list of destinations and which connection modes they support.)

If you plan to use destinations that require device-mode, you must package the Segment-integration version of that tool’s SDK along with the Segment source library in your app. The Segment-integration SDK allows you to still collect the data with Segment, but also enables any device-based features, and still saves you space.

When you package a tool’s device-mode SDK with the Segment SDK, Segment sends the data directly to the tool’s API endpoint. Segment then also adds the tool to the integrations object and sets it to false, so that the data is not sent a second time from Segment servers.

For example, if you bundled the Segment SDK and Segment-Intercom library, you would see this in your payload:

"integrations": {
  "Intercom": false

When you package Segment and the Segment-integration SDKs, you must use a dependency manager (such as Cocoapods or Gradle) to ensure that all SDKs are compatible and all of their dependencies are included. Segment does not support bundling mobile SDKs without a dependency manager.

Step 1: Install the Library

The recommended way to install the library for Android is with a build system like Gradle. This makes it simple to upgrade versions and add destinations. The library is distributed using Maven Central. Simply add the analytics module to your build.gradle:

dependencies {
  implementation ''

Packaging SDKs for Device-mode destinations

In the interest of keeping our SDK lightweight, the analytics artifact only installs the Segment destination. This means that all your data will be sent using Segment’s servers to any tools you’ve enabled with server-side-compatible destinations.

As described here, some destinations require or offer Device-mode. If that’s the case, you’ll need to take package the destination SDK, which might require some additional steps.

Now that the SDK is installed and set up, you’re ready to…

Step 2. Initialize the Client

We recommend initializing the client in your Application subclass. You’ll need your Write Key.

// Create an analytics client with the given context and Segment write key.
Analytics analytics = new Analytics.Builder(context, YOUR_WRITE_KEY)
  .trackApplicationLifecycleEvents() // Enable this to record certain application events automatically!
  .recordScreenViews() // Enable this to record screen views automatically!

// Set the initialized instance as a globally accessible instance.


  • Automatically tracking lifecycle events (Application Opened, Application Installed, Application Updated) and is optional, but highly recommended to hit the ground running with core events!
  • This only installs the Segment destination. This means that all your data is sent server-side to tools. To bundle additional destinations client-side, you’ll need to take some additional steps as shown here.

Optional Customizing the Client

The entry point of the library is through the Analytics class. As you might have seen in the quickstart, here’s how you initialize the Analytics client with it’s defaults.

Analytics analytics = new Analytics.Builder(context, writeKey).build();

The Analytics.Builder class lets you customize settings for the Analytics client, including things like the flush interval and packaging Device-mode destinations. Refer to the Javadocs for details on customizable parameters.

We also maintain a global default instance which is initialized with defaults suitable to most implementations.

// You can also register your custom instance as a global singleton.

In general, we recommend using the Builder method as it provides the greatest flexibility. Keep in mind that you can call Analytics.setSingletonInstance only ONCE, so it’s best to stash the initialization code inside your custom Application class.

public class MyApp extends Application {
  @Override public void onCreate() {
    Analytics analytics = new Analytics.Builder(context, writeKey).build();

    // Safely call Analytics.with(context) from anywhere within your app!
    Analytics.with(context).track("Application Started");

Once you have initialized an Analytics client, you can safely call any of it’s tracking methods from any thread. These events are dispatched asynchronously to our servers and Device-mode destinations.

Note: You should only ever initialize ONE instance of the Analytics client. These are expensive to create and throw away, and in most cases, you should stick to our singleton implementation to make using the SDK easier.

Step 3. Add Permissions

Ensure that the necessary permissions are declared in your application’s AndroidManifest.xml.

 <!-- Required for internet. -->
<uses-permission android:name="android.permission.INTERNET"/>


Good to know: For any of the different methods described in this doc, you can replace the properties and traits in the code samples with variables that represent the data collected.

identify lets you tie a user to their actions and record traits about them. It includes a unique User ID and any optional traits you know about them.

We recommend calling identify a single time when the user’s account is first created, and only identifying again later when their traits change.

Example identify call:

Analytics.with(context).identify("a user's id", new Traits().putName("a user's name"), null);

We recommend calling identify a single time when the user’s account is first created, and only identifying again later when their traits change. We’ll remember the previous user id and merge the new traits with the old ones.

// Initially when you only know the user's name
Analytics.with(context).identify(new Traits().putName("Michael Bolton"));

// Sometime later in your app when the user gives you their email
Analytics.with(context).identify(new Traits().putEmail(""));

Hold up though! When you actually put that code in your Android app, you’ll need to replace all those hard-coded strings with details about the currently logged-in user.

The identify call has the following fields:

userId String,optional The database ID for this user.
traits Traits,optional A map of traits about the user, such as their name, email, address, etc.
options Options, optional Extra options for the call.

Currently, the Android library will also send userId and anonymousId as traits as automatically. Additionally, traits will be sent in the context.traits field with every message.


track lets you record the actions your users perform. Every action triggers what we call an “event”, which can also have associated properties.

To get started, our SDK can automatically tracks a few key common events with our Native Mobile Spec, such as the Application Installed, Application Updated and Application Opened. Simply enable this option during initialization.

You’ll also want to track events that are indicators of success for your mobile app, like Signed Up, Item Purchased or Article Bookmarked. We recommend tracking just a few important events. You can always add more later!

Example track call:

Analytics analytics = new Analytics.Builder(context, writeKey)

Analytics.with(context).track("Product Viewed", new Properties().putValue("name", "Moto 360"));

This example track call tells us that your user just triggered the Product Viewed event with a name of “Moto 360.”

track event properties can be anything you want to record, for example:

Analytics.with(context).track("Purchased Item", new Properties().putValue("sku", "13d31").putRevenue(199.99));

The track call has the following fields:

name String,required A name for the tracked action.
properties Properties,optional A map of properties for this action, e.g. revenue if the action was a purchase.
options Options,optional Extra options for the call.

Formatting Order Completed Events

Segment’s Android library provides a number of helper methods so you can easily construct both properties objects and products lists so your Order Completed events conform to our ecommerce specification. Here’s a code example:


// initialize a new properties object
Properties properties = new Properties();

// add orderId and revenue to the properties object
properties.putValue("orderId", String orderId).putValue("revenue", double revenue);

// initialize a new product
Product product1 = new Product(String id, String sku, double price);

// initialize a second product
Product product2 = new Product(String id, String sku, double price);

// add products to the properties object
properties.putProducts(product1, product2);

// pass the properties object into your Order Completed event
Analytics.with(context).track("Order Completed", properties);

Find details on best practices in event naming as well as the track method payload in our Spec.


The screen method lets you you record whenever a user sees a screen of your mobile app, along with optional extra information about the page being viewed.

You’ll want to record a screen event an event whenever the user opens a screen in your app. This could be a view, fragment, dialog or activity depending on your app.

Not all services support screen, so when it’s not supported explicitly, the screen method tracks as an event with the same parameters.

Example screen call:

// category "Feed" and a property "Feed Length"
Analytics.with(context).screen("Feed", new Properties().putValue("Feed Length", "26"));

// no category, name "Photo Feed" and a property "Feed Length"
Analytics.with(context).screen(null, "Photo Feed", new Properties().putValue("Feed Length", "26"));

// category "Smartwatches", name "Purchase Screen", and a property "sku"
Analytics.with(context).screen("Smartwatches", "Purchase Screen", new Properties().putValue("sku", "13d31"));

The screen call has the following fields:

category String,optional* A category for the screen. Optional if name is provided.
name String,optional* A name for the screen. Optional if category is provided.
properties Properties,optional A map of properties for this screen.
options Options,optional Extra options for the call.

Find details on the screen payload in our Spec.


group lets you associate an identified user user with a group. A group could be a company, organization, account, project or team! It also lets you record custom traits about the group, like industry or number of employees.

This is useful for tools like Intercom, Preact and Totango, as it ties the user to a group of other users.

Example group call:

Analytics.with(context).group("a user's id", "a group id", new Traits().putEmployees(20));

The group call has the following fields:

userId String,required The database ID for this user.
groupdId String,required The database ID for this group.
traits Traits,optional A map of traits about the group, such as the number of employees, industry, etc.
options Options,optional Extra options for the call.

Find more details about group including the group payload in our Spec.


alias is how you associate one identity with another. This is an advanced method, but it is required to manage user identities successfully in some of our destinations.

In Mixpanel it’s used to associate an anonymous user with an identified user once they sign up. For KISSmetrics, if your user switches IDs, you can use ‘alias’ to rename the ‘userId’.

Example alias call:


The alias call has the following fields:

newId String,required The new ID to track this user with.
options Options,optional Extra options for the call.

For more details about alias, including the alias call payload, check out our Spec.

Note that the previousId will be the value passed in as the userId, which we cached after you make an identify call. We will pass that value as the previousId when you call alias and pass in a newId. If you have not called identify, the previousId will be the anonymousId.

Selecting Destinations

The alias, group, identify, page and track calls can all be passed an options object that allows you to turn certain destinations on or off. By default all destinations are enabled. (In our other libraries, you could do this in the list of integrations inside the options object.)

For instance, in the snippet below, the first event is sent to all destinations, but the second one is sent to all except Mixpanel.

// Sent to all destinations
Analytics.with(context).track("Viewed Item", new Properties());

// Sent to all destinations, except Mixpanel
Analytics.with(context).track("Purchased Item", new Properties(), new Options().setIntegration("Mixpanel", false));

// Sent only to Google Analytics and Countly
Analytics.with(context).track("Purchased Item", new Properties(), new Options().setIntegration(Options.ALL_INTEGRATIONS_KEY, false).setIntegration("Countly", true).setIntegration("Google Analytics", true));

If you build your own instance of the client, you can also specify a default options object that will be used for each call. In the snippet below, NONE of the analytics events will be sent to Heap.

// Disable Heap destination
Options defaultOptions = new Options().setIntegration("Heap", false);

// Attach the options to our client
Analytics analytics = new Analytics.Builder(context, writeKey).defaultOptions(defaultOptions).build();
// Set the client as a global singleton so it can be called from anywhere

// Now any calls made with this Analytics client won't be sent to Heap
Analytics.with(context).track("Viewed Item", new Properties());

Notice that in the first snippet, we used an Enum to disable the destination, but in the second snippet, we used a String. In general, we recommend, using the Enum method for Device-mode destinations (this way you get type safety, and don’t accidentally disable “GoogleAnalytics” instead of “Google Analytics”), and pass in a String for controlling the behavior of server side destinations.

destination flags are case sensitive and match the destination’s name in the docs (i.e. “AdLearn Open Platform”, “”, “MailChimp”, etc.).

Note: Available at the business level, filtering track calls can be done right from the Segment UI on your source schema page. We recommend using the UI if possible since it’s a much simpler way of managing your filters and can be updated with no code changes on your side.


Context is a dictionary of extra information you can provide about a specific API call. You can add any custom data to the context dictionary that you’d like to have access to in the raw logs. Some keys in the context dictionary have semantic meaning and will be collected for you automatically, e.g. the information about the device the user is on.

AnalyticsContext analyticsContext = Analytics.with(context).getAnalyticsContext();

You can read more about these special fields.

To alter data specific to the device object you can use the following:

AnalyticsContext analyticsContext = Analytics.with(context).getAnalyticsContext();
analyticsContext.device().putValue("advertisingId", "1");

If you’d prefer to opt out of automatic data collection, simply clear the context right after initializing the client. It’s important to do this BEFORE sending any events.

Analytics analytics = new Analytics.Builder(context, writeKey).defaultOptions(defaultOptions).build();
AnalyticsContext context = analytics.getContext();


You can retrieve the anonymousId set by the library by using:



The reset method clears the SDK’s internal stores for the current user and group. This is useful for apps where users can log in and out with different identities over time.

Clearing all information about the user is as simple as calling:


Events queued on disk are not cleared and are uploaded the next time the app starts.

Note: Each time you call reset, a new AnonymousId is generated the next time the app is opened, which can impact the number of Monthly Tracked Users (MTUs) you process.


If you run into any issues while using the Android library, we recommend turning on logging to help us trace the issue. The default singleton instance will have logging turned on if your application is in debug mode. If you’re using a custom instance, simply attach a LogLevel to the Builder.

Analytics analytics = new Analytics.Builder(context, writeKey).logLevel(LogLevel.VERBOSE);

You can choose to disable logging completely (LogLevel.NONE), turn on basic logging for the SDK (LogLevel.BASIC), turn on basic logging for Device-mode destination (LogLevel.INFO), or simply log everything (LogLevel.VERBOSE). We recommend turn logging off in production modes of your app. Logging also helps you see how long destinations take to complete their calls and discover bottlenecks.

Proxy HTTP Calls

You can point the Android SDK to your own hosted proxy of the Segment API. This will run the HTTP traffic for the Segment API through the proxy.

Analytics analytics = new Analytics.Builder(this, ANALYTICS_WRITE_KEY) //
        .connectionFactory(new ConnectionFactory() {
          @Override protected HttpURLConnection openConnection(String url) throws IOException {
            String path = Uri.parse(url).getPath();
            // Replace YOUR_PROXY_HOST with the address of your proxy, e.g.
            return super.openConnection("YOUR_PROXY_HOST" + path);

Automatic Screen Tracking

Our SDK can automatically instrument screen calls. It uses the label of the activity declared in the manifest as the screen name. Fragments and views do not trigger screen calls. However you can do so manually with the screen method directly.

Analytics analytics = new Analytics.Builder(context, writeKey)


Local device stats help you quickly see how many events you’ve sent us, the average time taken for bundled destinations to run, etc.

StatsSnapshot snapshot = Analytics.with(context).getSnapshot();

Bleeding Edge Releases

We publish stable releases every second Wednesday, when we tag and release the master branch.

After releasing, we also merge the dev branch merged into master. In general, code will be available on master for two weeks before being tagged as a stable release. During this period, master is published as a snapshot — the equivalent of bleeding edge releases. We recommend using the snapshot version to try out upcoming features and fixes that have not been published yet. Simply add the snapshots repo to your repository and Gradle will pull in the latest snapshot build.

repositories {
  maven { url '' }


Depending on the audience for your app (e.g. children) or the countries where you sell your app (e.g. the EU), you may need to offer the ability for users to opt-out of analytics data collection inside your app. You can turn off ALL destinations including Segment itself:

public void optOut(boolean optOut) {

Set the opt-out status for the current device and analytics client combination. This flag is persisted across device reboots, so you can simply call this once during your application (such as in a screen where a user can opt out of analytics tracking).


Middlewares are a powerful mechanism that can augment the events collected by the SDK. A middleware is a simple function that is invoked by the Segment SDK and can be used to monitor, modify, augment or reject events. Source Middleware are available on analytics-android 4.3.0 and later. Destination Middleware are available on analytics-android 4.7.0 and later.

You can register source middleware during construction with the .useSourceMiddleware method on the builder. These middleware are invoked for all events, including automatically tracked events, and external event sources like Adjust and Optimizely.

You can register destination middleware during construction with the .useDestinationMiddleware method on the builder. These middleware are invoked for all events to the specific device-mode destination.

You can use middleware to customize those messages to fit your use case, even if the event was not sent by your source code.

For example, you might want to record the device year class with your events. Previously, you would have to do this everywhere you trigger an event with the Segment SDK. With middleware, you can do this in a single place.

Analytics analytics = new Analytics.Builder(getApplicationContext(), ANALYTICS_WRITE_KEY)
    .useSourceMiddleware(new Middleware() {
      public void intercept(Chain chain) {
        // Get the payload.
        BasePayload payload = chain.payload();

        // Set the device year class on the context object.
        int year = YearClass.get(getApplicationContext());
        Map<String, Object> context = new LinkedHashMap<>(payload.context());
        context.put("device_year_class", year);

        // Build our new payload.
        BasePayload newPayload = payload.toBuilder()

        // Continue with the new payload.

Building on the earlier example, maybe you don’t want to collect any events for older devices. To do this, you can register a middleware that will reject events for older devices.

Analytics analytics = new Analytics.Builder(getApplicationContext(), ANALYTICS_WRITE_KEY)
        .useSourceMiddleware(deviceClassMiddleware) // From earlier example.
        .useSourceMiddleware(new Middleware() {
          public void intercept(Chain chain) {
            // Get the payload.
            BasePayload payload = chain.payload();

            // Check the device year class.
            AnalyticsContext context = payload.context();
            int year = context.getInt("device_year_class", 2009);

            // Reject the event if the year class is < 2012.
            if (year < 2012) {

            // Continue with the event otherwise.

The key thing to observe here is that the output produced by the first middleware feeds into the second. This allows you to chain and compose independent middlewares!

Destination Middleware

If you do not need to transform all of your Segment calls, and only want to transform the calls going to specific destinations, you should use Destination Middleware instead of Source middleware. Destination middleware are available for device-mode destinations only; there are several other ways to transform Segment calls sent to a destination in cloud-mode.

You can use the same middleware object to apply transformations for several different device-mode destinations at the same time. For example, you can use middleware to add a property before sending Checkout Started track events to both a Mixpanel and an Amplitude destination.

The example below adds a property key-value pair to any “Checkout Started” Track event, with the key “step” and the value “1”.

Integration.Factory mixpanelFactory = MixpanelIntegration.FACTORY; //
Integration.Factory amplitudeFactory = AmplitudeIntegration.FACTORY; //
Middleware addPropMiddleware = new Middleware() {
      public void intercept(Chain chain) {
        // Get the payload.
        BasePayload payload = chain.payload();

        if (payload.type() == BasePayload.Type.track) {
          TrackPayload track = (TrackPayload) payload;

          // Check the track call event name
          if (track.event().equals("Checkout Started")) {

            // Create copy of Properties map and add additional property
            ValueMap newProps = new ValueMap();
            newProps.put("step", 1);

            // Build our new payload.
            payload = track.toBuilder().properties(newProps).build();

        // Continue with new payload
Analytics analytics = new Analytics.Builder(getApplicationContext(), ANALYTICS_WRITE_KEY)
    .useDestinationMiddleware(mixpanelFactory.key(), addPropMiddleware)
    .useDestinationMiddleware(amplitudeFactory.key(), addPropMiddleware)

Braze Middleware

If you use the Braze (Appboy) destination in either cloud or device mode you can save Braze costs by “debouncing” duplicate identify() calls from Segment by adding our open-source Middleware tool to your implementation. More information about this tool and how it works is available in the project’s README.

Sending Data to destinations

There are two ways to send data to your analytics services through this library:

  1. Through the Segment servers
  2. Directly from the device using bundled SDK’s

Note: Refer to the specific destination’s docs to see if your tool must be bundled in the app or sent server-side.

Cloud-Mode in Android

When a destination’s SDK is not packaged, but it is enabled from your dashboard, the request goes through the Segment REST API, and is routed to the service’s server-side API as described here.

Packaging device-mode destination SDKs

By default, our analytics artifact does not package Device-mode destinations.

We recommend using device-mode destinations on a need-to-use basis to reduce the size of your application, and to avoid running into the dreaded 65k method limit.

To package Device-mode destinations, first add the dependencies you need. You can find these in our app when you open the destination for your source.

compile('') {
  transitive = true
compile('') {
  transitive = true

After adding the dependency, you must register the destination with our SDK.

Analytics analytics = new Analytics.Builder(context, writeKey)

Anonymizing IP

Segment automatically derives and sets the IP address for client-side (iOS, Android, Analytics.js and Xamarin) events. It is not collected on the device itself, but instead is filled in by our servers when they receive a message. Our servers don’t record the IP address of the client for libraries if the context.ip field is already set.

If you do not want us to record your tracked users’ IP in destinations and S3, you can set your event’s context.ip field to

Migrating to v4

Note: If you are using version 2 of the Android SDK, you’ll have to make few changes to get up and running with version 3.

In version 3, adding a Device-mode destination looks like this:

compile('') {
  transitive = true

// Add other dependencies as you want here
compile('') {
  transitive = true
compile('') {
  transitive = true
compile('') {
  transitive = true

or, if you wanted to use all Device-mode destinations:

compile('') {
  transitive = true

In version 4, the analytics-core artifact is not available any longer. It has been renamed to analytics (which previously packaged all Device-mode destinations). Version 4 of analytics only includes the Segment destination. Which means, to package a Device-mode destination, you must manually add that dependency.

compile ''

compile('') {
  transitive = true
compile('') {
  transitive = true

In addition to adding a dependency, you must point our SDK to the destination.

Analytics analytics = new Analytics.Builder(context, writeKey)


What is the latest version of the library?

The library is published to Maven Central where you can see all the published releases.

Where is the changelog for the library?

We publish a changelog in the Github repository, detailing the changes made in each release.

Can I use the library with Maven?

Yes! You can use our library with Maven or any custom build system since the core SDK is simply a JAR.


How big is the Segment SDK?

The core Segment SDK is extremely lightweight! It contains just under 1k methods, the JAR weighs in at 123kb and the dex size is 113kb.

How can I easily swap out debugging and production keys?

This is trivial if you’re using Gradle and build flavors. Simply provide an alternate analytics.xml for each configuration with different keys in each.

For other cases, you can also construct custom instances of the client, so you can pass in a different key for it. Set it as the singleton instance, and use the same API everywhere else.

class MyApp extends Application {
  @Override public void onCreate() {
    Analytics analytics;
    if(BuildConfig.DEBUG) {
      analytics = new Analytics.Builder(this, debugWriteKey);
    } else {
      analytics = new Analytics.Builder(this, releaseWriteKey);
    Analytics.setSingletonInstance(analytics); // Must be called before any calls to Analytics.with(context)

    // Now Analytics.with will return the custom instance
    Analytics.with(this).track("App Launched");

How does the library queue API calls?

Our library queues API calls and uploads them in batches so that we don’t drain your user’s battery life by making a network request for each event tracked.

As soon as you send as an event, we’ll save it to disk, and if queue size reaches your specified maximum queue size (which is 20 by default), we flush the queue and upload all the events in a single batch. Since the data is persisted right away, there is no data loss even if the app is killed, or the operating system crashes.

The queue behavior may differ for Device-mode destinations. For example, Mixpanel’s SDK queues events and then flushes them when the app goes to the background only.

This is why even if you see events in the debugger, the Device-mode destination may not show them on their dashboards yet, simply because their mobile SDK may still have them queued. The opposite may also happen, that we have some events queued so they haven’t shown up in the debugger, but the Device-mode destination has already sent the events to their servers.

Will my events be delivered even if the app is killed?

We use a persistent disk queue, so even when the app is killed, the events stay on disk. We’ll simply read them from disk and upload the events the next time the app starts. Our queue works on top of Tape, which is designed to even survive process and system crashes.

We save up to 1000 calls on disk, and these never expire.

I need to use the SDK on an older version of Android not supported by your library!

Our Android library has support for back to API level 14 (Android 4.0). You should consider it too! If you can’t do this for your own application, there are three options we’ve recommended to users:

  1. Use an older version of the library that does support your minimum requirements. Keep in mind that there won’t be any updates or bug fixes to those versions, but we do still have clients still using old versions of the library in production.
  2. Skip analytics for users on older devices - you can wrap calls to our SDK in a Build.VERSION check.
  3. Write your own SDK. You can still use most of the tools on Segment using our HTTP API. You can use either our Android or Java source to get a quick headstart.

How can I use a destination specific feature?

…for example, Mixpanel’s push notifications?

If you’re using Device-mode for a mobile destination, you can always access features from that tool’s native SDK.

To make sure you use the same instance of these destinations as we do, you can register a listener that notifies you when the destinations are ready. This will be called synchronously if the destinations are notified, and asynchronously if the destinations aren’t yet ready.

analytics.onIntegrationReady("Crittercism", new Callback() {
  @Override public void onReady(Object instance) {
    // Crittercism uses static methods only, so the instance returned is null.
analytics.onIntegrationReady("Mixpanel", new Callback() {
  @Override public void onReady(Object instance) {
    MixpanelAPI mixpanelAPI = (MixpanelAPI) instance;

For the destinations that return Void, they simply use a shared instance. You can call into the SDK directly. With this API, you’re guaranteed that they’ve been initialized first, and if you ever decide to change the settings for the destination on our dashboard, they’ll be reflected here.

analytics.onIntegrationReady(BundledIntegration.FLURRY, new Callback() {
  @Override public void onReady(Object instance) {
    // Flurry uses static methods only, so the instance returned is null.

Why is my callback not being invoked?

If you’re using the destination callbacks described above, and don’t receive a callback, check your proguard configuration. Any easy way to verify that Proguard is the issue is to disable it completely for a run and see if the callbacks is invoked.

Why is Google Analytics not receiving crash reports?

This is a known bug and is being worked on by Google. We recommend using alternatives like Bugsnag or Crittercism in the meantime.

How should I configure Proguard?

For our SDK, you should add -keep class** { *; } to your proguard configuration. You should also look up any proguard configurations recommended by each of the Device-mode destinations on their respective docs and websites.

How should I use Outbound’s push notifications?

Since Outbound isn’t a Device-mode destination, you’ll have to set it up manually.

First, you’ll need to set up the GCM client as described in the instructions.

Our server’s will look for context.device.token key to send to Outbound. Once you have the registration ID from the step above, simply set it on the context. (This convenience method was added in versino 2.1.6). analytics.getContext().putDeviceToken(registrationId);

The entire code flow looks a bit like this:

String registrationId = loadRegistrationId(); // look up a cached value
if(registrationId == null) {
  registrationId = register(SENDER_ID); // using GoogleCloudMessaging
  save(registrationId); // save the registration ID

Migrate from v2 to v3

NOTE: Version 3 of the SDK is now replaced by version 4. See the section below on upgrading. If you are already using version 2 of the Android SDK, you’ll have to make few changes to get up and running with version 3.

In version 3, we’ve organized the destinations to be make the core SDK even leaner and smaller. This is what the old set up looked like:

compile('') {
  transitive = true

// Add other dependencies as you want here
compile ''
compile ''
compile files('libs/QuantcastAndroidSdk.jar')

In the new version, instead of adding the destinations directly, simply add our destination modules as a dependency instead. This also ensures that the version of the Device-mode destination you’re using matches the one we depend on.

compile('') {
  transitive = true

// Add other dependencies as you want here
compile('') {
  transitive = true
compile('') {
  transitive = true
compile('') {
  transitive = true

Earlier, you could control the debugging behaviour with a boolean flag. In version 3, this is replaced by the more powerful LogLevel Enum, that lets you not only control the logging behavior of our SDK, but also for Device-mode destinations.

Version 2 of the SDK also let you customize the behaviour of the SDK by providing resource values in XML. Version 3 ignores these custom options from XML to simplify behaviour and improve performance. The recommended way to customize the Analytics client is to use the Builder methods instead.

Do you support Phonegap/Cordova?

Yep! You can use our browserify’d analytics-node package just like any other client-side JavaScript library.

How do you handle Unique Identifiers?

A key component of any analytics platform is consistently and accurately identifying users. Some kind of ID must be assigned and persisted on the device so that user actions can be effectively studied. This is especially important for funnel conversion analysis and retention analysis.

Naturally the Analytics SDK needs a unique ID for each user. The very first time an app is launched, our SDK will generated a UUID and save it on disk. This is used as the anonymousId and stays constant for the user on the device. If you want to create a new user on the same device, call reset on the Analytics client.

Our SDK also collects the Advertising ID provided by Play Services. Make sure the Play Services Ads library is included as a dependency for your application. This is the ID that should be used for advertising purposes. This value will be set to context.device.advertisingId.

We also collect the Android ID as Some destinations rely on this field being the Android ID, so take care if you choose to override the default value.


No events in my debugger

  1. Verify you have followed all Getting Started steps
  2. Verify you have entered the correct writeKey for your source
    • If the writeKey you have entered is something other than a string or an empty string your app may crash
    • If the writeKey you have entered is a valid form but not the correct writeKey for your specific source, you will not see an error response. Data will be accepted by Segment but not able to be correctly routed to your source (debugger).
  3. Enable logging to confirm if call is being sent to Segment

No events in my destinations

  1. Verify that your destination is enabled
  2. Verify your destination credentials entered in your Segment dashboard are correct
  3. Make sure the destination can accept what you’re sending:
    • Does the integration have device-mode/cloud-mode support? Confirm you are sending using the correct connection mode.
    • Does the destination accept the type of call you are sending? Not all destinations accept all calls: page, track, etc.
  4. If you are still not seeing data in your destination, continue debugging based on which type of connection mode you are using.

Debugging Device-mode Destinations

If you are using device-mode, you should see the value of that integration set to false in the integrations object. That means that the data is being sent from the device directly to the destination SDK, and not through Segment’s servers. This is expected if you chose to use a device-mode destination’s SDK with Segment’s during installation.

Enable verbose logging and trigger the call in question. You should see a call to Segment triggered as well as to the partner SDK. It will show you exactly which partner method was invoked and the arguments it was invoked with!

Debugging Cloud-mode Destinations

Look at the raw JSON in your debugger. Does the call look like what you expect?

Read through the docs for that destination to see expected event format, behavior and caveats for that destination.

Still having issues?

contact our Product Support team with the following information:

  • The version of our SDK you are using
  • Whether you are using device- or cloud-mode
  • Logs of the call in question
  • Screenshots of the event in the Segment debugger
  • Screenshots of what you are seeing in your destination

This page was last modified: 06 Aug 2020

Get started with Segment

Segment is the easiest way to integrate your websites & mobile apps data to over 300 analytics and growth tools.
Create free account