---
title: Error Analysis - Android
description: Implement error tracking and crash reporting in your Android app with the CSQ SDK to identify and resolve issues affecting user experience
lastUpdated: 11 March 2026
source_url:
  html: https://docs.contentsquare.com/en/csq-sdk-android/experience-analytics/error-analysis/
  md: https://docs.contentsquare.com/en/csq-sdk-android/experience-analytics/error-analysis/index.md
---

Note

This feature is part of [Experience Monitoring ↗](https://contentsquare.com/platform/experience-monitoring/), which is only available on Enterprise plans or as an add-on to Pro plans. Contact your Customer Success Manager or [sales ↗](https://contentsquare.com/request-a-demo/) to learn more.

## Prerequisites

### Screen tracking implemented

Tracking will start at the 1st screenview event, it is required to have screen tracking implemented. Make sure to follow the [Android Track screens](../track-screens/) sections.

### Reminder about User consent

If you are in the process of implementing the SDK for the 1st time (or choose to take this update as an opportunity to review your Privacy related implementation), make sure to follow the [Android Privacy](../privacy/) sections.

## API errors

### Automatic network inspection

By using code instrumentation, network calls will be instrumented to collect network data. This way, two largely used network stacks are supported, and all the libraries that use them:

* [OkHttp ↗](https://square.github.io/okhttp/),
* [HttpURLConnection ↗](https://developer.android.com/reference/java/net/HttpURLConnection)

#### Adding the Gradle plugin

With the use of a Gradle plugin, an instrumentation of your code will be performed to collect the data about network errors.

Add the Contentsquare Network Gradle plugin to the plugins block in both your root-level and app-level Gradle files:

* Kotlin

  **build.gradle.kts**

  ```kotlin
  plugins {
     id("com.contentsquare.error.analysis.network") version "1.7.0" apply false
  }
  ```

  **app/build.gradle.kts**

  ```kotlin
  plugins {
     id("com.contentsquare.error.analysis.network")
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  plugins {
     id "com.contentsquare.error.analysis.network" version "1.7.0" apply false
  }
  ```

  **app/build.gradle**

  ```groovy
  plugins {
     id "com.contentsquare.error.analysis.network"
  }
  ```

#### Task added

The plugin adds new tasks for network code instrumentation: `transformVariantClassesWithAsm`

#### Configure Gradle plugin

By default the plugin is enabled for each variant, there are three ways to disable the Gradle plugin:

##### Build type

* Kotlin

  **build.gradle.kts**

  ```kotlin
  android {
     buildTypes {
        debug {
           configure<com.contentsquare.gradle.error.analysis.network.ErrorAnalysisNetworkExtension> {
                 setInstrumentationEnabled(false)
           }
        }
     }
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  android {
     buildTypes {
        debug {
           errorAnalysisNetwork {
                 setInstrumentationEnabled(false)
           }
        }
     }
  }
  ```

##### By flavor

* Kotlin

  **build.gradle.kts**

  ```kotlin
  android {
     flavorDimensions += "example"
     productFlavors {
        create("enable") {
           dimension = "example"
        }
        create("disable") {
           dimension = "example"
           configure<com.contentsquare.gradle.error.analysis.network.ErrorAnalysisNetworkExtension> {
                 setInstrumentationEnabled(false)
           }
        }
     }
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  android {
     flavorDimensions "example"
     productFlavors {
        enable {
           dimension "example"
        }
        disable {
           dimension "example"
           errorAnalysisNetwork {
                 setInstrumentationEnabled(false)
           }
        }
     }
  }
  ```

##### With a Gradle properties

**gradle.properties**

```properties
errorAnalysisNetworkInstrumentationEnabled=false
```

Command line:

```shell
./gradlew :app:assembleDebug -PerrorAnalysisNetworkInstrumentationEnabled=false
```

### Manual inspection

Note

Our recommendation is to use the Gradle plugin.

#### OkHttp interceptor

If your project is using OkHttp client, an interceptor (`CsqOkHttpInterceptor`) can be added to collect all the network errors:

* Kotlin

  ```kotlin
  import com.contentsquare.api.contract.CsqOkHttpInterceptor


  OkHttpClient().newBuilder()
  .addInterceptor(CsqOkHttpInterceptor())
  .build()
  ```

* Java

  ```java
  import com.contentsquare.api.contract.CsqOkHttpInterceptor;


  new OkHttpClient().newBuilder()
  .addInterceptor(new CsqOkHttpInterceptor())
  .build();
  ```

#### Custom implementation

If no other solution works, the `CSQ.trackNetworkMetric()` API can be used to send custom Network Metric events.

Multiple data will need to be gathered: **URL** and **method** at the creation of the metric, and **status code** after the request is done.

To work properly, the `NetworkMetric` object must be created just before the request and `CSQ.trackNetworkMetric(metric)` must be called just after the request, to have the time metrics.

* Kotlin

  ```kotlin
  import com.contentsquare.api.model.HttpMethod
  import com.contentsquare.api.model.NetworkMetric


  val metric = NetworkMetric(url, HttpMethod.GET)


  // execute your request...


  // fill the network metric with result
  metric.statusCode = statusCode
  metric.responseHeaders = responseHeaders // (optional)
  metric.responseBody = "Hi there !".toByteArray() // (optional)


  CSQ.trackNetworkMetric(metric) // will stop and send the metric
  ```

* Java

  ```java
  import com.contentsquare.api.model.HttpMethod;
  import com.contentsquare.api.model.NetworkMetric;


  NetworkMetric metric = new NetworkMetric(url, HttpMethod.GET);


  // execute your request...


  // fill the network metric with result
  metric.setStatusCode(code);
  metric.setResponseHeaders(responseHeaders); // (optional)
  metric.setResponseBody("Hi there !".getBytes(StandardCharsets.UTF_8)); // (optional)


  CSQ.trackNetworkMetric(metric); // will stop and send the metric
  ```

### Removing Personal Data in request URL path

By default, the API errors feature collects the URL path of the failed API requests. To prevent the collection of Personal Data in the URL path, you can rewrite the request URL path with the `CSQ.setUrlMaskingPatterns` SDK API.

Replace a step of the path - meaning between two slashes (/) - containing Personal Data with a variable:

* `:user_id` becomes CS\_ANONYMIZED\_USER\_ID
* `:address` becomes CS\_ANONYMIZED\_ADDRESS

#### Example

* Kotlin

  ```kotlin
  CSQ.setUrlMaskingPatterns(
     listOf("https://www.contentsquare.com/users/:user_id/address/:address")
  )
  ```

* Java

  ```java
  CSQ.setUrlMaskingPatterns(
     List.of("https://www.contentsquare.com/users/:user_id/address/:address") );
  ```

##### Result

| URL before masking | URL after masking |
| - | - |
| `https://www.contentsquare.com/users/123/address/castle+black` | `https://www.contentsquare.com/users/CS_ANONYMIZED_USER_ID/address/CS_ANONYMIZED_ADDRESS` |

### Validate API error integration

#### Validate API error collection is enabled

If in-app features are enabled, an info log should appear when API Error collection has successfully been enabled (see [Android Debugging and Logging](../in-app-features/#debugging-and-logging) section).:

```plaintext
CSLIB: Api Error collection is enabled
```

#### Validate API error collection

If you have [logging enabled](../in-app-features/#debugging-and-logging), you will see API errors:

* Displayed in [Contentsquare Log Visualizer](../in-app-features/#viewing-logs-in-the-contentsquare-platform).
* As an Info log in Logcat:

```plaintext
CSLIB: API Error - 401 GET https://api.client.com
```

### How API errors works

#### Initialization

The way our SDK works is by auto-starting with the application launch and collects the API errors through the instrumented code added by the Gradle plugin.

#### Configuration

Once started, our SDK fetches its config from our servers. It will start collecting data from network events if the API errors setting is enabled in the config (this is handled by the Contentsquare team).

#### API errors collection

The SDK monitors only the API errors with response code equal or above 400, and generates analytics data. These events are then locally stored, and eventually sent to our servers in batches.

Warning

For API errors to be tracked and processed, the session has to be tracked (included in tracked users and not opted-out) and a first screenview event has to be sent before.

#### Sending API errors data

For each network error, a new event will be sent in analytics and Session Replay data. Check the following sections to learn more about how data is processed and sent:

* [Analytics requests](../data-collection/#sending-data)
* [Session Replay requests](../session-replay/#requests)

### API Troubleshooting Details

API errors troubleshooting details enables you to collect more information about API errors so you can troubleshoot errors faster.

With this feature you will be able to see three types of additional API error details in the Event Stream of Session Replay.

* The HTTP headers of the request and the response.
* The body (the data sent by the request or received in the response).
* The query parameters of the request endpoint (of the URL of the information you request for).

Note

This feature is part of [Experience Monitoring ↗](https://contentsquare.com/platform/experience-monitoring/), which is only available on Enterprise plans or as an add-on to Pro plans. Contact your Customer Success Manager or [sales ↗](https://contentsquare.com/request-a-demo/) to learn more.

See [API Troubleshooting Details ↗](https://support.contentsquare.com/hc/en-us/articles/37271885035537) for more details.

### Collected data points

Only network calls in error (response code above 400) will be collected. Here the exhaustive list of data collected:

* Response code
* URL (without query strings)
* HTTP method
* Timestamp of the request
* Timestamp of the response

### Known limitations and recommendations

#### Conflict with Firebase Performance using code instrumentation

Code instrumentation of requests made using HttpURLConnection does not work well with Firebase Performance plugin. Network events will not be logged when using Contentsquare Error Analysis network and Firebase performance plugin (only one of the two will log events). If you want to use both libraries, prefer using interceptors than code instrumentation.

## Crash Reporter

### Upload mapping file

Android mapping files are generated during the process of obfuscating Android application code using tools like ProGuard. A mapping file for your app will be generated for all [obfuscated builds ↗](https://developer.android.com/build/shrink-code) at compile time.

[Download the mapping file example](https://docs.contentsquare.com/ff-sample-mapping.txt) generated when building the [Contentsquare Android sample app ↗](https://github.com/ContentSquare/contentsquare-android-sample).

In order to produce readable crash reports from builds that have been obfuscated, Contentsquare requires to upload the mapping file produced by your build to our servers. To simplify this process, we've provided a Gradle plugin that you can integrate into your build. It adds a distinct Gradle task that will be executed immediately after the build is done. This new task will be automatically triggered on assemble task for any minified build.

#### Adding the Gradle plugin

Add the Contentsquare Crash Gradle plugin to the plugins block in both your root-level and app-level Gradle files:

* Kotlin

  **build.gradle.kts**

  ```kotlin
  plugins {
     id("com.contentsquare.error.analysis.crash") version "1.7.0" apply false
  }
  ```

  **app/build.gradle.kts**

  ```kotlin
  plugins {
     id("com.contentsquare.error.analysis.crash")
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  plugins {
     id "com.contentsquare.error.analysis.crash" version "1.7.0" apply false
  }
  ```

  **app/build.gradle**

  ```groovy
  plugins {
     id "com.contentsquare.error.analysis.crash"
  }
  ```

#### Configuring the Gradle Plugin

To use the plugin, you must provide it with the relevant credentials to be able to upload the mapping file.

##### Get project ID

1. Login to the Contentsquare platform on [https://app.contentsquare.com ↗](https://app.contentsquare.com)
2. Make sure to be on the right project
3. The project ID can be found in the URL query parameter `project`: `https://app.contentsquare.com/#/{MODULE_NAME}?project={PROJECT_ID}&hash={HASH}`

##### Get project credentials

Follow the dedicated documentation from the Help Center to get the **client ID** and **client Secret**: [How to create API credentials ↗](https://support.contentsquare.com/hc/en-us/articles/9292880837660).

##### Use credentials

You can do this by setting the `uploadCredentials` property of the errorAnalysisCrash extension in your app-level `build.gradle` or `build.gradle.kts` file, as shown below. The errorAnalysisCrash extension is available on all build types and product flavours.

* Kotlin

  **build.gradle.kts**

  ```kotlin
  android {
     buildTypes {
        release {
           configure<ErrorAnalysisCrashExtension> {
              uploadCredentials {
                 projectId = <your project Id>
                 clientId = "<your client Id>"
                 clientSecret = "<your client secret>"
              }
           }
        }
     }
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  android {
     buildTypes {
        release {
           errorAnalysisCrash {
              uploadCredentials {
                 projectId = <you project Id>
                 clientId = "<your client Id>"
                 clientSecret = "<your client secret>"
              }
           }
        }
     }
  }
  ```

#### Disable Upload

By default, the mapping file will be uploaded automatically. If you need to disable the upload, you can do it by adding a specific flag `mappingFileUploadEnabled` to the plugin configuration:

* Kotlin

  **build.gradle.kts**

  ```kotlin
  android {
     buildTypes {
        release {
           configure<ErrorAnalysisCrashExtension> {
              mappingFileUploadEnabled = false
              uploadCredentials {
                 ...
              }
           }
        }
     }
  }
  ```

* Groovy

  **build.gradle**

  ```groovy
  android {
     buildTypes {
        release {
           errorAnalysisCrash {
              mappingFileUploadEnabled = false
              uploadCredentials {
                 ...
              }
           }
        }
     }
  }
  ```

It is also possible to disable the upload using the command line when the assemble task is triggered by using the flag `errorAnalysisCrashMappingFileUploadEnabled` as follow:

```plaintext
./gradlew app:assembleRelease -PerrorAnalysisCrashMappingFileUploadEnabled=false
```

Doing that, the upload task will be disabled and you will see the following log:

```plaintext
[ErrorAnalysisCrashPlugin] uploadContentsquareMappingFileRelease disabled for release
```

#### ProGuard Configuration

To ensure that we can provide line numbers and file names in the crash reports, add the following configuration to your ProGuard file:

```plaintext
-keepattributes SourceFile,LineNumberTable # Keep file names and line numbers
```

### Validate Crash reporter integration

#### Validate crash collection is activated

If in-app features are enabled, an info log should appear when the Crash reporter has successfully been initialized (see [Android Debugging and Logging](../in-app-features/#debugging-and-logging) section).:

```plaintext
CSLIB: Crash reporter is enabled
```

#### Validate crash reporting

To test that the Crash Reporter is working properly, you can force a crash in your application. The next time you start your application, the crash will be sent to our servers. If you have [logging enabled](../in-app-features/#debugging-and-logging), you will see the upload reflected in the log:

```plaintext
CSLIB: Crash event detected and sent for userID: <user-id>, session: <session-number> on screen: <screen-number> crashID: <crash-id>
```

### How Crash Reporter works

#### Initialization

Crash Reporter is started automatically and begins to report basic information for crashes in your application when it is launched.

#### Configuration

Once started, our SDK fetches its configuration from our servers. It will start reporting crashes if the Crash Reporter setting is enabled (this is handled by the Contentsquare team).

#### Reporting

When a crash occurs, a report is created and stored locally in the device. Once the app is launched again, the report is sent to our servers and then removed from the local storage.

Warning

For crashes to be reported and processed, the session has to be tracked (included in tracked users and not opted-out) and a first screenview event has to be sent before.

#### Sending crash data

For each crash, a new event will be sent to Analytics and Session Replay data when the app is launched again after the crash occurred and the network conditions allow for the server to be reached.

### Collected data points

The Crash Reporter will capture any crashes caused by an unhandled exception in applications written in Java or Kotlin. It will collect information about the application, system, process, threads, stack traces and some other event metadata you can find in [collected data points](../data-collection/#collected-data-points)

### Known limitations and recommendations

Native crashes from applications written using C or C++ are currently not supported.

#### Compatibility with other crash reporters

It is possible that the Crash Reporter will work with other SDKs, but we cannot guarantee it. Android has a global error handling class and therefore we rely on other SDKs forwarding the error on to us in the event of a crash, should they have been registered first. If the Contentsquare Crash Reporter is registered first, it will forward on errors to any other registered handlers.

Based on our tests, we can confirm it is compatible with Firebase Crashlytics.

## WebView errors

Errors occurring in web pages loaded in WebViews can be collected if Webview tracking is setup in your app.

See 📚 [Webview Tracking implementation](https://docs.contentsquare.com/en/webview-tracking-tag/).

Once WebView tracking is implemented, errors collection can be set up.

See 📚 [Errors (in WebView)](https://docs.contentsquare.com/en/webview-tracking-tag/error-analysis/)

## Compatibility

### Dependencies list

| Package | Name | Version |
| - | - | - |
| androidx.annotation | annotation | 1.5.0 |

## Impact on Performance

We always strive to be non-intrusive, and transparent to the developers of the client app. We apply this rule on the performance as well. These are the technical specifics we can share on performance, if you have any questions feel free to reach out to us.

The following performance results were obtained under the following conditions:

| Condition | Value |
| - | - |
| Device model | Pixel 5 |
| Android version | 13 |

We used [Android Microbenchmark ↗](https://developer.android.com/topic/performance/benchmarking/microbenchmark-overview) to measure the time added by our implementation.

Note

The numbers provided below will vary depending on the user's device, Android version, SDK version.

The instrumented code added is running in *less than 1ms* per request: our benchmarks show less 400µs.

About CPU and memory, the overhead of adding the collection of network error is negligible.
