Usage examples
- Library initialization with the extended configuration
- Sending statistics to an additional API key
- Tracking app crashes
- Determining the location
- Setting device location manually
- Sending a custom event
- Sending a custom event with nested parameters
- Sending an event from the WebView's JavaScript code
- Sending an error message
- Sending profile attributes
- Sending ProfileId
- Sending E-commerce events
- Sending Revenue
- Setting the session timeout
- Setting the app version
- Tracking app opens using deeplinks
- Tracking new users
- Disabling and enabling sending statistics
- Getting AppMetrica SDK IDs
Library initialization with the extended configuration
To initialize the library with the extended startup configuration:
- Initialize an instance of the
AppMetricaConfiguration
class. - Specify the configuration settings using methods of the
AppMetricaConfiguration
class. For example, enable logging or set a session timeout. - Pass the
AppMetricaConfiguration
instance to theactivate(with:)
method of theAppMetrica
class.
The parameters of the extended configuration are applied from the time of library initialization. To configure the library while the app is running, use the AppMetrica
class methods.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : AnyObject]? = nil) -> Bool {
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Setting up the configuration. For example, to enable logging.
configuration.areLogsEnabled = true
// ...
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
}
- Initialize an instance of the
AMAAppMetricaConfiguration
class. - Specify the configuration settings using methods of the
AMAAppMetricaConfiguration
class. For example, enable logging or set a session timeout. - Pass the
AMAAppMetricaConfiguration
instance to the+activateWithConfiguration:
method of theAMAAppMetrica
class.
The parameters of the extended configuration are applied from the time of library initialization. To configure the library while the app is running, use the AMAAppMetrica
class methods.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Setting up the configuration. For example, to enable logging.
configuration.logsEnabled = YES;
// ...
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
return YES;
}
What is an API key?
The API key is a unique app ID issued in the AppMetrica web interface at app registration. You can find it under Settings.
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
Warning
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.
To initialize a reporter with an extended configuration:
- Initialize an instance of the
MutableReporterConfiguration
class. - Specify the configuration settings using methods of the
MutableReporterConfiguration
class. For example, enable logging or set a session timeout. - Pass the
MutableReporterConfiguration
instance to theactivateReporter(with:)
method of theAppMetrica
class. - This configuration is used for a reporter with the specified API key. You can set up your own configuration for each additional API key.
// Creating an extended library configuration.
// To create it, pass an API key that is different from the app's API key.
if let reporterConfiguration = MutableReporterConfiguration(apiKey: "API key") {
// Setting up the configuration. For example, to enable logging.
reporterConfiguration.areLogsEnabled = true
// ...
// Initializing a reporter.
AppMetrica.activateReporter(with: reporterConfiguration)
}
- Initialize an instance of the
AMAMutableReporterConfiguration
class. - Specify the configuration settings using methods of the
AMAMutableReporterConfiguration
class. For example, enable logging or set a session timeout. - Pass the
AMAMutableReporterConfiguration
instance to the+activateReporterWithConfiguration:
method of theAMAAppMetrica
class. - This configuration is used for a reporter with the specified API key. You can set up your own configuration for each additional API key.
// Creating an extended library configuration.
// To create it, pass an API key that is different from the app's API key.
AMAMutableReporterConfiguration *reporterConfiguration = [[AMAMutableReporterConfiguration alloc] initWithAPIKey:@"API key"];
// Setting up the configuration. For example, to enable logging.
reporterConfiguration.logsEnabled = YES;
// ...
// Initializing a reporter.
[AMAAppMetrica activateReporterWithConfiguration:[reporterConfiguration copy]];
What is an API key?
The API key is a unique app ID issued in the AppMetrica web interface at app registration. You can find it under Settings.
Step 2. Configure sending data using a reporter
To send statistics data to another API key:
-
Use the
reporter(for:)
method of theAppMetrica
class to get the instance that implements theAppMetricaReporting
protocol.If the reporter was not initialized with an extended configuration, calling this method will initialize the reporter for the specified API key.
-
Use methods of the
AppMetricaReporting
protocol to send events and revenue. -
To ensure that sessions are tracked correctly, set up sending session start and pause events for each reporter.
guard let reporter = AppMetrica.reporter(for: "API key") else {
print("REPORT ERROR: Failed to create AppMetrica reporter")
return // or return someDefaultValue or throw someError
}
reporter.resumeSession()
// ...
reporter.reportEvent(name: "Updates installed", onFailure: { (error) in
print("REPORT ERROR: %@", error.localizedDescription)
})
// ...
reporter.pauseSession()
-
Use the
+reporterForAPIKey:
method of theAMAAppMetrica
class to get the instance that implements theAMAAppMetricaReporting
protocol.If the reporter was not initialized with an extended configuration, calling this method will initialize the reporter for the specified API key.
-
Use methods of the
AMAAppMetricaReporting
protocol to send events and revenue. -
To ensure that sessions are tracked correctly, set up sending session start and pause events for each reporter.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"API key"];
[reporter resumeSession];
// ...
[reporter reportEvent:@"Updates installed" onFailure:^(NSError *error) {
NSLog(@"REPORT ERROR: %@", [error localizedDescription]);
}];
// ...
[reporter pauseSession];
What is an API key?
The API key is a unique app ID issued in the AppMetrica web interface at app registration. You can find it under Settings.
Tracking app crashes
Reports on app crashes are sent by default.
To disable automatic tracking, pass the configuration in which sending crashes is disabled to the crash module.
To do this, set the false
value for the autoCrashTracking
property of the AppMetricaCrashesConfiguration
configuration.
// Creating a crashes configuration.
let configuration = AppMetricaCrashesConfiguration()
// Disabling sending the information on crashes of the application.
configuration.autoCrashTracking = false
// Set the configuration for AppMetricaCrashes.
AppMetricaCrashes.crashes().setConfiguration(configuration)
To do this, set the NO
value for the autoCrashTracking
property of the AMAAppMetricaCrashesConfiguration
configuration.
// Creating a crashes configuration.
AMAAppMetricaCrashesConfiguration *configuration = [[AMAAppMetricaCrashesConfiguration alloc] init];
// Disabling sending the information on crashes of the application.
configuration.autoCrashTracking = NO;
// Set the configuration in AppMetricaCrashes.
[[AMAAppMetricaCrashes crashes] setConfiguration:configuration];
Determining the location
AppMetrica can determine the location of a device. Location accuracy depends on the configuration that the library uses for initialization:
-
With the
locationTracking
option enabled. For iOS, the option is enabled by default.The location is determined with accuracy to the city. You can retrieve this information in reports and via the Logs API.
The app requests GPS access. Battery consumption may increase.
-
With the
locationTracking
option disabled.The location is determined by the IP address with accuracy to the country. You can retrieve this information in reports and via the Logs API.
The app requests GPS access. Battery consumption does not increase.
Note
If you have enabled IP address masking, AppMetrica determines location with the accuracy to the country by the unmasked part of the IP address.
By default, the AppMetrica SDK is initialized with locationTracking
enabled, but it doesn't request permission to get location data. You should implement this using methods of the CLLocationManager class.
To initialize a library with locationTracking
disabled, set the locationTracking
property of the AppMetricaConfiguration
configuration to false
.
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Disabling sending information about the location of the device.
configuration.locationTracking = false
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
To disable locationTracking
after initializing the library, use the isLocationTrackingEnabled
property of the AppMetrica
class:
AppMetrica.isLocationTrackingEnabled = false
To initialize a library with locationTracking
disabled, set the locationTracking
property of the AMAAppMetricaConfiguration
configuration to NO
.
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Disabling sending information about the device location.
configuration.locationTracking = NO;
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
To disable locationTracking
after initializing the library, use the +setLocationTrackingEnabled:
method of the AMAAppMetrica
class:
AMAAppMetrica.locationTrackingEnabled = NO;
Setting device location manually
Before sending custom information about the device location, make sure that reporting is enabled.
By default, the device location is detected by the library.
To send custom device location, pass the CLLocation instance to the customLocation
property of the AppMetrica
class.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
AppMetrica.customLocation = locations.last
}
To send custom device location using the startup configuration, pass the CLLocation instance to the customLocation
property of the AppMetricaConfiguration
configuration.
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Set a custom location.
configuration.customLocation = CLLocation(latitude: 0, longitude: 0)
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
To send custom device location, pass the CLLocation instance to the setCustomLocation
method of the AMAAppMetrica
class.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
AMAAppMetrica.customLocation = newLocation;
}
To send custom device location using the startup configuration, pass the CLLocation instance to the customLocation
property of the AMAAppMetricaConfiguration
configuration.
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Set a custom location.
configuration.customLocation = [[CLLocation alloc] initWithLatitude:0 longitude:0];
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
Sending a custom event
To send a custom event without nested parameters, pass the following parameters to the reportEvent(name:onFailure:)
method of the AppMetrica
class:
name
: Short name or description of the event.onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
var message = "Updates installed"
AppMetrica.reportEvent(name: message, onFailure: { (error) in
print("DID FAIL TO REPORT EVENT: %@", message)
print("REPORT ERROR: %@", error.localizedDescription)
})
To send a custom event without nested parameters, pass the following parameters to the +reportEvent:onFailure:
method of the AMAAppMetrica
class:
message
: Short name or description of the event.onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
NSString *message = @"Updates installed";
[AMAAppMetrica reportEvent:message onFailure:^(NSError *error) {
NSLog(@"DID FAIL REPORT EVENT: %@", message);
NSLog(@"REPORT ERROR: %@", [error localizedDescription]);
}];
Sending a custom event with nested parameters
To send a custom event with nested parameters, pass the following parameters to the reportEvent(name:parameters:onFailure:)
method of the AppMetrica
class:
-
name
: Short name or description of the event. -
parameters
: Nested parameters as key-value pairs.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.
-
onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
var message = "Updates installed"
let params = ["key1": "value1", "key2": "value2"]
AppMetrica.reportEvent(name: message, parameters: params, onFailure: { (error) in
print("DID FAIL REPORT EVENT: %@", message)
print("REPORT ERROR: %@", error.localizedDescription)
})
To send a custom event with nested parameters, pass the following parameters to the +reportEvent:parameters:onFailure:
method of the AMAAppMetrica
class:
-
message
: Short name or description of the event. -
parameters
: Nested parameters as key-value pairs.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.
-
onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
NSString *message = @"Updates installed";
NSDictionary *params = @{@"key1": @"value1", @"key2": @"value2"};
[AMAAppMetrica reportEvent:message parameters:params onFailure:^(NSError *error) {
NSLog(@"DID FAIL REPORT EVENT: %@", message);
NSLog(@"REPORT ERROR: %@", [error localizedDescription]);
}];
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. To do this, you need to connect the AppMetricaWebKit
module via the dependency management system that you're using.
Add the import:
import AppMetricaWebKit
Initialize the sending by calling the setupWebViewReporting(with:onFailure:)
method:
let userController = WKUserContentController()
AppMetrica.setupWebViewReporting(with: JSController(userContentController:userController), onFailure: nil)
userController.add(myHandler, name: myScriptName)
let configuration = WKWebViewConfiguration()
configuration.userContentController = userController;
let webView = WKWebView(frame: .zero, configuration: configuration)
Add the import:
#import <AppMetricaWebKit/AppMetricaWebKit.h>
Initialize the sending by calling the +setupWebViewReporting:onFailure:
method:
WKUserContentController *userController = [[WKUserContentController alloc] init];
[AMAAppMetrica setupWebViewReporting:[[AMAJSController alloc] initWithUserContentController:userController] onFailure:nil];
[userController addScriptMessageHandler:myHandler name:myScriptName];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userController;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
Call this method before loading any content. We recommend calling this method before creating a webview and before adding your scripts to WKUserContentController.
To send an event from JavaScript code, use the reportEvent(name, value)
method in the AppMetrica interface:
function buttonClicked() {
AppMetrica.reportEvent('Button clicked!', '{}');
}
Arguments of the reportEvent
method:
name
: A string. Can't benull
or empty.value
: A JSON string. Can benull
.
Sending an error message
To send an error message, you need to connect the AppMetricaCrashes
module via the dependency management system that you're using.
To send a custom error message, add the import:
import AppMetricaCrashes
Then use the methods of the AppMetricaCrashes
class and the AppMetricaCrashReporting
protocol:
report(error:onFailure:)
report(error:options:onFailure:)
report(nserror:onFailure:)
report(nserror:options:onFailure:)
To send error messages, you can use the standard NSError class, the simplified AppMetricaError
class, or the ErrorRepresentable
protocol.
To send a custom error message, add the import:
#import <AppMetricaCrashes/AppMetricaCrashes.h>
Then use the methods of the AMAAppMetricaCrashes
class and the AMAAppMetricaCrashReporting
protocol:
-reportError:onFailure:
-reportError:options:onFailure:
-reportNSError:onFailure:
-reportNSError:options:onFailure:
To send error messages, you can use the standard NSError class, the simplified AMAError
class, or the AMAErrorRepresentable
protocol.
Example with NSError
If errors are sent using the NSError class, they're grouped by the domain domain and the code error code.
let firstError = NSError(domain: "io.appmetrica.error-a", code: 12, userInfo: [
BacktraceErrorKey: Thread.callStackReturnAddresses,
NSLocalizedDescriptionKey: "Error A"
])
AppMetricaCrashes.crashes().report(nserror: firstError)
NSError *firstError = [NSError errorWithDomain:@"io.appmetrica.error-a"
code:12
userInfo:@{
AMABacktraceErrorKey: NSThread.callStackReturnAddresses,
NSLocalizedDescriptionKey: @"Error A"
}];
[[AMAAppMetricaCrashes crashes] reportNSError:firstError onFailure:nil];
Example with AppMetricaError
If errors are sent using the AppMetricaError
class or the ErrorRepresentable
protocol, they're grouped by the identifier
.
let underlyingError = AppMetricaError(identifier: "Underlying AMAError")
let error = AppMetricaError(
identifier: "AMAError identifier",
message: "Another custom message",
parameters: [
"foo": "bar"
],
backtrace: Thread.callStackReturnAddresses,
underlyingError: underlyingError
)
AppMetricaCrashes.crashes().report(error: error)
If errors are sent using the AMAError
class or the AMAErrorRepresentable
protocol, they're grouped by the identifier
.
AMAError *underlyingError = [AMAError errorWithIdentifier:@"Underlying AMAError"];
AMAError *error = [AMAError errorWithIdentifier:@"AMAError identifier"
message:@"Another custom message"
parameters:@{ @"foo": @"bar" }
backtrace:NSThread.callStackReturnAddresses
underlyingError:underlyingError];
[[AMAAppMetricaCrashes crashes] reportError:error onFailure:nil];
Don't use variable values as grouping IDs. Otherwise, the number of groups increases and it becomes difficult to analyze them.
Sending profile attributes
To send profile attributes, pass the following parameters to the reportUserProfile(_:onFailure:)
method of the AppMetrica
class:
userProfile
: TheUserProfile
instance that contains an array of attribute updates. Profile attributes are created by methods of theProfileAttribute
class.onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
let profile = MutableUserProfile()
// Updating a single user profile attribute.
let timeLeftAttribute = ProfileAttribute.customCounter("time_left")
profile.apply(timeLeftAttribute.withDelta(-4.42))
// Updating multiple attributes.
profile.apply(from: [
// Updating predefined attributes.
ProfileAttribute.name().withValue("John"),
ProfileAttribute.gender().withValue(GenderType.male),
ProfileAttribute.birthDate().withAge(24),
ProfileAttribute.notificationsEnabled().withValue(false),
// Updating custom attributes.
ProfileAttribute.customString("born_in").withValueIfUndefined("Moscow"),
ProfileAttribute.customString("address").withValueReset(),
ProfileAttribute.customNumber("age").withValue(24),
ProfileAttribute.customCounter("logins_count").withDelta(1),
ProfileAttribute.customBool("has_premium").withValue(true)
])
// ProfieID is set using the method of the AppMetrica class.
AppMetrica.userProfileID = "id"
// Sending profile attributes.
AppMetrica.reportUserProfile(profile, onFailure: { (error) in
print("REPORT ERROR: %@", error.localizedDescription)
})
To send profile attributes, pass the following parameters to the +reportUserProfile:onFailure:
method of the AMAAppMetrica
class:
userProfile
: TheAMAUserProfile
instance that contains an array of attribute updates. To create profile attributes, use methods of theAMAProfileAttribute
class.onFailure
: The block the error is passed to. If you do not want to track the error, passnil
for this block.
AMAMutableUserProfile *profile = [[AMAMutableUserProfile alloc] init];
// Updating a single user profile attribute.
id<AMACustomCounterAttribute> timeLeftAttribute = [AMAProfileAttribute customCounter:@"time_left"];
[profile apply:[timeLeftAttribute withDelta:-4.42]];
// Updating multiple attributes.
[profile applyFromArray:@[
// Updating predefined attributes.
[[AMAProfileAttribute name] withValue:@"John"],
[[AMAProfileAttribute gender] withValue:AMAGenderTypeMale],
[[AMAProfileAttribute birthDate] withAge:24],
[[AMAProfileAttribute notificationsEnabled] withValue:NO],
// Updating custom attributes.
[[AMAProfileAttribute customString:@"born_in"] withValueIfUndefined:@"Moscow"],
[[AMAProfileAttribute customString:@"address"] withValueReset],
[[AMAProfileAttribute customNumber:@"age"] withValue:24],
[[AMAProfileAttribute customCounter:@"logins_count"] withDelta:1],
[[AMAProfileAttribute customBool:@"has_premium"] withValue:YES]
]];
// ProfieID is set using the method of the AMAAppMetrica class.
[AMAAppMetrica setUserProfileID:@"id"];
// Sending profile attributes.
[AMAAppMetrica reportUserProfile:[profile copy] onFailure:^(NSError *error) {
NSLog(@"Error: %@", error);
}];
Sending ProfileId
If you don't configure ProfileId
sending in the SDK, the web interface displays the appmetrica_device_id
value.
To send the ProfileId
, use the userProfileID
property of the AppMetrica
class.
AppMetrica.userProfileID = "id"
To send the ProfileId
, use the +setUserProfileID:
method of the AMAAppMetrica
class.
AMAAppMetrica.userProfileID = @"id";
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 ECommerce
class method.
The examples below show how to send specific types of events:
Opening a page
// Creating a screen object.
let screen = ECommerceScreen(
name: "ProductCardScreen",
categoryComponents: ["Promos", "Hot deal"],
searchQuery: "danissimo maple syrup",
payload: ["full_screen": "true"]
)
// Sending an e-commerce event.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportECommerce(.showScreenEvent(screen: screen))
}
// Creating a screen object.
AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:@"ProductCardScreen"
categoryComponents:@[ @"Promos", @"Hot deal" ]
searchQuery:@"danissimo maple syrup"
payload:@{ @"full_screen": @"true" }];
// Sending an e-commerce event.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportECommerce:[AMAECommerce showScreenEventWithScreen:screen] onFailure:nil];
Viewing a product card
// Creating a screen object.
let screen = ECommerceScreen(
name: "ProductCardScreen",
categoryComponents: ["Promos", "Hot deal"],
searchQuery: "danissimo maple syrup",
payload: ["full_screen": "true"]
)
// Creating an actualPrice object.
let actualPrice = ECommercePrice(
fiat: .init(unit: "USD", value: .init(string: "4.53")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30570000")),
.init(unit: "iron", value: .init(string: "26.89")),
.init(unit: "gold", value: .init(string: "5.1")),
]
)
// Creating a product object.
let product = ECommerceProduct(
sku: "779213",
name: "Danissimo curd product 5.9%, 130 g",
categoryComponents: ["Groceries", "Dairy products", "Yogurts"],
payload: ["full_screen": "true"],
actualPrice: actualPrice,
originalPrice: .init(
fiat: .init(unit: "USD", value: .init(string: "5.78")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30590000")),
.init(unit: "iron", value: .init(string: "26.92")),
.init(unit: "gold", value: .init(string: "5.5")),
]
),
promoCodes: ["BT79IYX", "UT5412EP"]
)
// Sending an e-commerce event.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportECommerce(.showProductCardEvent(product: product, screen: screen))
}
// Creating a screen object.
AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:@"ProductCardScreen"
categoryComponents:@[ @"Promos", @"Hot deal" ]
searchQuery:@"danissimo maple syrup"
payload:@{ @"full_screen": @"true" }];
// Creating an actualPrice object.
AMAECommerceAmount *actualFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"4.53"]];
AMAECommerceAmount *woodActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30570000"]];
AMAECommerceAmount *ironActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.89"]];
AMAECommerceAmount *goldActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.1"]];
AMAECommercePrice *actualPrice = [[AMAECommercePrice alloc] initWithFiat:actualFiat
internalComponents:@[ woodActualPrice, ironActualPrice, goldActualPrice ]];
// Creating an originalPrice object.
AMAECommerceAmount *originalFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"5.78"]];
AMAECommerceAmount *woodOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30590000"]];
AMAECommerceAmount *ironOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.92"]];
AMAECommerceAmount *goldOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.5"]];
AMAECommercePrice *originalPrice = [[AMAECommercePrice alloc] initWithFiat:originalFiat
internalComponents:@[ woodOriginalPrice, ironOriginalPrice, goldOriginalPrice ]];
// Creating a product object.
AMAECommerceProduct *product = [[AMAECommerceProduct alloc] initWithSKU:@"779213"
name:@"Danissimo curd product 5.9%, 130 g"
categoryComponents:@[ @"Groceries", @"Dairy products", @"Yogurts" ]
payload:@{ @"full_screen" : @"true" }
actualPrice:actualPrice
originalPrice:originalPrice
promoCodes:@[ @"BT79IYX", @"UT5412EP" ]];
// Sending an e-commerce event.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportECommerce:[AMAECommerce showProductCardEventWithProduct:product screen:screen] onFailure:nil];
Viewing a product page
// Creating a screen object.
let screen = ECommerceScreen(
name: "ProductCardScreen",
categoryComponents: ["Promos", "Hot deal"],
searchQuery: "danissimo maple syrup",
payload: ["full_screen": "true"]
)
// Creating an actualPrice object.
let actualPrice = ECommercePrice(
fiat: .init(unit: "USD", value: .init(string: "4.53")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30570000")),
.init(unit: "iron", value: .init(string: "26.89")),
.init(unit: "gold", value: .init(string: "5.1")),
]
)
// Creating a product object.
let product = ECommerceProduct(
sku: "779213",
name: "Danissimo curd product 5.9%, 130 g",
categoryComponents: ["Groceries", "Dairy products", "Yogurts"],
payload: ["full_screen": "true"],
actualPrice: actualPrice,
originalPrice: .init(
fiat: .init(unit: "USD", value: .init(string: "5.78")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30590000")),
.init(unit: "iron", value: .init(string: "26.92")),
.init(unit: "gold", value: .init(string: "5.5")),
]
),
promoCodes: ["BT79IYX", "UT5412EP"]
)
// Creating a referrer object.
let referrer = ECommerceReferrer(type: "button", identifier: "76890", screen: screen)
// Sending an e-commerce event.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportECommerce(.showProductDetailsEvent(product: product, referrer: referrer))
}
// Creating a screen object.
AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:@"ProductCardScreen"
categoryComponents:@[ @"Promos", @"Hot deal" ]
searchQuery:@"danissimo maple syrup"
payload:@{ @"full_screen": @"true" }];
// Creating an actualPrice object.
AMAECommerceAmount *actualFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"4.53"]];
AMAECommerceAmount *woodActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30570000"]];
AMAECommerceAmount *ironActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.89"]];
AMAECommerceAmount *goldActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.1"]];
AMAECommercePrice *actualPrice = [[AMAECommercePrice alloc] initWithFiat:actualFiat
internalComponents:@[ woodActualPrice, ironActualPrice, goldActualPrice ]];
// Creating an originalPrice object.
AMAECommerceAmount *originalFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"5.78"]];
AMAECommerceAmount *woodOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30590000"]];
AMAECommerceAmount *ironOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.92"]];
AMAECommerceAmount *goldOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.5"]];
AMAECommercePrice *originalPrice = [[AMAECommercePrice alloc] initWithFiat:originalFiat
internalComponents:@[ woodOriginalPrice, ironOriginalPrice, goldOriginalPrice ]];
// Creating a product object.
AMAECommerceProduct *product = [[AMAECommerceProduct alloc] initWithSKU:@"779213"
name:@"Danissimo curd product 5.9%, 130 g"
categoryComponents:@[ @"Groceries", @"Dairy products", @"Yogurts" ]
payload:@{ @"full_screen" : @"true" }
actualPrice:actualPrice
originalPrice:originalPrice
promoCodes:@[ @"BT79IYX", @"UT5412EP" ]];
// Creating a referrer object.
AMAECommerceReferrer *referrer = [[AMAECommerceReferrer alloc] initWithType:@"button"
identifier:@"76890"
screen:screen];
// Sending an e-commerce event.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportECommerce:[AMAECommerce showProductDetailsEventWithProduct:product referrer:referrer] onFailure:nil];
Adding or removing an item to/from the cart
// Creating a screen object.
let screen = ECommerceScreen(
name: "ProductCardScreen",
categoryComponents: ["Promos", "Hot deal"],
searchQuery: "danissimo maple syrup",
payload: ["full_screen": "true"]
)
// Creating an actualPrice object.
let actualPrice = ECommercePrice(
fiat: .init(unit: "USD", value: .init(string: "4.53")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30570000")),
.init(unit: "iron", value: .init(string: "26.89")),
.init(unit: "gold", value: .init(string: "5.1")),
]
)
// Creating a product object.
let product = ECommerceProduct(
sku: "779213",
name: "Danissimo curd product 5.9%, 130 g",
categoryComponents: ["Groceries", "Dairy products", "Yogurts"],
payload: ["full_screen": "true"],
actualPrice: actualPrice,
originalPrice: .init(
fiat: .init(unit: "USD", value: .init(string: "5.78")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30590000")),
.init(unit: "iron", value: .init(string: "26.92")),
.init(unit: "gold", value: .init(string: "5.5")),
]
),
promoCodes: ["BT79IYX", "UT5412EP"]
)
// Creating a referrer object.
let referrer = ECommerceReferrer(type: "button", identifier: "76890", screen: screen)
// Creating a cartItem object.
let addedItems = ECommerceCartItem(
product: product,
quantity: .init(string: "1"),
revenue: actualPrice,
referrer: referrer
)
// Sending an e-commerce event.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportECommerce(.addCartItemEvent(cartItem: addedItems))
// Or:
reporter.reportECommerce(.removeCartItemEvent(cartItem: addedItems))
}
// Creating a screen object.
AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:@"ProductCardScreen"
categoryComponents:@[ @"Promos", @"Hot deal" ]
searchQuery:@"danissimo maple syrup"
payload:@{ @"full_screen": @"true" }];
// Creating an actualPrice object.
AMAECommerceAmount *actualFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"4.53"]];
AMAECommerceAmount *woodActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30570000"]];
AMAECommerceAmount *ironActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.89"]];
AMAECommerceAmount *goldActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.1"]];
AMAECommercePrice *actualPrice = [[AMAECommercePrice alloc] initWithFiat:actualFiat
internalComponents:@[ woodActualPrice, ironActualPrice, goldActualPrice ]];
// Creating an originalPrice object.
AMAECommerceAmount *originalFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"5.78"]];
AMAECommerceAmount *woodOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30590000"]];
AMAECommerceAmount *ironOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.92"]];
AMAECommerceAmount *goldOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.5"]];
AMAECommercePrice *originalPrice = [[AMAECommercePrice alloc] initWithFiat:originalFiat
internalComponents:@[ woodOriginalPrice, ironOriginalPrice, goldOriginalPrice ]];
// Creating a product object.
AMAECommerceProduct *product = [[AMAECommerceProduct alloc] initWithSKU:@"779213"
name:@"Danissimo curd product 5.9%, 130 g"
categoryComponents:@[ @"Groceries", @"Dairy products", @"Yogurts" ]
payload:@{ @"full_screen" : @"true" }
actualPrice:actualPrice
originalPrice:originalPrice
promoCodes:@[ @"BT79IYX", @"UT5412EP" ]];
// Creating a referrer object.
AMAECommerceReferrer *referrer = [[AMAECommerceReferrer alloc] initWithType:@"button"
identifier:@"76890"
screen:screen];
// Creating a cartItem object.
NSDecimalNumber *quantity = [NSDecimalNumber decimalNumberWithString:@"1"];
AMAECommerceCartItem *addedItems = [[AMAECommerceCartItem alloc] initWithProduct:product
quantity:quantity
revenue:actualPrice
referrer:referrer];
// Sending an e-commerce event.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportECommerce:[AMAECommerce addCartItemEventWithItem:addedItems] onFailure:nil];
// Or:
[reporter reportECommerce:[AMAECommerce removeCartItemEventWithItem:addedItems] onFailure:nil];
Starting and completing a purchase
// Creating a screen object.
let screen = ECommerceScreen(
name: "ProductCardScreen",
categoryComponents: ["Promos", "Hot deal"],
searchQuery: "danissimo maple syrup",
payload: ["full_screen": "true"]
)
// Creating an actualPrice object.
let actualPrice = ECommercePrice(
fiat: .init(unit: "USD", value: .init(string: "4.53")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30570000")),
.init(unit: "iron", value: .init(string: "26.89")),
.init(unit: "gold", value: .init(string: "5.1")),
]
)
// Creating a product object.
let product = ECommerceProduct(
sku: "779213",
name: "Danissimo curd product 5.9%, 130 g",
categoryComponents: ["Groceries", "Dairy products", "Yogurts"],
payload: ["full_screen": "true"],
actualPrice: actualPrice,
originalPrice: .init(
fiat: .init(unit: "USD", value: .init(string: "5.78")),
internalComponents: [
.init(unit: "wood", value: .init(string: "30590000")),
.init(unit: "iron", value: .init(string: "26.92")),
.init(unit: "gold", value: .init(string: "5.5")),
]
),
promoCodes: ["BT79IYX", "UT5412EP"]
)
// Creating a referrer object.
let referrer = ECommerceReferrer(type: "button", identifier: "76890", screen: screen)
// Creating a cartItem object.
let addedItems = ECommerceCartItem(
product: product,
quantity: .init(string: "1"),
revenue: actualPrice,
referrer: referrer
)
// Creating an order object.
let order = ECommerceOrder(
identifier: "88528768",
cartItems: [addedItems],
payload: ["black_friday": "true"]
)
// Sending an e-commerce event.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportECommerce(.beginCheckoutEvent(order:order))
reporter.reportECommerce(.purchaseEvent(order: order))
}
// Creating a screen object.
AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:@"ProductCardScreen"
categoryComponents:@[ @"Promos", @"Hot deal" ]
searchQuery:@"danissimo maple syrup"
payload:@{ @"full_screen": @"true" }];
// Creating an actualPrice object.
AMAECommerceAmount *actualFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"4.53"]];
AMAECommerceAmount *woodActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30570000"]];
AMAECommerceAmount *ironActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.89"]];
AMAECommerceAmount *goldActualPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.1"]];
AMAECommercePrice *actualPrice = [[AMAECommercePrice alloc] initWithFiat:actualFiat
internalComponents:@[ woodActualPrice, ironActualPrice, goldActualPrice ]];
// Creating an originalPrice object.
AMAECommerceAmount *originalFiat =
[[AMAECommerceAmount alloc] initWithUnit:@"USD" value:[NSDecimalNumber decimalNumberWithString:@"5.78"]];
AMAECommerceAmount *woodOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"wood" value:[NSDecimalNumber decimalNumberWithString:@"30590000"]];
AMAECommerceAmount *ironOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"iron" value:[NSDecimalNumber decimalNumberWithString:@"26.92"]];
AMAECommerceAmount *goldOriginalPrice =
[[AMAECommerceAmount alloc] initWithUnit:@"gold" value:[NSDecimalNumber decimalNumberWithString:@"5.5"]];
AMAECommercePrice *originalPrice = [[AMAECommercePrice alloc] initWithFiat:originalFiat
internalComponents:@[ woodOriginalPrice, ironOriginalPrice, goldOriginalPrice ]];
// Creating a product object.
AMAECommerceProduct *product = [[AMAECommerceProduct alloc] initWithSKU:@"779213"
name:@"Danissimo curd product 5.9%, 130 g"
categoryComponents:@[ @"Groceries", @"Dairy products", @"Yogurts" ]
payload:@{ @"full_screen" : @"true" }
actualPrice:actualPrice
originalPrice:originalPrice
promoCodes:@[ @"BT79IYX", @"UT5412EP" ]];
// Creating a referrer object.
AMAECommerceReferrer *referrer = [[AMAECommerceReferrer alloc] initWithType:@"button"
identifier:@"76890"
screen:screen];
// Creating a cartItem object.
NSDecimalNumber *quantity = [NSDecimalNumber decimalNumberWithString:@"1"];
AMAECommerceCartItem *addedItems = [[AMAECommerceCartItem alloc] initWithProduct:product
quantity:quantity
revenue:actualPrice
referrer:referrer];
// Creating an order object.
AMAECommerceOrder *order = [[AMAECommerceOrder alloc] initWithIdentifier:@"88528768"
cartItems:@[ addedItems ]
payload:@{ @"black_friday" : @"true"}];
// Sending an e-commerce event.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportECommerce:[AMAECommerce beginCheckoutEventWithOrder:order] onFailure:nil];
[reporter reportECommerce:[AMAECommerce purchaseEventWithOrder:order] onFailure:nil];
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 ECommerce
object to the main API key, use the reportECommerce(_:onFailure:)
method of the AppMetrica
class.
// ...
// Sending an E-commerce event.
AppMetrica.reportECommerce(.showScreenEvent(screen: screen))
To send the AMAECommerce
instance to the main API key, use the +reportECommerce:onFailure:
method of the AMAAppMetrica
class.
// ...
// Sending an E-commerce event.
[AMAAppMetrica reportECommerce:[AMAECommerce showScreenEventWithScreen:screen] onFailure:nil];
Sending Revenue
AppMetrica supports validation of purchases implemented using the StoreKit 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
To validate purchases, enable the validation in the settings. For more information, see Sending in-app purchases on iOS.
Step 1. Test sending Revenue
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 iOS, configure sending the transactionID
field and receiptData
where you implement the transaction completion:
- Initialize the
MutableRevenueInfo
instance. - To validate a purchase, specify
transactionID
andreceiptData
. You should receive them before invokingSKPaymentQueue.default ().finishTransaction(transaction)
. - Send the
MutableRevenueInfo
instance to the test API key using theAppMetricaReporting
reporter. For more information about reporters, see Sending statistics to an additional API key.
func completeTransaction(_ transaction: SKPaymentTransaction) {
// ...
let price = NSDecimalNumber(string: "2100.5")
// Initializing the Revenue instance.
let revenueInfo = MutableRevenueInfo(priceDecimal: price, currency: "BYN")
revenueInfo.productID = "TV soundbar"
revenueInfo.quantity = 2
revenueInfo.payload = ["source": "AppStore"]
// Set purchase information for validation.
if let url = Bundle.main.appStoreReceiptURL, let data = try? Data(contentsOf: url), let transactionID = transaction.transactionIdentifier {
revenueInfo.transactionID = transactionID
revenueInfo.receiptData = data
}
// Sending the Revenue instance using reporter.
guard let reporter = AppMetrica.reporter(for: "Testing API key") else {
print("Failed to create AppMetrica reporter")
return
}
reporter.reportRevenue(revenueInfo, onFailure: { (error) in
print("Revenue error: \(error.localizedDescription)")
})
// Remove the transaction from the payment queue.
SKPaymentQueue.default().finishTransaction(transaction)
}
- Initialize the
AMAMutableRevenueInfo
instance. - To validate a purchase, specify
transactionID
andreceiptData
. The must be received before[[SKPaymentQueue defaultQueue] finishTransaction:transaction]
is invoked. - Send the
AMAMutableRevenueInfo
instance to the test API key using theAMAAppMetricaReporting
reporter. For more information about reporters, see Sending statistics to an additional API key.
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
// ...
NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:@"2100.5"];
// Initializing the Revenue instance.
AMAMutableRevenueInfo *revenueInfo = [[AMAMutableRevenueInfo alloc] initWithPriceDecimal:price currency:@"BYN"];
revenueInfo.productID = @"TV soundbar";
revenueInfo.quantity = 2;
revenueInfo.payload = @{ @"source": @"AppStore" };
// Set purchase information for validation.
revenueInfo.transactionID = transaction.transactionIdentifier;
revenueInfo.receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
// Sending the Revenue instance using reporter.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportRevenue:[revenueInfo copy] onFailure:^(NSError *error) {
NSLog(@"Revenue error: %@", error);
}];
// Remove the transaction from the payment queue.
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
Without validation
To send information about a purchase without validation:
-
Initialize the
MutableRevenueInfo
instance. -
(Optional) To group purchases by
OrderID
, specify it in thepayload
property.Note
If the
OrderID
is not specified, AppMetrica generates the ID automatically. -
Send the
MutableRevenueInfo
instance to the test API key using theAppMetricaReporting
reporter. For more information about reporters, see Sending statistics to an additional API key.
let price = NSDecimalNumber(string: "2100.5")
// Initializing the Revenue instance.
let revenueInfo = MutableRevenueInfo(priceDecimal: price, currency: "BYN")
revenueInfo.productID = "TV soundbar"
revenueInfo.quantity = 2
// To group purchases, set the OrderID parameter in the payload property.
revenueInfo.payload = ["OrderID": "Identifier", "source": "AppStore"]
// Sending the Revenue instance using reporter.
if let reporter = AppMetrica.reporter(for: "Testing API key") {
reporter.reportRevenue(revenueInfo, onFailure: { (error) in
print("Revenue error: \(error.localizedDescription)")
})
}
-
Initialize the
AMAMutableRevenueInfo
instance. -
(Optional) To group purchases by
OrderID
, specify it in thepayload
property.Note
If the
OrderID
is not specified, AppMetrica generates the ID automatically. -
Send the
AMAMutableRevenueInfo
instance to the test API key using theAMAAppMetricaReporting
reporter. For more information about reporters, see Sending statistics to an additional API key.
NSDecimalNumber *price = [NSDecimalNumber decimalNumberWithString:@"2100.5"];
// Initializing the Revenue instance.
AMAMutableRevenueInfo *revenueInfo = [[AMAMutableRevenueInfo alloc] initWithPriceDecimal:price currency:@"BYN"];
revenueInfo.productID = @"TV soundbar";
revenueInfo.quantity = 2;
// Setting the OrderID parameter in the payload property to group purchases
revenueInfo.payload = @{ @"OrderID": @"Identifier", @"source": @"AppStore" };
// Sending the Revenue instance using reporter.
id<AMAAppMetricaReporting> reporter = [AMAAppMetrica reporterForAPIKey:@"Testing API key"];
[reporter reportRevenue:[revenueInfo copy] onFailure:^(NSError *error) {
NSLog(@"Revenue error: %@", error);
}];
Step 2. Configure sending Revenue to the main API key
After successful testing, configure sending Revenue to the main API key.
To send the MutableRevenueInfo
instance to the main API key, use the reportRevenue(_:onFailure:)
method of the AppMetrica
class.
// ...
// Sending the Revenue instance.
AppMetrica.reportRevenue(revenueInfo, onFailure: { (error) in
print("Revenue error: \(error)")
})
To send the AMAMutableRevenueInfo
instance to the main API key, use the +reportRevenue:onFailure:
method of the AMAAppMetrica
class.
// ...
// Sending the Revenue instance.
[AMAAppMetrica reportRevenue:[revenueInfo copy] onFailure:^(NSError *error) {
NSLog(@"Revenue error: %@", error);
}];
Setting the session timeout
By default, the session timeout is 10 seconds. This is the minimum acceptable value for the sessionTimeout
property.
To change the timeout length, pass the value in seconds to the sessionTimeout
property of the library configuration AppMetricaConfiguration
.
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Setting the session timeout.
configuration.sessionTimeout = 15
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
To change the timeout length, pass the value in seconds to the sessionTimeout
property of the library configuration AMAAppMetricaConfiguration
.
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Setting the session timeout.
configuration.sessionTimeout = 15;
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
Setting the app version
By default, the app version is set in the app configuration file Info.plist (CFBundleShortVersionString
).
To specify the app version from the code, pass it to the appVersion
property of the AppMetricaConfiguration
configuration.
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Setting the app version.
configuration.appVersion = "1.13.2"
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
To specify the app version from the code, pass it to the appVersion
property of the AMAAppMetricaConfiguration
configuration.
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Setting the app version.
configuration.appVersion = @"1.13.2";
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
Tracking app opens using deeplinks
Warning
Starting with version 4.0 of the AppMetrica SDK for iOS, app openings via deeplinks are tracked automatically. For other versions, set up tracking manually:
- iOS AppMetrica SDK version below 4.0. Setting up deeplink tracking for UIApplicationDelegate.
- Setting up deeplink tracking for UISceneDelegate (AppMetrica doesn't track such app openings automatically).
You need to track app openings to correctly track remarketing campaigns.
Note
To work with Universal Links, configure them for your application.
UISceneDelegate
To manually track app openings via universal links or deeplinks, in UISceneDelegate
, add the following code to the scene:willConnectToSession:options:
method:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions
{
//Universal Link
NSUserActivity *userActivity = [[connectionOptions.userActivities allObjects] firstObject];
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
[AMAAppMetrica trackOpeningURL:context.URL];
}
else {
//Deeplink
UIOpenURLContext *context = [[connectionOptions.URLContexts allObjects] firstObject];
if (context != nil) {
[AMAAppMetrica trackOpeningURL:context.URL];
}
}
}
To manually track app openings via universal links or deeplinks in a running app, use the following code:
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity
{
NSURL *url = userActivity.webpageURL;
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
[AMAAppMetrica trackOpeningURL:context.URL];
}
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
UIOpenURLContext *context = [[URLContexts allObjects] firstObject];
if (context != nil) {
[AMAAppMetrica trackOpeningURL:context.URL];
}
}
To manually track app openings via universal links or deeplinks, in UISceneDelegate
, add the following code to the scene(_:willConnectTo:options:)
method:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Universal Link
if let userActivity = connectionOptions.userActivities.first {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL {
AppMetrica.trackOpeningURL(url)
}
}
// Deep Link
if let context = connectionOptions.urlContexts.first {
AppMetrica.trackOpeningURL(context.url)
}
}
To manually track app openings via universal links or deeplinks in a running app, use the following code:
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else { return }
AppMetrica.trackOpeningURL(url)
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let context = URLContexts.first else { return }
AppMetrica.trackOpeningURL(context.url)
}
UIApplicationDelegate
Warning
Manual setup of tracking with UIApplicationDelegate is relevant for iOS AppMetrica SDK versions below 4.0.
To manually track app openings via universal links or deeplinks, use the +trackOpeningURL:
method of the AMAAppMetrica
class.
To manually track app openings using deeplinks or deeplink handling in a running app, use UIApplicationDelegate
and add the following modifications:
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
[AMAAppMetrica trackOpeningURL:url];
return YES;
}
// Delegate for tracking Universal links.
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
[AMAAppMetrica trackOpeningURL:userActivity.webpageURL];
}
return YES;
}
To manually track app openings via universal links or deeplinks, use the +trackOpeningURL:
method of the AMAAppMetrica
class.
To manually track app openings using deeplinks or deeplink handling in a running app, use UIApplicationDelegate
and add the following modifications:
func application(_ application: UIApplication, openURL url: URL, sourceApplication: String?, annotation: AnyObject) -> Bool {
AppMetrica.trackOpeningURL(url)
return true
}
// Delegate for tracking Universal links.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
if let url = userActivity.webpageURL {
AppMetrica.trackOpeningURL(url)
}
}
return true
}
Learn more
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.
To do this, initialize the AppMetrica SDK using the AMAAppMetricaConfiguration
extended startup configuration.
BOOL isFirstLaunch = NO;
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Implement the logic for detecting whether the app is starting 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 = YES;
}
configuration.handleFirstActivationAsUpdate = !isFirstLaunch;
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
To do this, initialize the AppMetrica SDK using the AppMetricaConfiguration
extended startup configuration.
var isFirstLaunch = false
// Creating an extended library configuration.
guard let configuration = AppMetricaConfiguration(apiKey: "API key") else {
print("AppMetricaConfiguration initialization failed.")
return // or return someDefaultValue or throw someError
}
// Implement the logic for detecting whether the app is starting 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
}
configuration.handleFirstActivationAsUpdate = !isFirstLaunch
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
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.
To do this, set the NO
value for the dataSendingEnabled
property of the AMAAppMetricaConfiguration
.
// Creating an extended library configuration.
AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:@"API key"];
// Disabling sending statistics.
configuration.dataSendingEnabled = NO;
// Initializing the AppMetrica SDK.
[AMAAppMetrica activateWithConfiguration:configuration];
After the user has consented to sending statistics (for example, in the app settings or in the agreement on the first start of the app), you should enable sending using the +setDataSendingEnabled:
method of the AMAAppMetrica
class.
// Checking the status of the boolean variable. It shows the user confirmation.
if (flag) {
// Enabling sending statistics.
[AMAAppMetrica setDataSendingEnabled:YES];
}
To do this, set the false
value for the dataSendingEnabled
property of the AppMetricaConfiguration
.
// Creating an extended library configuration.
if let configuration = AppMetricaConfiguration(apiKey: "API key") {
// Disabling sending statistics.
configuration.dataSendingEnabled = false
// Initializing the AppMetrica SDK.
AppMetrica.activate(with: configuration)
}
After the user has consented to sending statistics (for example, in the app settings or in the agreement on the first start of the app), you should enable sending using the setDataSendingEnabled(_:)
method of the AppMetrica
class.
// Checking the status of the boolean variable. It shows the user confirmation.
if flag {
// Enabling sending statistics.
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 requestStartupIdentifiersWithKeys()
/ requestStartupIdentifiers()
method. To get the appmetrica_device_id
, make sure to request the DeviceIdHash
.
AMAIdentifiersCompletionBlock block = ^(NSDictionary<AMAStartupKey,id> * _Nullable identifiers, NSError * _Nullable error) {
if (identifiers[kAMADeviceIDHashKey] != nil) {
NSLog(@"deviceIDHash = %@", identifiers[kAMADeviceIDHashKey]);
}
if (identifiers[kAMADeviceIDKey] != nil) {
NSLog(@"deviceID = %@", identifiers[kAMADeviceIDKey]);
}
if (identifiers[kAMAUUIDKey] != nil) {
NSLog(@"uuid = %@", identifiers[kAMAUUIDKey]);
}
};
[AMAAppMetrica requestStartupIdentifiersWithKeys:@[kAMADeviceIDHashKey, kAMADeviceIDKey, kAMAUUIDKey] completionQueue:nil completionBlock:block];
// Specifying the keys for which we need to get identifiers
let keys: [StartupKey] = [StartupKey.deviceIDKey, StartupKey.deviceIDHashKey, StartupKey.uuidKey]
// Specifying the queue on which the completion handler will be executed (for example, the main thread)
let queue = DispatchQueue.main
// Requesting IDs
AppMetrica.requestStartupIdentifiers(for: keys, on: queue) { identifiers, error in
if let error = error {
print("An error has occurred: \(error.localizedDescription)")
} else if let identifiers = identifiers {
// Processing the received IDs
if let deviceIDHash = identifiers[StartupKey.deviceIDHashKey] as? String {
print("AppMetrica deviceIDHash: \(deviceIDHash)")
}
if let deviceID = identifiers[StartupKey.deviceIDKey] as? String {
print("AppMetrica deviceID: \(deviceID)")
}
if let uuid = identifiers[StartupKey.uuidKey] as? String {
print("AppMetrica uuid: \(uuid)")
}
}
}
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.
An ad campaign aimed at getting users to come back to an app they previously installed. For more information, see Creating a remarketing tracker.