Usage examples

Library initialization with the extended configuration

To initialize the library with the extended startup configuration, create an instance of the AppMetricaConfig class with appropriate settings and activate the library using the AppMetrica.activate(Context context, AppMetricaConfig config) method. The extended configuration lets you enable/disable logging, set session timeout, pass parameters for tracking pre-installed apps, and more.

Extended configuration settings take effect immediately upon library initialization.

class YourApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // Creating an extended library configuration.
        val config = AppMetricaConfig.newConfigBuilder(API_KEY)
            // Setting up the configuration. For example, to enable logging.
            .withLogs()
            // ...
            .build()
        // Initializing the AppMetrica SDK.
        AppMetrica.activate(applicationContext, config)
        // Automatic tracking of user activity.
        AppMetrica.enableActivityAutoTracking(this)
    }
}
public class YourApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Creating an extended library configuration.
        AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
                // Setting up the configuration. For example, to enable logging.
                .withLogs()
                // ...
                .build();
        // Initializing the AppMetrica SDK.
        AppMetrica.activate(getApplicationContext(), config);
        // Automatic tracking of user activity.
        AppMetrica.enableActivityAutoTracking(this);
    }
}

To configure the library while the application is running, use the AppMetrica class methods.

Sending statistics to an additional API key

Sending data to an additional API key allows you to collect own statistics for these API keys. You can use this to control access to information for other users. For example, to provide access to statistics for analysts you can duplicate sending marketing data for the additional API key. Thus they will only have access to the information they need.

To send data to an additional API key, you must use reporters. Just like for the main API key, you can set up an extended startup configuration for a reporter, send events, profile information, and data about in-app purchases. The reporter can work without the AppMetrica SDK initialization.

Step 1. (Optional) Initialize a reporter with an extended configuration

To initialize a reporter with the extended configuration, create a ReporterConfig class object with the settings you need and activate the reporter using the AppMetrica.activateReporter(Context context, ReporterConfig config) method. This configuration is used for a reporter with the specified API key. You can set up your own configuration for each additional API key.

Alert

The reporter with an extended configuration should be initialized before the first call to the reporter. Otherwise, the reporter will be initialized without a configuration.

// Creating extended configuration of the reporter.
// To create it, pass a ANOTHER_API_KEY that is different from the app's API_KEY.
val reporterConfig = ReporterConfig.newConfigBuilder(ANOTHER_API_KEY)
    // Setting up the configuration. For example, to enable logging.
    .withLogs()
    // ...
    .build()
// Initializing a reporter.
AppMetrica.activateReporter(applicationContext, reporterConfig)
// Creating extended configuration of the reporter.
// To create it, pass a ANOTHER_API_KEY that is different from the app's API_KEY.
ReporterConfig reporterConfig = ReporterConfig.newConfigBuilder(ANOTHER_API_KEY)
        // Setting up the configuration. For example, to enable logging.
        .withLogs()
        // ...
        .build();
// Initializing a reporter.
AppMetrica.activateReporter(getApplicationContext(), reporterConfig);

Step 2. Configure sending data using a reporter

To send data using a reporter, get an object that implements the IReporter interface by the AppMetrica.getReporter(Context context, String apiKey) method and use the interface methods to send reports. If the reporter was not initialized with the extended configuration, calling this method will initialize the reporter for the specified API key.

Example of sending an event:

AppMetrica.getReporter(applicationContext, ANOTHER_API_KEY).reportEvent("Updates installed")
AppMetrica.getReporter(getApplicationContext(), ANOTHER_API_KEY).reportEvent("Updates installed");

For correct tracking, manually configure the reporters to send events about the start and the pause of the session for each reporter. Use the resumeSession() and pauseSession() methods in the IReporter interface when implementing onResume() and onPause() for your Activity:

public class YourActivity : Activity() {
    override fun onResume() {
        super.onResume()
        AppMetrica.getReporter(applicationContext, ANOTHER_API_KEY).resumeSession()
    }

    override fun onPause() {
        AppMetrica.getReporter(applicationContext, ANOTHER_API_KEY).pauseSession()
        super.onPause()
    }
}
public class YourActivity extends Activity {
    @Override
    protected void onResume() {
        super.onResume();
        AppMetrica.getReporter(getApplicationContext(), ANOTHER_API_KEY).resumeSession();
    }

    @Override
    protected void onPause() {
        AppMetrica.getReporter(getApplicationContext(), ANOTHER_API_KEY).pauseSession();
        super.onPause();
    }
}

Tracking app crashes

Reports on app crashes are sent by default.

To disable automatic monitoring, initialize the library with the configuration in which sending crashes is disabled. To do this, pass the false value to the withLocationTracking(boolean enabled) method when creating the extended library configuration.

// Creating an extended library configuration.
val config = AppMetrica.newConfigBuilder(API_KEY)
    // Disabling the data sending about the app crashes.
    .withCrashReporting(false)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Disabling the data sending about the app crashes.
        .withCrashReporting(false)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

If automatic monitoring is disabled, you can manually submit information about crashes.

Manually monitoring app crashes

Reports on app crashes are sent by default. To prevent event duplication when sending crashes manually, disable the automatic monitoring of app crashes.

To send crash data manually, use the AppMetrica.reportUnhandledException(Throwable exception) method.

val previousUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
// Creating a new handler.
val uncaughtExceptionHandler = Thread.UncaughtExceptionHandler { thread, exception ->
    try {
        // Sending a message about an app crash to the AppMetrica server.
        AppMetrica.reportUnhandledException(exception)
    } finally {
        // Sending a message about an app crash to the system handler.
        previousUncaughtExceptionHandler?.uncaughtException(thread, exception)
    }
}
// Setting the default handler.
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler)
final Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
// Creating a new handler.
Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable exception) {
        try {
            // Sending a message about an app crash to the AppMetrica server.
            AppMetrica.reportUnhandledException(exception);
        } finally {
            // Sending a message about an app crash to the system handler.
            if (previousUncaughtExceptionHandler != null) {
                previousUncaughtExceptionHandler.uncaughtException(thread, exception);
            }
        }
    }
};
// Setting the default handler.
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);

Monitoring native app crashes

Reports are sent automatically on native app crashes if the library's SO files are added to the project. By default, SO files are omitted. To add them, configure the AppMetrica Gradle Plugin as follows:

appmetrica {
    ...
    ndk {
        enable = { applicationVariant -> true }
    }
}
appmetrica {
    ...
    ndk {
        enable = { applicationVariant -> true }
    }
}

The plugin will automatically add the appropriate dependencies. The library added by the plugin contains SO files for every platform (arm, armv7, mips, x86). Use abi splits to exclude unnecessary SO files.

If you don't use Gradle

Download and add the library to your project.

To disable automatic monitoring, initialize the library with the configuration in which sending crashes is disabled. To do this, pass the false value to the withNativeCrashReporting(boolean enabled) method when creating the extended library configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Disabling the data sending about the native app crashes.
    .withNativeCrashReporting(false)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Disabling the data sending about the native app crashes.
        .withNativeCrashReporting(false)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

See also More information on the native code.

Advertising identifiers tracking

Note

Sending advertising identifiers with event enabled by default.

If you need to disable the collection of advertising identifiers for any reason, for example, you expect the user's consent, disable sending at the library initialization stage. To do this, pass the value false to the withAdvIdentifiersTracking (boolean enabled) method when creating the configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Disabling advertising identifiers tracking
    .withAdvIdentifiersTracking(false)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Disabling advertising identifiers tracking
        .withAdvIdentifiersTracking(false)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

After obtaining the user's consent, it is recommended to enable the collection of advertising identifiers in the course of work. To do this, pass the value true to the AppMetrica.setAdvIdentifiersTracking(boolean enabled) method.

// Enabling advertising identifiers tracking
AppMetrica.setAdvIdentifiersTracking(true)
// Enabling advertising identifiers tracking
AppMetrica.setAdvIdentifiersTracking(true);

Using the library to send device location

Note

Sending device location is disabled by default.

Starting with version 5.0.0, the AppMetrica SDK is initialized with locationTracking disabled by default.

To enable sending it, initialize the library with the configuration where sending device location data is enabled. To do this, pass the true value to the withLocationTracking(boolean enabled) method when creating an extended library configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Enabling the data sending about the device location.
    .withLocationTracking(true)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Enabling the data sending about the device location.
        .withLocationTracking(true)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

To enable sending at app runtime, use the AppMetrica.setLocationTracking(boolean enabled) method:

AppMetrica.setLocationTracking(true)
AppMetrica.setLocationTracking(true);

For more precise locations, add one of the following permissions to the AndroidManifest.xml file:

For example:

<manifest>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <application>...</application>
</manifest>

Setting location manually

Before sending custom information about the device location, make sure that reporting is enabled.

The library determines the device location on its own. To send custom data on device location, pass an instance of the android.location.Location class to the AppMetrica.setLocation(Location Location) method.

// Determining the location.
val currentLocation = ...
// Setting your own location information of the device.
AppMetrica.setLocation(currentLocation)
// Determining the location.
Location currentLocation = ...;
// Setting your own location information of the device.
AppMetrica.setLocation(currentLocation);

To send your own device location information using the startup configuration, pass the android.location.Location instance to the withLocation(Location Location) method when creating the extended library configuration.

// Determining the location.
val currentLocation = ...

// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Set your own location information of the device.
    .withLocation(currentLocation)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Determining the location.
Location currentLocation = ...;

// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Set your own location information of the device.
        .withLocation(currentLocation)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

To resume location detection by the library, pass the null value to the AppMetrica.setLocation(Location location) method and configure delivery of device location data.

AppMetrica.setLocation(null)
AppMetrica.setLocation(null);

Sending a custom event

To send a custom event without nested parameters, pass a short name or description of the event to the AppMetrica.reportEvent(String eventName) method:

AppMetrica.reportEvent("Updates installed")
AppMetrica.reportEvent("Updates installed");

Sending a custom event with nested parameters

The AppMetrica SDK allows you to send your own events with nested parameters that can be set in the JSON format or as a set of attributes (Map).

JSON

To pass nested event parameters in the JSON format, use the AppMetrica.reportEvent(String eventName, String jsonValue) method:

val eventParameters = """{"name":"Alice", "age":"18"}"""

AppMetrica.reportEvent("New person", eventParameters)
String eventParameters = "{\"name\":\"Alice\", \"age\":\"18\"}";

AppMetrica.reportEvent("New person", eventParameters);

Map

To send a custom event message as a set of attributes (Map), use the AppMetrica.reportEvent(String eventName, Map<String, Object> attributes) method:

val eventParameters = mapOf("name" to "Alice", "age" to 18)

AppMetrica.reportEvent("New person", eventParameters)
Map<String, Object> eventParameters = new HashMap<String, Object>();
eventParameters.put("name", "Alice");
eventParameters.put("age", 18);

AppMetrica.reportEvent("New person", eventParameters);

The AppMetrica web interface displays up to five nesting levels for events. So if an event has six or more levels, only the top five are shown in the report. You can use the Reporting API to export up to ten levels.

For more information about events, see Events.

Sending an event from the WebView's JavaScript code

The AppMetrica SDK lets you send client events from JavaScript code. Initialize the sending by calling the initWebViewReporting method:

val webView = findViewById<WebView>(R.id.myWebView)
// do your initialization here
webView.settings.javaScriptEnabled = true
AppMetrica.initWebViewReporting(webView)
webView.loadUrl(myURL)
WebView webView = (WebView) findViewById(R.id.myWebView);
// do your initialization here
webView.getSettings().setJavaScriptEnabled(true);
AppMetrica.initWebViewReporting(webView);
webView.loadUrl(myURL);

Invoke the initWebViewReporting method after calling the setJavaScriptEnabled method but before calling loadUrl.

To send an event from JavaScript code, use the reportEvent(name, value) method in the AppMetrica interface:

Javascript

function buttonClicked() {
  AppMetrica.reportEvent('Button clicked!', '{}');
}

Arguments of the reportEvent method:

  • name: A string. Can't be null or empty.
  • value: A JSON string. Can be null.

Sending a custom error message

To send your own error message, use the following methods:

  • AppMetrica.reportError(String message, Throwable error)
  • AppMetrica.reportError(String groupIdentifier, String message)
  • AppMetrica.reportError(String groupIdentifier, String message, Throwable error)
Example with groupIdentifier

If you send errors using methods with groupIdentifier, they are grouped by ID.

try {
    "00xffWr0ng".toInt()
} catch (error: Throwable) {
    AppMetrica.reportError("Your ID", "Error while parsing some integer number", error)
}
try {
    Integer.valueOf("00xffWr0ng");
} catch (Throwable error) {
    AppMetrica.reportError("Your ID", "Error while parsing some integer number", error);
}

Don't use variable values as grouping IDs. Otherwise, the number of groups increases and it becomes difficult to analyze them.

Example with message

If errors are sent using the AppMetrica.reportError(String message, Throwable error) method, they are grouped by stack trace.

try {
    "00xffWr0ng".toInt()
} catch (error: Throwable) {
    AppMetrica.reportError("Error while parsing some integer number", error)
}
try {
    Integer.valueOf("00xffWr0ng");
} catch (Throwable error) {
    AppMetrica.reportError("Error while parsing some integer number", error);
}

Sending ProfileId

If you know the user profile ID before initializing the AppMetrica SDK, pass it before initialization (setUserProfileID) or during initialization with the extended configuration (withUserProfileID).

Otherwise, a user profile is created with the ID appmetrica_device_id.

Warning

AppMetrica doesn't display predefined attributes in the web interface if ProfieId sending isn't configured.

You can update ProfileId at any time by calling setUserProfileID:

AppMetrica.setUserProfileID("id")
AppMetrica.setUserProfileID("id");

Sending profile attributes

To send profile attributes, pass the required attributes to the instance of the UserProfile class and send the instance using the AppMetrica.reportUserProfile(UserProfile profile) method. To create profile attributes, use methods of the Attribute class.

// Creating the UserProfile instance.
val userProfile = UserProfile.newBuilder()
    // Updating predefined attributes.
    .apply(Attribute.name().withValue("John"))
    .apply(Attribute.gender().withValue(GenderAttribute.Gender.MALE))
    .apply(Attribute.birthDate().withAge(24))
    .apply(Attribute.notificationsEnabled().withValue(false))
    // Updating custom attributes.
    .apply(Attribute.customString("string_attribute").withValue("string"))
    .apply(Attribute.customNumber("number_attribute").withValue(55.0))
    .apply(Attribute.customCounter("counter_attribute").withDelta(1.0))
    .build()
// Setting the ProfileID using the method of the AppMetrica class.
AppMetrica.setUserProfileID("id")

// Sending the UserProfile instance.
AppMetrica.reportUserProfile(userProfile)
// Creating the UserProfile instance.
UserProfile userProfile = UserProfile.newBuilder()
        // Updating predefined attributes.
        .apply(Attribute.name().withValue("John"))
        .apply(Attribute.gender().withValue(GenderAttribute.Gender.MALE))
        .apply(Attribute.birthDate().withAge(24))
        .apply(Attribute.notificationsEnabled().withValue(false))
        // Updating custom attributes.
        .apply(Attribute.customString("string_attribute").withValue("string"))
        .apply(Attribute.customNumber("number_attribute").withValue(55))
        .apply(Attribute.customCounter("counter_attribute").withDelta(1))
        .build();
// Setting the ProfileID using the method of the AppMetrica class.
AppMetrica.setUserProfileID("id");

// Sending the UserProfile instance.
AppMetrica.reportUserProfile(userProfile);

Sending E-commerce events

AppMetrica doesn't let you segment E-commerce events into test and non-test events. If you use the main API key for debugging purchases, the test events are included in general statistics. Therefore, to debug E-commerce event sending, use a reporter to send statistics to the additional API key.

Step 1. Configure sending E-commerce events to the test API key

For different user actions, there are appropriate types of E-commerce events. To create a specific event type, use the appropriate ECommerceEvent class method.

The examples below show how to send specific types of events:

Opening a page
val payload = mapOf(
    "configuration" to "landscape",
    "full_screen" to "true",
)
// Creating a screen object.
val screen = ECommerceScreen()
    .setCategoriesPath(listOf("Promos", "Hot deal")) // Optional.
    .setName("ProductCardActivity") // Optional.
    .setSearchQuery("danissimo maple syrup") // Optional.
    .setPayload(payload) // Optional.
val showScreenEvent = ECommerceEvent.showScreenEvent(screen)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(showScreenEvent)
Map<String, String> payload = new HashMap<>();
payload.put("configuration", "landscape");
payload.put("full_screen", "true");
// Creating a screen object.
CommerceScreen screen = new ECommerceScreen()
        .setCategoriesPath(Arrays.asList("Promos", "Hot deal")) // Optional.
        .setName("ProductCardActivity") // Optional.
        .setSearchQuery("danissimo maple syrup") // Optional.
        .setPayload(payload); // Optional.
ECommerceEvent showScreenEvent = ECommerceEvent.showScreenEvent(screen);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(showScreenEvent);
Viewing a product profile
val payload = mapOf(
    "configuration" to "landscape",
    "full_screen" to "true",
)
// Creating a screen object.
val screen = ECommerceScreen()
    .setCategoriesPath(listOf("Promos", "Hot deal")) // Optional.
    .setName("ProductCardActivity") // Optional.
    .setSearchQuery("danissimo maple syrup") // Optional.
    .setPayload(payload) // Optional.
// Creating an actualPrice object.
val actualPrice = ECommercePrice(ECommerceAmount(4.53, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30570000, "wood"),
        ECommerceAmount(26.89, "iron"),
        ECommerceAmount(BigDecimal("5.1"), "gold")
    ))
// Creating an originalPrice object.
val originalPrice = ECommercePrice(ECommerceAmount(5.78, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30590000, "wood"),
        ECommerceAmount(26.92, "iron"),
        ECommerceAmount(BigDecimal("5.5"), "gold")
    ))
// Creating a product object.
val product = ECommerceProduct("779213")
    .setActualPrice(actualPrice) // Optional.
    .setPromocodes(listOf("BT79IYX", "UT5412EP")) // Optional.
    .setPayload(payload) // Optional.
    .setOriginalPrice(originalPrice) // Optional.
    .setName("Danissimo curd product 5.9%, 130 g") // Optional.
    .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
val showProductCardEvent = ECommerceEvent.showProductCardEvent(product, screen)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(showProductCardEvent)
Map<String, String> payload = new HashMap<>();
payload.put("configuration", "landscape");
payload.put("full_screen", "true");
// Creating a screen object.
ECommerceScreen screen = new ECommerceScreen()
        .setCategoriesPath(Arrays.asList("Promos", "Hot deal")) // Optional.
        .setName("ProductCardActivity") // Optional.
        .setSearchQuery("danissimo maple syrup") // Optional.
        .setPayload(payload); // Optional.
// Creating an actualPrice object.
ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(4.53, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_570_000, "wood"),
                new ECommerceAmount(26.89, "iron"),
                new ECommerceAmount(new BigDecimal("5.1"), "gold")
        ));
// Creating an originalPrice object.
ECommercePrice originalPrice = new ECommercePrice(new ECommerceAmount(5.78, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_590_000, "wood"),
                new ECommerceAmount(26.92, "iron"),
                new ECommerceAmount(new BigDecimal("5.5"), "gold")
        ));
// Creating a product object.
ECommerceProduct product = new ECommerceProduct("779213")
        .setActualPrice(actualPrice) // Optional.
        .setPromocodes(Arrays.asList("BT79IYX", "UT5412EP")) // Optional.
        .setPayload(payload) // Optional.
        .setOriginalPrice(originalPrice) // Optional.
        .setName("Danissimo curd product 5.9%, 130 g") // Optional.
        .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
ECommerceEvent showProductCardEvent = ECommerceEvent.showProductCardEvent(product, screen);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(showProductCardEvent);
Viewing a product page
val payload = mapOf(
    "configuration" to "landscape",
    "full_screen" to "true",
)
// Creating a screen object.
val screen = ECommerceScreen()
    .setCategoriesPath(listOf("Promos", "Hot deal")) // Optional.
    .setName("ProductCardActivity") // Optional.
    .setSearchQuery("danissimo maple syrup") // Optional.
    .setPayload(payload) // Optional.
// Creating an actualPrice object.
val actualPrice = ECommercePrice(ECommerceAmount(4.53, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30570000, "wood"),
        ECommerceAmount(26.89, "iron"),
        ECommerceAmount(BigDecimal("5.1"), "gold")
    ))
// Creating an originalPrice object.
val originalPrice = ECommercePrice(ECommerceAmount(5.78, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30590000, "wood"),
        ECommerceAmount(26.92, "iron"),
        ECommerceAmount(BigDecimal("5.5"), "gold")
    ))
// Creating a product object.
val product = ECommerceProduct("779213")
    .setActualPrice(actualPrice) // Optional.
    .setPromocodes(listOf("BT79IYX", "UT5412EP")) // Optional.
    .setPayload(payload) // Optional.
    .setOriginalPrice(originalPrice) // Optional.
    .setName("Danissimo curd product 5.9%, 130 g") // Optional.
    .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
val referrer = ECommerceReferrer()
    .setType("button") // Optional.
    .setIdentifier("76890") // Optional.
    .setScreen(screen) // Optional.
val showProductDetailsEvent = ECommerceEvent.showProductDetailsEvent(product, referrer) // Referrer is optional — can be null.
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(showProductDetailsEvent)
Map<String, String> payload = new HashMap<>();
payload.put("configuration", "landscape");
payload.put("full_screen", "true");
// Creating a screen object.
ECommerceScreen screen = new ECommerceScreen()
        .setCategoriesPath(Arrays.asList("Promos", "Hot deal")) // Optional.
        .setName("ProductCardActivity") // Optional.
        .setSearchQuery("danissimo maple syrup") // Optional.
        .setPayload(payload); // Optional.
// Creating an actualPrice object.
ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(4.53, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_570_000, "wood"),
                new ECommerceAmount(26.89, "iron"),
                new ECommerceAmount(new BigDecimal("5.1"), "gold")
        ));
// Creating an originalPrice object.
ECommercePrice originalPrice = new ECommercePrice(new ECommerceAmount(5.78, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_590_000, "wood"),
                new ECommerceAmount(26.92, "iron"),
                new ECommerceAmount(new BigDecimal("5.5"), "gold")
        ));
// Creating a product object.
ECommerceProduct product = new ECommerceProduct("779213")
        .setActualPrice(actualPrice) // Optional.
        .setPromocodes(Arrays.asList("BT79IYX", "UT5412EP")) // Optional.
        .setPayload(payload) // Optional.
        .setOriginalPrice(originalPrice) // Optional.
        .setName("Danissimo curd product 5.9%, 130 g") // Optional.
        .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
ECommerceReferrer referrer = new ECommerceReferrer()
        .setType("button") // Optional.
        .setIdentifier("76890") // Optional.
        .setScreen(screen); // Optional.
ECommerceEvent showProductDetailsEvent = ECommerceEvent.showProductDetailsEvent(product, referrer); // Referrer is optional — can be null.
// Sending an E-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(showProductDetailsEvent);
Adding or removing an item to/from the cart
val payload = mapOf(
    "configuration" to "landscape",
    "full_screen" to "true",
)
// Creating a screen object.
val screen = ECommerceScreen()
    .setCategoriesPath(listOf("Promos", "Hot deal")) // Optional.
    .setName("ProductCardActivity") // Optional.
    .setSearchQuery("danissimo maple syrup") // Optional.
    .setPayload(payload) // Optional.
// Creating an actualPrice object.
val actualPrice = ECommercePrice(ECommerceAmount(4.53, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30570000, "wood"),
        ECommerceAmount(26.89, "iron"),
        ECommerceAmount(BigDecimal("5.1"), "gold")
    ))
// Creating an originalPrice object.
val originalPrice = ECommercePrice(ECommerceAmount(5.78, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30590000, "wood"),
        ECommerceAmount(26.92, "iron"),
        ECommerceAmount(BigDecimal("5.5"), "gold")
    ))
// Creating a product object.
val product = ECommerceProduct("779213")
    .setActualPrice(actualPrice) // Optional.
    .setPromocodes(listOf("BT79IYX", "UT5412EP")) // Optional.
    .setPayload(payload) // Optional.
    .setOriginalPrice(originalPrice) // Optional.
    .setName("Danissimo curd product 5.9%, 130 g") // Optional.
    .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
val referrer = ECommerceReferrer()
    .setType("button") // Optional.
    .setIdentifier("76890") // Optional.
    .setScreen(screen) // Optional.
// Creating a cartItem object.
val addedItems1 = ECommerceCartItem(product, actualPrice, 1.0)
    .setReferrer(referrer) // Optional.
val addCartItemEvent = ECommerceEvent.addCartItemEvent(addedItems1)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(addCartItemEvent)
val removeCartItemEvent = ECommerceEvent.removeCartItemEvent(addedItems1)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(removeCartItemEvent)
Map<String, String> payload = new HashMap<>();
payload.put("configuration", "landscape");
payload.put("full_screen", "true");
// Creating a screen object.
ECommerceScreen screen = new ECommerceScreen()
        .setCategoriesPath(Arrays.asList("Promos", "Hot deal")) // Optional.
        .setName("ProductCardActivity") // Optional.
        .setSearchQuery("danissimo maple syrup") // Optional.
        .setPayload(payload); // Optional.
// Creating an actualPrice object.
ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(4.53, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_570_000, "wood"),
                new ECommerceAmount(26.89, "iron"),
                new ECommerceAmount(new BigDecimal("5.1"), "gold")
        ));
// Creating an originalPrice object.
ECommercePrice originalPrice = new ECommercePrice(new ECommerceAmount(5.78, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_590_000, "wood"),
                new ECommerceAmount(26.92, "iron"),
                new ECommerceAmount(new BigDecimal("5.5"), "gold")
        ));
// Creating a product object.
ECommerceProduct product = new ECommerceProduct("779213")
        .setActualPrice(actualPrice) // Optional.
        .setPromocodes(Arrays.asList("BT79IYX", "UT5412EP")) // Optional.
        .setPayload(payload) // Optional.
        .setOriginalPrice(originalPrice) // Optional.
        .setName("Danissimo curd product 5.9%, 130 g") // Optional.
        .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
ECommerceReferrer referrer = new ECommerceReferrer()
        .setType("button") // Optional.
        .setIdentifier("76890") // Optional.
        .setScreen(screen); // Optional.
// Creating a cartItem object.
ECommerceCartItem addedItems1 = new ECommerceCartItem(product, actualPrice, 1.0)
        .setReferrer(referrer); // Optional.
ECommerceEvent addCartItemEvent = ECommerceEvent.addCartItemEvent(addedItems1);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(addCartItemEvent);
ECommerceEvent removeCartItemEvent = ECommerceEvent.removeCartItemEvent(addedItems1);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(removeCartItemEvent);
Starting and completing a purchase
val payload = mapOf(
    "configuration" to "landscape",
    "full_screen" to "true",
)
// Creating a screen object.
val screen = ECommerceScreen()
    .setCategoriesPath(listOf("Promos", "Hot deal")) // Optional.
    .setName("ProductCardActivity") // Optional.
    .setSearchQuery("danissimo maple syrup") // Optional.
    .setPayload(payload) // Optional.
// Creating an actualPrice object.
val actualPrice = ECommercePrice(ECommerceAmount(4.53, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30570000, "wood"),
        ECommerceAmount(26.89, "iron"),
        ECommerceAmount(BigDecimal("5.1"), "gold")
    ))
// Creating an originalPrice object.
val originalPrice = ECommercePrice(ECommerceAmount(5.78, "USD"))
    .setInternalComponents(listOf( // Optional.
        ECommerceAmount(30590000, "wood"),
        ECommerceAmount(26.92, "iron"),
        ECommerceAmount(BigDecimal("5.5"), "gold")
    ))
// Creating a product object.
val product = ECommerceProduct("779213")
    .setActualPrice(actualPrice) // Optional.
    .setPromocodes(listOf("BT79IYX", "UT5412EP")) // Optional.
    .setPayload(payload) // Optional.
    .setOriginalPrice(originalPrice) // Optional.
    .setName("Danissimo curd product 5.9%, 130 g") // Optional.
    .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
val referrer = ECommerceReferrer()
    .setType("button") // Optional.
    .setIdentifier("76890") // Optional.
    .setScreen(screen) // Optional.
// Creating a cartItem object.
val addedItems1 = ECommerceCartItem(product, actualPrice, 1.0)
    .setReferrer(referrer) // Optional.
// Creating an order object.
val order = ECommerceOrder("88528768", listOf(addedItems1))
    .setPayload(payload) // Optional.
val beginCheckoutEvent = ECommerceEvent.beginCheckoutEvent(order)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(beginCheckoutEvent)
val purchaseEvent = ECommerceEvent.purchaseEvent(order)
// Sending an e-commerce event.
AppMetrica.getReporter(applicationContext, "Testing API key").reportECommerce(purchaseEvent)
Map<String, String> payload = new HashMap<>();
payload.put("configuration", "landscape");
payload.put("full_screen", "true");
// Creating a screen object.
ECommerceScreen screen = new ECommerceScreen()
        .setCategoriesPath(Arrays.asList("Promos", "Hot deal")) // Optional.
        .setName("ProductCardActivity") // Optional.
        .setSearchQuery("danissimo maple syrup") // Optional.
        .setPayload(payload); // Optional.
// Creating an actualPrice object.
ECommercePrice actualPrice = new ECommercePrice(new ECommerceAmount(4.53, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_570_000, "wood"),
                new ECommerceAmount(26.89, "iron"),
                new ECommerceAmount(new BigDecimal("5.1"), "gold")
        ));
// Creating an originalPrice object.
ECommercePrice originalPrice = new ECommercePrice(new ECommerceAmount(5.78, "USD"))
        .setInternalComponents(Arrays.asList( // Optional.
                new ECommerceAmount(30_590_000, "wood"),
                new ECommerceAmount(26.92, "iron"),
                new ECommerceAmount(new BigDecimal("5.5"), "gold")
        ));
// Creating a product object.
ECommerceProduct product = new ECommerceProduct("779213")
        .setActualPrice(actualPrice) // Optional.
        .setPromocodes(Arrays.asList("BT79IYX", "UT5412EP")) // Optional.
        .setPayload(payload) // Optional.
        .setOriginalPrice(originalPrice) // Optional.
        .setName("Danissimo curd product 5.9%, 130 g") // Optional.
        .setCategoriesPath(listOf("Groceries", "Dairy products", "Yogurts")) // Optional.
// Creating a referrer object.
ECommerceReferrer referrer = new ECommerceReferrer()
        .setType("button") // Optional.
        .setIdentifier("76890") // Optional.
        .setScreen(screen); // Optional.
// Creating a cartItem object.
ECommerceCartItem addedItems1 = new ECommerceCartItem(product, actualPrice, 1.0)
        .setReferrer(referrer); // Optional.
// Creating an order object.
ECommerceOrder order = new ECommerceOrder("88528768", Arrays.asList(addedItems1))
        .setPayload(payload); // Optional.
ECommerceEvent beginCheckoutEvent = ECommerceEvent.beginCheckoutEvent(order);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(beginCheckoutEvent);
ECommerceEvent purchaseEvent = ECommerceEvent.purchaseEvent(order);
// Sending an e-commerce event.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportECommerce(purchaseEvent);

Step 2. Check the test app report

Make in-app test purchases. After a while, check the Purchase analysis report in the AppMetrica interface. Make sure that the report shows E-commerce events.

For more information about the report, see Purchase analysis.

Step 3. Configure sending events to the main API key

After successful testing, configure sending E-commerce events to the main API key.

To send the ECommerceEvent instance to the main API key, use the AppMetrica.reportECommerce(@NonNull ECommerceEvent event) method.

// ...
// Sending an e-commerce event.
AppMetrica.reportECommerce(ecommerceEvent)
// ...
// Sending an e-commerce event.
AppMetrica.reportECommerce(ecommerceEvent);

Sending Revenue

AppMetrica supports the validation of purchases made using the Google Play Billing library. Validation lets you filter purchases made from hacked apps. If validation is enabled and a purchase fails it, this purchase isn't shown in reports.

Note

Local validation with a public key is used to validate purchases on Android. To enable validation, create a public key and specify it in the settings.

Step 1. Configure sending Revenue to the test API key

AppMetrica doesn't let you segment between test and non-test revenue. If you use the main API key for debugging purchases, the test purchases are included in general statistics. Therefore, to debug Revenue sending, use a reporter to send statistics to the additional API key.

This section outlines the steps for sending Revenue to the additional API key:

With validation

To validate purchases on Android, configure sending the Revenue.Receipt instance along with the Revenue:

  1. Create a Revenue.Receipt instance with information about the purchase and signature. You must use it when creating the Revenue instance in Revenue.Builder.withReceipt (Revenue.Receipt receipt).
  2. Create the Revenue instance using the Revenue.Builder constructor.
  3. Send the Revenue instance to the test API key using the IReporter. For more information about reporters, see Sending statistics to an additional API key.
fun handlePurchase(purchase: Purchase) {
    // Creating the Revenue.Receipt instance.
    // It is used for checking purchases in Google Play.
    val revenueReceipt = Receipt.newBuilder()
        .withData(purchase.originalJson)
        .withSignature(purchase.signature)
        .build()
    // Creating the Revenue instance.
    val revenue = Revenue.newBuilder(99000000, Currency.getInstance("RUB"))
        .withProductID("io.appmetrica.service.299")
        .withQuantity(2)
        .withReceipt(revenueReceipt)
        .withPayload("""{"source":"Google Play"}""")
        .build()
    // Sending the Revenue instance using reporter.
    AppMetrica.getReporter(applicationContext, "Testing API key").reportRevenue(revenue)
}
void handlePurchase(Purchase purchase) {
    // Creating the Revenue.Receipt instance.
    // It is used for checking purchases in Google Play.
    Revenue.Receipt revenueReceipt = Revenue.Receipt.newBuilder()
            .withData(purchase.getOriginalJson())
            .withSignature(purchase.getSignature())
            .build();
    // Creating the Revenue instance.
    Revenue revenue = Revenue.newBuilder(99000000, Currency.getInstance("RUB"))
            .withProductID("io.appmetrica.service.299")
            .withQuantity(2)
            .withReceipt(revenueReceipt)
            .withPayload("{\"source\":\"Google Play\"}")
            .build();
    // Sending the Revenue instance using reporter.
    AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportRevenue(revenue);
}
Without validation

To send information about a purchase without validation:

  1. Create the Revenue instance using the Revenue.Builder constructor.

  2. (Optional) To group purchases, set the OrderID in the Revenue.Builder.withPayload(String payload) method.

    Note

    If the OrderID is not specified, AppMetrica generates the ID automatically.

  3. Send the Revenue instance to the test API key using the IReporter. For more information about reporters, see Sending statistics to an additional API key.

// Creating the Revenue instance.
val revenue = Revenue.newBuilder(99000000, Currency.getInstance("RUB"))
    .withProductID("io.appmetrica.service.299")
    .withQuantity(2) // Passing the OrderID parameter in the .withPayload(String payload) method to group purchases.
    .withPayload("""{"OrderID":"Identifier", "source":"Google Play"}""")
    .build()
// Sending the Revenue instance using reporter.
AppMetrica.getReporter(applicationContext, "Testing API key").reportRevenue(revenue)
// Creating the Revenue instance.
Revenue revenue = Revenue.newBuilder(99000000, Currency.getInstance("RUB"))
        .withProductID("io.appmetrica.service.299")
        .withQuantity(2)
        // Passing the OrderID parameter in the .withPayload(String payload) method to group purchases.
        .withPayload("{\"OrderID\":\"Identifier\", \"source\":\"Google Play\"}")
        .build();
// Sending the Revenue instance using reporter.
AppMetrica.getReporter(getApplicationContext(), "Testing API key").reportRevenue(revenue);

Step 2. Check the test app report

Check the Revenue report in the AppMetrica report. Make sure that the number of purchases has increased.

For more information about the report, see Revenue.

Step 3. Configure sending Revenue to the main API key

After successful testing, have Revenue sent to the main API key.

To send the Revenue instance to the main API key, use the AppMetrica.reportRevenue(Revenue revenue) method.

// ...
// Sending the Revenue instance.
AppMetrica.reportRevenue(revenue)
// ...
// Sending the Revenue instance.
AppMetrica.reportRevenue(revenue);

Sending Ad Revenue data

AppMetrica offers several options for sending ad revenue data from ad monetization and mediation services:

Automatic integration

Data is transmitted automatically. You can disable automatic collection of data where appropriate.

ironSource

Step 1. Set up sending Ad Revenue data

IronSource supports automatic collection of Ad Revenue data. The process is managed by the io.appmetrica.analytics:analytics-ad-revenue-ironsource-v7 module.

Activation example:

AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY).build();
AppMetrica.activate(context, config);
Step 2. Make sure that the Ad Revenue data is included in the reports
  1. View ads in the app.

  2. Make sure that the Revenue report shows the same number of ad revenue events as the number of ad views.

Disabling automatic collection of Ad Revenue data

To disable automatic collection of Ad Revenue data, exclude the following module from the list of dependencies:

configurations.configureEach {
    exclude(group = "io.appmetrica.analytics", module = "io.appmetrica.analytics:analytics-ad-revenue-ironsource-v7")
}
configurations.configureEach {
    exclude group: 'io.appmetrica.analytics', module: 'io.appmetrica.analytics:analytics-ad-revenue-ironsource-v7'
}

Simplified integration

Use the simplified API for sending data. It supports popular ad monetization and mediation services.

Applovin MAX

Step 1. Make sure that the SDK is activated

Activation example:

AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY).build();
AppMetrica.activate(context, config);
Step 2. Set up sending ad revenue data
  1. Once the appropriate ad instance is created, set the MaxAdRevenueListener using the setRevenueListener method.

  2. Send data from the onAdRevenuePaid(MaxAd) method to the AppMetrica SDK: call the AppMetrica#reportExternalAdRevenue method, then pass the parameter sent to the MaxAd listener and the AppLovinSdk instance as arguments.

    val maxAppOpenAdView = MaxAppOpenAd( "ad-unit-ID", applicationContext)
    maxAppOpenAdView.setRevenueListener {
        AppMetrica.reportExternalAdRevenue(it, AppLovinSdk.getInstance(applicationContext))
    }
    
    MaxAppOpenAd maxAppOpenAd = new MaxAppOpenAd( "ad-unit-ID", getApplicationContext());
    maxAppOpenAd.setRevenueListener(maxAdRevenue ->
        AppMetrica.reportExternalAdRevenue(maxAdRevenue, AppLovinSdk.getInstance(getApplicationContext())));
    
    val maxAdView = MaxAdView("ad-unit-ID", applicationContext)
    maxAdView.setRevenueListener {
        AppMetrica.reportExternalAdRevenue(it, AppLovinSdk.getInstance(applicationContext))
    }
    
    MaxAdView maxAdView = new MaxAdView("ad-unit-ID", getApplicationContext());
    maxAdView.setRevenueListener(maxAdRevenue ->
        AppMetrica.reportExternalAdRevenue(maxAdRevenue, AppLovinSdk.getInstance(getApplicationContext())));
    
    val maxInterstitialAd = MaxInterstitialAd("ad-unit-ID", applicationContext)
    maxInterstitialAd.setRevenueListener {
        AppMetrica.reportExternalAdRevenue(it, AppLovinSdk.getInstance(applicationContext))
    }
    
    MaxInterstitialAd maxInterstitialAd = new MaxInterstitialAd("ad-unit-ID", getApplicationContext());
    maxInterstitialAd.setRevenueListener(maxAdRevenue ->
        AppMetrica.reportExternalAdRevenue(maxAdRevenue, AppLovinSdk.getInstance(getApplicationContext())));
    
    val nativeAdLoader = MaxNativeAdLoader("ad-unit-ID", applicationContext)
    nativeAdLoader.setRevenueListener {
        AppMetrica.reportExternalAdRevenue(it, AppLovinSdk.getInstance(applicationContext))
    }
    
    MaxNativeAdLoader maxNativeAdLoader = new MaxNativeAdLoader("ad-unit-ID", getApplicationContext());
    maxNativeAdLoader.setRevenueListener(maxAdRevenue ->
        AppMetrica.reportExternalAdRevenue(maxAdRevenue, AppLovinSdk.getInstance(getApplicationContext())));
    
    val maxRewardedAd = MaxRewardedAd.getInstance("ad-unit-ID", applicationContext);
    maxRewardedAd.setRevenueListener {
        AppMetrica.reportExternalAdRevenue(it, AppLovinSdk.getInstance(applicationContext))
    }
    
    MaxRewardedAd maxRewardedAd = MaxRewardedAd.getInstance("ad-unit-ID", getApplicationContext());
    maxRewardedAd.setRevenueListener(maxAdRevenue ->
        AppMetrica.reportExternalAdRevenue(maxAdRevenue, AppLovinSdk.getInstance(getApplicationContext())));
    
Step 3. Make sure that the Ad Revenue data is included in the reports
  1. View ads in the app.

  2. Make sure that the Revenue report shows the same number of ad revenue events as the number of ad views.

Digital Turbine

Step 1. Make sure that the SDK is activated

Activation example:

AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY).build();
AppMetrica.activate(context, config);
Step 2. Set up sending Ad Revenue data
  1. For required ad types (Banner, Interstitial, and Rewarded), set the respective listener (BannerListener, InterstitalListener, or RewardedListener).

  2. Set up sending impressionData from the listener's onShow method to the AppMetrica SDK using the AppMetrica#reportExternalAdRevenue() method.

    Banner.setBannerListener(object:BannerListener {
        //....
        override fun onShow(placementId: String, impressionData: ImpressionData) {
            AppMetrica.reportAdRevenue(impressionData)
                //.....
        }
        //....
    })
    
    Banner.setBannerListener(new BannerListener() {
        //......
        @Override
        public void onShow(@NonNull String s, @NonNull ImpressionData impressionData) {
            AppMetrica.reportExternalAttribution(impressionData);
            //......
        }
        //......
    });
    
    Interstitial.setInterstitialListener(object:InterstitialListener {
        //....
        override fun onShow(placementId: String, impressionData: ImpressionData) {
            AppMetrica.reportExternalAdRevenue(impressionData)
            //....
        }
    //....
    })
    
    Interstitial.setInterstitialListener(new InterstitialListener() {
        //......
        @Override
        public void onShow(@NonNull String s, @NonNull ImpressionData impressionData) {
            AppMetrica.reportExternalAdRevenue(impressionData);
            //......
        }
    //.......
    });
    
    Rewarded.setRewardedListener(object:RewardedListener {
        override fun onShow(placementId: String, impressionData: ImpressionData) {
            AppMetrica.reportExternalAdRevenue(impressionData);
            //.......
        }
    })
    
    Rewarded.setRewardedListener(new RewardedListener() {
        //.....
        @Override
        public void onShow(@NonNull String s, @NonNull ImpressionData impressionData) {
            AppMetrica.reportExternalAdRevenue(impressionData);
            //......
        }
        //.....
    });
    
Step 3. Make sure that theAd Revenue data is included in the reports
  1. View ads in the app.

  2. Make sure that the Revenue report shows the same number of ad revenue events as the number of ad views.

Google AdMob

Step 1. Make sure that the SDK is activated

Activation example:

AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY).build();
AppMetrica.activate(context, config);
Step 2. Set up sending Ad Revenue data
  1. In the AppOpenAdLoadCallback#onAdLoaded method of the ad load listener, set the OnPaidEventListener listener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and AppOpenAd instances as arguments.

    AppOpenAd.load(
        this,
        "ad-unit-ID",
        adRequest,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        object : AppOpenAdLoadCallback() {
            override fun onAdLoaded(adMobAppOpenAd: AppOpenAd) {
                super.onAdLoaded(adMobAppOpenAd)
                adMobAppOpenAd.onPaidEventListener =
                    OnPaidEventListener { adValue ->
                        AppMetrica.reportExternalAdRevenue(
                            adValue,
                            adMobAppOpenAd
                        )
                        //......
                    }
                //......
            }
    })
    
    AppOpenAd.load(
        this,
        "ad-unit-ID",
        adRequest,
        AppOpenAd.APP_OPEN_AD_ORIENTATION_PORTRAIT,
        new RewardedInterstitialAdLoadCallback() {
        @Override
        public void onAdLoaded(@NonNull AppOpenAd adMobAppOpenAd) {
            super.onAdLoaded(adMobAppOpenAd);
            adMobAppOpenAd.setOnPaidEventListener(adValue -> {
                AppMetrica.reportExternalAdRevenue(adValue, adMobAppOpenAd);
                //......
            });
            //......
        }
    });
    
  1. After creating an adView and before loading ads, call the setOnPaidEventListener method to register the OnPaidEventListener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and adView instances as arguments.

    val adMobAdView = AdView(this)
    //........
    adMobAdView.setOnPaidEventListener {
        AppMetrica.reportExternalAdRevenue(it, adMobAdView)
        //.......
    }
    //........
    adMobAdView.loadAd(adRequest)
    
    AdView adMobAdView = new AdView(this);
    //......
    adMobAdView.setOnPaidEventListener(adValue -> {
        AppMetrica.reportExternalAdRevenue(adValue, adMobAdView);
        //.......
    });
    //.......
    adMobAdView.loadAd(adRequest);
    
  1. In the InterstitialAdLoadCallback#onAdLoaded method of the ad load listener, set the OnPaidEventListener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and interstitialAd instances as arguments.

    InterstitialAd.load(this, "add-unit-ID", adRequest, object : InterstitialAdLoadCallback() {
        //......
        override fun onAdLoaded(adMobInterstitalAd: InterstitialAd) {
            super.onAdLoaded(adMobInterstitalAd)
            //.......
            adMobInterstitalAd.setOnPaidEventListener { adValue ->
                AppMetrica.reportExternalAdRevenue(adValue, adMobInterstitalAd)
            }
            //.......
        }
    })
    
    InterstitialAd.load(this, "ad-unit-ID", adRequest, new InterstitialAdLoadCallback() {
    //........
        @Override
        public void onAdLoaded(@NonNull InterstitialAd adMobInterstitialAd) {
            super.onAdLoaded(adMobInterstitialAd);
            adMobInterstitialAd.setOnPaidEventListener(adValue -> {
                AppMetrica.reportExternalAdRevenue(adValue, adMobInterstitialAd);
                //......
            });
            //......
        }
    });
    
  1. In the OnNativeAdLoadedListener#onNativeAdLoaded method of the ad load listener, set the OnPaidEventListener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and nativeAd instances as arguments.

    val adMobAdLoader = AdLoader.Builder(this, "add-unit-ID")
        .forNativeAd { adMobNativeAd ->
           adMobNativeAd.setOnPaidEventListener { adValue ->
                AppMetrica.reportExternalAdRevenue(adValue, adMobNativeAd)
            }
        }
        //.......
        .build()
    //.....
    
    //.....
    AdLoader admobLoader = new AdLoader.Builder(this, "ad-unit-ID")
        .forNativeAd(adMobNativeAd -> {
            adMobNativeAd.setOnPaidEventListener(adValue -> {
                AppMetrica.reportExternalAdRevenue(adValue, adMobNativeAd);
                //......
            });
        //......
        })
        .build();
    //......
    
  1. In the RewardedAdLoadCallback#onAdLoaded method of the ad load listener, set the OnPaidEventListener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and rewardedAd instances as arguments.

    //.....
    RewardedAd.load(this, "ad-unit-ID", adRequest, object : RewardedAdLoadCallback() {
        override fun onAdLoaded(rewardedAd: RewardedAd) {
            super.onAdLoaded(rewardedAd)
            //.....
            rewardedAd.onPaidEventListener = OnPaidEventListener { adValue ->
                AppMetrica.reportExternalAdRevenue(
                    adValue,
                    rewardedAd
                )
            }
        }
    })
    //.....
    
    //.....
    RewardedAd.load(this, "ad-unit-ID", adRequest, new RewardedAdLoadCallback() {
        @Override
        public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
            super.onAdLoaded(rewardedAd);
            //.....
            rewardedAd.setOnPaidEventListener(adValue -> {
                AppMetrica.reportExternalAdRevenue(adValue, rewardedAd);
                //........
            });
        }
    });
    //.....
    
  1. In the RewardedInterstitialAdLoadCallback#onAdLoaded method of the ad load listener, set the OnPaidEventListener.

  2. In the OnPaidEventListener#onPaidEvent method, set up sending data to AppMetrica using the AppMetrica#reportExternalAdRevenue() method and passing the obtained AdValue and rewardedInterstitialAd instances as arguments.

    RewardedInterstitialAd.load(
        this,
        "ad-unit-ID",
        adRequest,
        object : RewardedInterstitialAdLoadCallback() {
            override fun onAdLoaded(rewardedInterstitialAd: RewardedInterstitialAd) {
                super.onAdLoaded(rewardedInterstitialAd)
                rewardedInterstitialAd.onPaidEventListener =
                    OnPaidEventListener { adValue ->
                        AppMetrica.reportExternalAdRevenue(
                            adValue,
                            rewardedInterstitialAd
                        )
                        //......
                    }
                //......
            }
    })
    
    RewardedInterstitialAd.load(this, "ad-unit-ID", adRequest, new RewardedInterstitialAdLoadCallback() {
        @Override
        public void onAdLoaded(@NonNull RewardedInterstitialAd rewardedInterstitialAd) {
            super.onAdLoaded(rewardedInterstitialAd);
            rewardedInterstitialAd.setOnPaidEventListener(adValue -> {
                AppMetrica.reportExternalAdRevenue(adValue, rewardedInterstitialAd);
                //......
            });
            //......
        }
    });
    
Step 3. Make sure that the Ad Revenue data is included in the reports
  1. View ads in the app.

  2. Make sure that the Revenue report shows the same number of ad revenue events as the number of ad views.

Manual integration and setup

Use this option to manually set up the data transfer from any other ad monetization service that provides impression-level revenue data.

Step 1. Make sure that the SDK is activated

Activation example:

AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY).build();
AppMetrica.activate(context, config);

Step 2. Set up sending Ad Revenue data

  1. Create an AdRevenue instance using the AdRevenue.Builder.

    Map<String, String> adRevenuePayload = new HashMap<>();
    adRevenuePayload.put("payload_key_1", "payload_value_1");
    adRevenuePayload.put("payload_key_2", "payload_value_2");
    AdRevenue adRevenue = AdRevenue.newBuilder(new BigDecimal("100.100"), Currency.getInstance("USD"))
    .withAdNetwork("ad_network")
    .withAdPlacementId("ad_placement_id")
    .withAdPlacementName("ad_placement_name")
    .withAdType(AdType.NATIVE)
    .withAdUnitId("ad_unit_id")
    .withAdUnitName("ad_unit_name")
    .withPrecision("some precision")
    .withPayload(adRevenuePayload)
    .build();
    
  2. Send the Ad Revenue instance using the AppMetrica.reportAdRevenue(AdRevenue adRevenue) method.

    AppMetrica.reportAdRevenue(adRevenue);
    

Step 3. Make sure that the Ad Revenue data is included in the reports

  1. View ads in the app.

  2. Make sure that the Revenue report shows the same number of ad revenue events as the number of ad views.

Setting the session timeout

By default, the session timeout is 10 seconds. The minimum acceptable value for the sessionTimeout parameter is 10 seconds.

To change the timeout, pass the value in seconds to the withSessionTimeout(int sessionTimeout) method when creating the extended library configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Setting the length of the session timeout.
    .withSessionTimeout(15)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Setting the length of the session timeout.
        .withSessionTimeout(15)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

Setting the app version

By default, the app version is set in the file build.gradle.

To specify the app version from the code, pass the app version to the withAppVersion(String appVersion) method when creating the extended library configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    // Setting the app version.
    .withAppVersion("1.13.2")
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Setting the app version.
        .withAppVersion("1.13.2")
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

where 1.13.2 is the app version.

Determining the library's API level (Android)

To determine the API level of the library from the application code, use the AppMetrica.getLibraryApiLevel() method.

val libraryApiLevel = AppMetrica.getLibraryApiLevel()
int libraryApiLevel = AppMetrica.getLibraryApiLevel();

Determining the library's version

To determine the library version from the application code, use the AppMetrica.getLibraryVersion() method:

val libraryVersion = AppMetrica.getLibraryVersion()
string libraryVersion = AppMetrica.GetLibraryVersion();

Tracking installation sources

Tracking installation source in AppMetrica SDK is enabled by default.

To track app openings that use deeplinks, you make changes in the Activity that handles deeplinks. Tracking app opening is a prerequisite for correctly tracking remarketing campaigns.

Tip

To work with deeplinks, configure them in your application.

Use the reportAppOpen() method to track app openings:

class DeeplinkActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            AppMetrica.reportAppOpen(this)
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        AppMetrica.reportAppOpen(intent)
    }
}
public class DeeplinkActivity extends Activity {
    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            AppMetrica.reportAppOpen(this);
        }
    }

    @Override
    protected void onNewIntent(final Intent intent) {
        super.onNewIntent(intent);
        AppMetrica.reportAppOpen(intent);
    }
}

Note

You can add the opening of the app via the deferred deeplink on Android.

See also How do I create a remarketing campaign in AppMetrica?.

To request a deferred deeplink, pass a class instance that implements the DeferredDeeplinkListener interface to the AppMetrica.requestDeferredDeeplink(DeferredDeeplinkListener listener) method. The method returns the deferred deeplink only at the initial application start after obtaining the Google Play Install Referrer.

AppMetrica.requestDeferredDeeplink(object : DeferredDeeplinkListener {
    override fun onDeeplinkLoaded(deeplink: String) {
        Log.i("Deeplink", "deeplink = $deeplink")
    }

    override fun onError(error: DeferredDeeplinkListener.Error, referrer: String?) {
        Log.i("Deeplink", "Error: ${error.description}, unparsed referrer: $referrer")
    }
})
AppMetrica.requestDeferredDeeplink(new DeferredDeeplinkListener() {
    @Override
    public void onDeeplinkLoaded(@NotNull String deeplink) {
        Log.i("Deeplink", "deeplink = " + deeplink);
    }

    @Override
    public void onError(@NotNull Error error, @Nullable String referrer) {
        Log.i("Deeplink", "Error: " + error.getDescription() + ", unparsed referrer: " + referrer);
    }
});

For more information about deferred deeplinks, see Support for deferred deeplinks

To request parameters for a deferred deeplink, pass an instance of the class implementing the DeferredDeeplinkParametersListener interface to the AppMetrica.requestDeferredDeeplinkParameters(DeferredDeeplinkParametersListener listener) method. The method returns the deferred deeplink parameters only at the first application start after Google Play Install Referrer obtaining.

AppMetrica.requestDeferredDeeplinkParameters(object : DeferredDeeplinkParametersListener {
    override fun onParametersLoaded(parameters: Map<String, String>) {
        // Processing deeplink parameters.
        for (key in parameters.keys) {
            Log.i("Deeplink params", "key: $key value: ${parameters[key]}")
        }
    }

    override fun onError(error: DeferredDeeplinkParametersListener.Error, referrer: String) {
        // Handling the error.
        Log.e("Error!", error.description)
    }
})
AppMetrica.requestDeferredDeeplinkParameters(new DeferredDeeplinkParametersListener() {
    @Override
    public void onParametersLoaded(@NotNull Map<String, String> parameters) {
        // Processing deeplink parameters.
        for (String key : parameters.keySet()) {
            Log.i("Deeplink params", "key: " + key + " value: " + parameters.get(key));
        }
    }

    @Override
    public void onError(@NotNull Error error, @NotNull String referrer) {
        // Handling the error.
        Log.e("Error!", error.getDescription());
    }
});

For more information about deferred deeplinks, see Support for deferred deeplinks

Tracking new users

By default, the user is counted as a new user when the app is opened for the first time. If you connect the AppMetrica SDK to an app that already has active users, you can set up tracking new and old users to get correct statistics. Configure that by initializing the AppMetrica SDK using the extended AppMetricaConfig configuration:

var isFirstLaunch: Boolean = false
// Implement logic to detect whether the app is opening for the first time.
// For example, you can check for files (settings, databases, and so on),
// which the app creates on its first launch.
if (conditions) {
    isFirstLaunch = true
}
// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
    .handleFirstActivationAsUpdate(!isFirstLaunch)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
boolean isFirstLaunch = false;
// Implement logic to detect whether the app is opening for the first time.
// For example, you can check for files (settings, databases, and so on),
// which the app creates on its first launch.
if (conditions) {
    isFirstLaunch = true;
}
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        .handleFirstActivationAsUpdate(!isFirstLaunch)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

Disabling and enabling sending statistics

If you need confirmation from the user before sending statistical data, you should initialize the library with the disabled sending option. Pass the false value to the withDataSendingEnabled(boolean value) method when creating the extended library configuration.

// Creating an extended library configuration.
val config = AppMetricaConfig.newConfigBuilder(API_KEY)
// Disabling sending data.
    .withDataSendingEnabled(false)
    .build()
// Initializing the AppMetrica SDK.
AppMetrica.activate(applicationContext, config)
// Creating an extended library configuration.
AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
        // Disabling sending data.
        .withDataSendingEnabled(false)
        .build();
// Initializing the AppMetrica SDK.
AppMetrica.activate(getApplicationContext(), config);

After the user has confirmed that you can send statistics (for example, in the app settings or by giving their permission at the first app start), enable sending of statistics using the AppMetrica.setDataSendingEnabled(true) method:

// Checking the status of the boolean variable. It shows the user confirmation.
if (flag) {
    // Enabling sending data.
    AppMetrica.setDataSendingEnabled(true)
}
// Checking the status of the boolean variable. It shows the user confirmation.
if (flag) {
    // Enabling sending data.
    AppMetrica.setDataSendingEnabled(true);
}

Alert example

You can use any text to inform users of statistics collection. For example:

This app uses the AppMetrica analytical service provided by YANDEX LLC, ulitsa Lva Tolstogo 16, Moscow, Russia 119021 (hereinafter referred to as Yandex) based on the Terms of Use.

AppMetrica analyzes app usage data, including the device it is running on, the installation source, calculates conversion, collects statistics of your activity for product analytics, ad campaign analysis, and optimization, as well as for troubleshooting. Information collected in this way cannot identify you.

Depersonalized information about your use of this app collected by AppMetrica tools will be transferred to Yandex and stored on Yandex’s server in the EU and the Russian Federation. Yandex will process this information to assess how you use the app, compile reports for us on our app operation, and provide other services.

Getting AppMetrica SDK IDs

To get AppMetrica SDK IDs (DeviceId, DeviceIdHash, UUID), use the requestStartupParams() method. To get the appmetrica_device_id, make sure to request the DeviceIdHash.

val startupParamsCallback = object : StartupParamsCallback {
    override fun onReceive(
        result: StartupParamsCallback.Result?,
    ) {
        val deviceIdHash = result?.deviceIdHash
        // ...
    }

    override fun onRequestError(
        reason: StartupParamsCallback.Reason,
        result: StartupParamsCallback.Result?,
    ) {
        // ...
    }
}
AppMetrica.requestStartupParams(
    this,
    startupParamsCallback,
    listOf(
        StartupParamsCallback.APPMETRICA_UUID,
        StartupParamsCallback.APPMETRICA_DEVICE_ID,
        StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH
    )
)
StartupParamsCallback startupParamsCallback = new StartupParamsCallback() {
    @Override
    public void onReceive(@Nullable Result result) {
        if (result != null) {
            String deviceId = result.deviceId;
            String deviceIdHash = result.deviceIdHash;
            String uuid = result.uuid;
        }
    }

    @Override
    public void onRequestError(@NonNull Reason reason, @Nullable Result result) {
        // ...
    }
};
AppMetrica.requestStartupParams(
        this,
        startupParamsCallback,
        Arrays.asList(
                StartupParamsCallback.APPMETRICA_DEVICE_ID,
                StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH,
                StartupParamsCallback.APPMETRICA_UUID
        )
);

Delivering the device type

If you want to set the device type, specify it when creating your configuration:

class YourApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // Creating an extended library configuration.
        val config = AppMetricaConfig.newConfigBuilder(API_KEY)
            // Defining the device type
            .withDeviceType(PredefinedDeviceTypes.TABLET)
            // ...
            .build()
        // Initializing the AppMetrica SDK.
        AppMetrica.activate(applicationContext, config)
        // Automatic tracking of user activity.
        AppMetrica.enableActivityAutoTracking(this)
    }
}
public class YourApplication extends Application {
   @Override
   public void onCreate() {
      super.onCreate();
      // Creating an extended library configuration.
      AppMetricaConfig config = AppMetricaConfig.newConfigBuilder(API_KEY)
              // Defining the device type
              .withDeviceType(PredefinedDeviceTypes.TABLET)
              // ...
              .build();
      // Initializing the AppMetrica SDK.
      AppMetrica.activate(getApplicationContext(), config);
      // Automatic tracking of user activity.
      AppMetrica.enableActivityAutoTracking(this);
   }
}

If you didn't find the answer you were looking for, you can use the feedback form to submit your question. Please describe the problem in as much detail as possible. Attach a screenshot if possible.

Contact support