In-app события
Обзор
Общие сведения о внутренних событиях для разработчиков см. в статье Внутренние события приложения.
Прежде чем начать
Необходимо интегрировать SDK.
Регистрация внутренних событий приложения
SDK позволяет регистрировать действия пользователей в контексте приложения. Такие действия обычно называют внутренними событиями приложения.
The logEvent
method
logEvent
methodThe logEvent
method lets you log in-app events and send them to AppsFlyer for processing.
To access the logEvent
method, import AppsFlyerLib
:
import com.appsflyer.AppsFlyerLib;
import com.appsflyer.AppsFlyerLib
To access predefined event constants, import AFInAppEventType
and AFInAppEventParameterName
:
import com.appsflyer.AFInAppEventType; // Predefined event names
import com.appsflyer.AFInAppEventParameterName; // Predefined parameter names
import com.appsflyer.AFInAppEventType // Predefined event names
import com.appsflyer.AFInAppEventParameterName // Predefined parameter names
logEvent
принимает четыре аргумента:
void logEvent(Context context,
java.lang.String eventName,
java.util.Map<java.lang.String,java.lang.Object> eventValues,
AppsFlyerRequestListener listener)
- The first argument (
context
) is the Application/Activity Context - The second argument (
eventName
) is the In-app event name - The third argument (
eventValues
) is the event parametersMap
- The fourth argument (
listener
) is an optionalAppsFlyerRequestListener
(useful for Handling event submission success/failure)
Example: Send "add to wishlist" event
Например, чтобы зарегистрировать, что пользователь добавил товар в список желаний:
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.PRICE, 1234.56);
eventValues.put(AFInAppEventParameterName.CONTENT_ID,"1234567");
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.ADD_TO_WISHLIST , eventValues);
val eventValues = HashMap<String, Any>()
eventValues.put(AFInAppEventParameterName.PRICE, 1234.56)
eventValues.put(AFInAppEventParameterName.CONTENT_ID,"1234567")
AppsFlyerLib.getInstance().logEvent(getApplicationContext() ,
AFInAppEventType.ADD_TO_WISHLIST , eventValues)
In the above logEvent
invocation:
- Имя события
AFInAppEventType.ADD_TO_WISHLIST
- The event value is a
Map
containing these event parameters:- AFInAppEventParameterName.PRICE: цена, связанная с событием.
- AFInAppEventParameterName.CONTENT_ID: идентификатор добавленного товара.
Implementing event structure definitions
На основе примера определения из раздела Определение структуры событий, событие следует реализовать следующим образом:
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.PRICE, <ITEM_PRICE>);
eventValues.put(AFInAppEventParameterName.CONTENT_TYPE, <ITEM_TYPE>);
eventValues.put(AFInAppEventParameterName.CONTENT_ID, <ITEM_SKU>);
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.CONTENT_VIEW, eventValues);
val eventValues = HashMap<String, Any>()
eventValues.put(AFInAppEventParameterName.PRICE, <ITEM_PRICE>)
eventValues.put(AFInAppEventParameterName.CONTENT_TYPE, <ITEM_TYPE>)
eventValues.put(AFInAppEventParameterName.CONTENT_ID, <ITEM_SKU>)
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.CONTENT_VIEW, eventValues)
Handling event submission success and failure
You can provide logEvent
with a AppsFlyerRequestListener
object when recording in-app events. The handler allows you to define logic for two scenarios:
- Внутреннее событие приложения зарегистрировано успешно.
- При регистрации внутреннего события произошла ошибка.
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.PURCHASE,
eventValues,
new AppsFlyerRequestListener() {
@Override
public void onSuccess() {
Log.d(LOG_TAG, "Event sent successfully");
}
@Override
public void onError(int i, @NonNull String s) {
Log.d(LOG_TAG, "Event failed to be sent:\n" +
"Error code: " + i + "\n"
+ "Error description: " + s);
}
});
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.PURCHASE,
eventValues,
object : AppsFlyerRequestListener {
override fun onSuccess() {
Log.d(LOG_TAG, "Event sent successfully")
}
override fun onError(errorCode: Int, errorDesc: String) {
Log.d(LOG_TAG, "Event failed to be sent:\n" +
"Error code: " + errorCode + "\n"
+ "Error description: " + errorDesc)
}
})
В случае возникновения ошибки во время записи внутреннего события отображается код ошибки и описание строки, как указано в таблице ниже.
Код ошибки | Описание (NSError) |
---|---|
10 | "Event timeout. Check 'minTimeBetweenSessions' param" («Время события истекло. Проверьте параметр minTimeBetweenSessions») |
11 | "Skipping event because 'isStopTracking' enabled" («Событие пропущено, т. к. включен параметр isStopTracking») |
40 | Ошибка сети: описание ошибки предоставляет Android |
41 | "No dev key" («Нет ключа разработчика») |
50 | "Status code failure" («Ошибка кода статуса») + фактический код ответа от сервера |
Recording offline events
SDK может регистрировать события, которые произошли без подключения к интернету. См. статью Внутренние события приложения в режиме офлайн.
Logging events before calling start
start
If you initialized the SDK but didn't call start
, the SDK will cache in-app events until start
is invoked.
Если в кэше хранится несколько событий, они отправляются на сервер одно за другим (без пакетирования, один сетевой запрос на событие).
Регистрация дохода
You can send revenue with any in-app event. Use the AFInAppEventParameterName.REVENUE
event parameter to include revenue in the in-app event. You can populate it with any numeric value, positive or negative.
В значениях дохода нельзя использовать запятые-разделители, знаки валюты или текст. Событие дохода должно иметь, например, такой формат: 1234.56.
Example: Purchase event with revenue
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.CONTENT_ID, <ITEM_SKU>);
eventValues.put(AFInAppEventParameterName.CONTENT_TYPE, <ITEM_TYPE>);
eventValues.put(AFInAppEventParameterName.REVENUE, 200);
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.PURCHASE, eventValues);
val eventValues = HashMap<String, Any>()
eventValues.put(AFInAppEventParameterName.CONTENT_ID, <ITEM_SKU>)
eventValues.put(AFInAppEventParameterName.CONTENT_TYPE, <ITEM_TYPE>)
eventValues.put(AFInAppEventParameterName.REVENUE, 200)
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.PURCHASE, eventValues)
В этом событии покупки указан доход $200, который будет отображаться на дэшборде.
Примечание
Не добавляйте символы валюты в значение дохода.
Configuring revenue currency
You can set the currency code for an event's revenue by using the af_currency
predefined event parameter:
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.CURRENCY, "USD");
eventValues.put(AFInAppEventParameterName.REVENUE, <TRANSACTION_REVENUE>);
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
AFInAppEventType.PURCHASE, eventValues);
val eventValues = HashMap<String, Any>()
eventValues.put(AFInAppEventParameterName.REVENUE, <TRANSACTION_REVENUE>)
eventValues.put(AFInAppEventParameterName.CURRENCY,"USD")
AppsFlyerLib.getInstance().logEvent(getApplicationContext() , AFInAppEventType.PURCHASE , eventValues)
- Код валюты должен быть кодом из трех символов по стандарту ISO 4217
- Валюта по умолчанию: USD
Сведения о настройках валюты, отображении и конвертации валюты см. в нашем справочнике по валюте доходов.
Logging negative revenue
Возможны такие ситуации, когда нужно зарегистрировать отрицательный доход. Пример: пользователь приложения получает возмещение или отменяет подписку.
Чтобы регистрировать отрицательную выручку:
Map<String, Object> eventValues = new HashMap<String, Object>();
eventValues.put(AFInAppEventParameterName.REVENUE, -1234.56);
eventValues.put(AFInAppEventParameterName.CONTENT_ID,"1234567");
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
"cancel_purchase",
eventValues);
val eventValues = HashMap<String, Any>()
eventValues.put(AFInAppEventParameterName.REVENUE, -1234.56)
eventValues.put(AFInAppEventParameterName.CONTENT_ID,"1234567")
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),
"cancel_purchase",
eventValues)
Примечание
Обратите внимание на приведенный выше код:
- Перед значением дохода стоит знак минус
- Имя события — это настраиваемое имя события "cancel_purchase". Оно позволяет легко найти события отрицательного дохода на дэшборде и в отчетах с сырыми данными.
Проверка покупок
AppsFlyer provides server verification for in-app purchases. The validateAndLogInAppPurchase
method takes care of validating and logging the purchase event.
Примечание
Устаревшую функцию
validateAndLogInAppPurchase
можно заменить более новым и полностью автоматическим коннектором SDK для покупок. Чтобы узнать, как интегрировать коннектор, смотрите статью на Github Коннектор SDK для измерения дохода от покупок на Android
The validateAndLogInAppPurchase
method
validateAndLogInAppPurchase
methodvalidateAndLogInAppPurchase
is exposed via AppsFlyerLib
.
validateAndLognInAppPurchase
принимает следующие аргументы:
validateAndLogInAppPurchase(Context context,
java.lang.String publicKey,
java.lang.String signature,
java.lang.String purchaseData,
java.lang.String price, java.lang.String currency,
java.util.Map<java.lang.String,java.lang.String> additionalParameters)
context
: контекст приложения/активностиpublicKey
: лицензионный ключ, полученный из консоли Google Playsignature
:data.INAPP_DATA_SIGNATURE
fromonActivityResult
purchaseData
:data.INAPP_PURCHASE_DATA
fromonActivityResult
price
: цена покупки должна быть получена изskuDetails.getStringArrayList("DETAILS_LIST")
currency
: валюта покупки должна быть получена изskuDetails.getStringArrayList("DETAILS_LIST")
additionalParameters
— дополнительные параметры события, которые требуется регистрировать
If the validation is successful, an af_purchase
event is logged with the values provided to validateAndLogInAppPurchase
.
Примечание
validateAndLogInAppPurchase
generates anaf_purchase
in-app event upon successful validation. Sending this event yourself will cause duplicate event reporting.
Example: Validate an in-app purchase
// Purchase object is returned by Google API in onPurchasesUpdated() callback
private void handlePurchase(Purchase purchase) {
Log.d(LOG_TAG, "Purchase successful!");
Map<String, String> eventValues = new HashMap<>();
eventValues.put("some_parameter", "some_value");
AppsFlyerLib.getInstance().validateAndLogInAppPurchase(getApplicationContext(),
PUBLIC_KEY,
purchase.getSignature(),
purchase.getOriginalJson(),
"10",
"USD",
eventValues);
}
// Purchase object is returned by Google API in onPurchasesUpdated() callback
private fun handlePurchase(Purchase purchase) {
Log.d(LOG_TAG, "Purchase successful!")
val eventValues = HashMap<String, String>()
eventValues.put("some_parameter", "some_value")
AppsFlyerLib.getInstance().validateAndLogInAppPurchase(this,
PUBLIC_KEY,
purchase.getSignature(),
purchase.getOriginalJson(),
"10",
"USD",
eventValues)
}
Handling purchase validation success/failure
use AppsFlyerInAppPurchaseValidatorListener
to subscribe to purchase validation successes/failures and registerValidatorListener
to register it in your Application class.
registerValidatorListener
is exposed via AppsFlyerLib
. To use AppsFlyerInAppPurchaseValidatorListener
, import it:
import com.appsflyer.AppsFlyerInAppPurchaseValidatorListener;
import com.appsflyer.AppsFlyerInAppPurchaseValidatorListener
AppsFlyerInAppPurchaseValidatorListener
имеет два обратных вызова:
onValidateInApp
: вызывается, когда проверка покупки пройдена успешно.onValidateInAppFailure
: вызывается, когда проверка покупки не пройдена.
registerValidatorListener
принимает 2 аргумента:
context
: контекст приложения.validationListener
: TheAppsFlyerInAppPurchaseValidatorListener
object you wish to register
AppsFlyerLib.getInstance().registerValidatorListener(this,new
AppsFlyerInAppPurchaseValidatorListener() {
public void onValidateInApp() {
Log.d(TAG, "Purchase validated successfully");
}
public void onValidateInAppFailure(String error) {
Log.d(TAG, "onValidateInAppFailure called: " + error);
}
});
AppsFlyerLib.getInstance().registerValidatorListener(this, object : AppsFlyerInAppPurchaseValidatorListener {
override fun onValidateInApp() {
Log.d(LOG_TAG, "Purchase validated successfully")
}
override fun onValidateInAppFailure(error: String) {
Log.d(LOG_TAG, "onValidateInAppFailure called: $error")
}
})
Валидация покупки в приложении автоматически отправляет в AppsFlyer данные события о покупке. Далее приведены примеры данных, которые передаются в параметре event_value:
{
"some_parameter": "some_value", // from additional_event_values
"af_currency": "USD", // from currency
"af_content_id" :"test_id", // from purchase
"af_revenue": "10", // from revenue
"af_quantity": "1", // from purchase
"af_validated": true // flag that AF verified the purchase
}
Константы событий
Predefined event names
Чтобы использовать следующие константы, импортируйте com.appsflyer.AFInAppEventType:
import com.appsflyer.AFInAppEventType;
import com.appsflyer.AFInAppEventType
Predefined event name constants follow a AFInAppEventType.EVENT_NAME
naming convention. For example, AFInAppEventType.ADD_TO_CART
Имя события | Имя константы Android | |
---|---|---|
"af_level_achieved" | AFInAppEventType.LEVEL_ACHIEVED | |
"af_add_payment_info" | AFInAppEventType.ADD_PAYMENT_INFO | |
"af_add_to_cart" | AFInAppEventType.ADD_TO_CART | |
"af_add_to_wishlist" | AFInAppEventType.ADD_TO_WISHLIST | |
"af_complete_registration" | AFInAppEventType.COMPLETE_REGISTRATION | |
"af_tutorial_completion" | AFInAppEventType.TUTORIAL_COMPLETION | |
"af_initiated_checkout" | AFInAppEventType.INITIATED_CHECKOUT | |
"af_purchase" | AFInAppEventType.PURCHASE | |
"af_rate" | AFInAppEventType.RATE | |
"af_search" | AFInAppEventType.SEARCH | |
"af_spent_credits" | AFInAppEventType.SPENT_CREDITS | |
"af_achievement_unlocked" | AFInAppEventType.ACHIEVEMENT_UNLOCKED | |
"af_content_view" | AFInAppEventType.CONTENT_VIEW | |
"af_list_view" | AFInAppEventType.LIST_VIEW | |
"af_travel_booking" | AFInAppEventType.TRAVEL_BOOKING | |
"af_share" | ||
"af_invite" | AFInAppEventType.INVITE | |
"af_login" | AFInAppEventType.LOGIN | |
"af_re_engage" | AFInAppEventType.RE_ENGAGE | |
"af_update" | AFInAppEventType.UPDATE | |
"af_location_coordinates" | AFInAppEventType.LOCATION_COORDINATES | |
"af_customer_segment" | AFInAppEventType.CUSTOMER_SEGMENT | |
"af_subscribe" | AFInAppEventType.SUBSCRIBE | |
"af_start_trial" | AFInAppEventType.START_TRIAL | |
"af_ad_click" | AFInAppEventType.AD_CLICK | |
"af_ad_view" | AFInAppEventType.AD_VIEW | |
"af_opened_from_push_notification" | AFInAppEventType.OPENED_FROM_PUSH_NOTIFICATION |
Predefined event parameters
To use the following constants, import AFInAppEventParameterName
:
import com.appsflyer.AFInAppEventParameterName;
import com.appsflyer.AFInAppEventParameterName
Predefined event parameter constants follow a AFInAppEventParameterName.PARAMETER_NAME
naming convention. For example, AFInAppEventParameterName.CURRENCY
Имя параметра события | Имя константы Android | Тип |
---|---|---|
"af_content" | CONTENT | String[] |
"af_achievement_id" | ACHIEVEMENT_ID | String |
"af_level" | LEVEL | String |
"af_score" | SCORE | String |
"af_success" | SUCCESS | String |
"af_price" | PRICE | float |
"af_content_type" | CONTENT_TYPE | String |
"af_content_id" | CONTENT_ID | String |
"af_content_list" | CONTENT_LIST | String[] |
"af_currency" | CURRENCY | String |
"af_quantity" | QUANTITY | int |
"af_registration_method" | REGISTRATION_METHOD | String |
"af_payment_info_available" | PAYMENT_INFO_AVAILABLE | String |
"af_max_rating_value" | MAX_RATING_VALUE | String |
"af_rating_value" | RATING_VALUE | String |
"af_search_string" | SEARCH_STRING | String |
"af_date_a" | DATE_A | String |
"af_date_b" | DATE_B | String |
"af_destination_a" | DESTINATION_A | String |
"af_destination_b" | DESTINATION_B | String |
"af_description" | DESCRIPTION | String |
"af_class" | CLASS | String |
"af_event_start" | EVENT_START | String |
"af_event_end" | EVENT_END | String |
"af_lat" | LAT | String |
"af_long" | LONG | String |
"af_customer_user_id" | CUSTOMER_USER_ID | String |
"af_validated" | VALIDATED | boolean |
"af_revenue" | REVENUE | int |
"af_projected_revenue" | PROJECTED_REVENUE | int |
"af_receipt_id" | RECEIPT_ID | String |
"af_tutorial_id" | TUTORIAL_ID | String |
"af_virtual_currency_name" | VIRTUAL_CURRENCY_NAME | String |
"af_deep_link" | DEEP_LINK | String |
"af_old_version" | OLD_VERSION | String |
"af_new_version" | NEW_VERSION | String |
"af_review_text" | REVIEW_TEXT | String |
"af_coupon_code" | COUPON_CODE | String |
"af_order_id" | ORDER_ID | String |
"af_param_1" | PARAM_1 | String |
"af_param_2" | PARAM_2 | String |
"af_param_3" | PARAM_3 | String |
"af_param_4" | PARAM_4 | String |
"af_param_5" | PARAM_5 | String |
"af_param_6" | PARAM_6 | String |
"af_param_7" | PARAM_7 | String |
"af_param_8" | PARAM_8 | String |
"af_param_9" | PARAM_9 | String |
"af_param_10" | PARAM_10 | String |
"af_departing_departure_date" | DEPARTING_DEPARTURE_DATE | String |
"af_returning_departure_date" | RETURNING_DEPARTURE_DATE | String |
"af_destination_list" | DESTINATION_LIST | String[] |
"af_city" | CITY | String |
"af_region" | REGION | String |
"af_country" | COUNTRY | String |
"af_departing_arrival_date" | DEPARTING_ARRIVAL_DATE | String |
"af_returning_arrival_date" | RETURNING_ARRIVAL_DATE | String |
"af_suggested_destinations" | SUGGESTED_DESTINATIONS | String[] |
"af_travel_start" | TRAVEL_START | String |
"af_travel_end" | TRAVEL_END | String |
"af_num_adults" | NUM_ADULTS | String |
"af_num_children" | NUM_CHILDREN | String |
"af_num_infants" | NUM_INFANTS | String |
"af_suggested_hotels" | SUGGESTED_HOTELS | String[] |
"af_user_score" | USER_SCORE | String |
"af_hotel_score" | HOTEL_SCORE | String |
"af_purchase_currency" | PURCHASE_CURRENCY | String |
"af_preferred_neighborhoods" | PREFERRED_NEIGHBORHOODS | String[] |
"af_preferred_num_stops" | PREFERRED_NUM_STOPS | String |
"af_adrev_ad_type" | AD_REVENUE_AD_TYPE | String |
"af_adrev_network_name" | AD_REVENUE_NETWORK_NAME | String |
"af_adrev_placement_id" | AD_REVENUE_PLACEMENT_ID | String |
"af_adrev_ad_size" | AD_REVENUE_AD_SIZE | String |
"af_adrev_mediated_network_name" | AD_REVENUE_MEDIATED_NETWORK_NAME | String |
"af_preferred_price_range" | PREFERRED_PRICE_RANGE | String , кортеж int в формате (min,max) |
"af_preferred_star_ratings" | PREFERRED_STAR_RATINGS | String , кортеж int в формате (min,max) |
Изменения сохранены 16 дней назад