Eventos in-app
Aprende a trabajar con eventos in-app en el SDK para iOS.
Resumen General
Este documento es una guía sobre la implementación de eventos in-app en el SDK para iOS. Para ver una introducción a los eventos in-app para desarrolladores, consulta eventos in-app.
Antes de comenzar
Debes integrar el SDK.
Registro de eventos in-app
El SDK te permite registrar las acciones de los usuarios que ocurren en el contexto de tu aplicación. Estos se conocen comúnmente como eventos in-app.
The logEvent
method
logEvent
methodThe logEvent
method lets you log in-app events and send them to AppsFlyer for processing.
AppsFlyerLib
exposes logEvent
, predefined event name constants and predefined event parameter constants.
logEvent
toma 3 argumentos:
- (void)logEventWithEventName:(NSString *)eventName
eventValues:(NSDictionary<NSString * , id> * _Nullable)eventValues
completionHandler:(void (^ _Nullable)(NSDictionary<NSString *, id> * _Nullable dictionary, NSError * _Nullable error))completionHandler;
- The first argument (
eventName
) is the event name - The second argument (
eventValues
) is the event parametersNSDictionary
- The third argument (
completionHandler
) is an optional completion handler (useful for Handling event submission success/failure)
Nota
eventValues
(second argument) must be a validNSDictionary
. For more information, see Foundation JSONSerialization.
Example: Send "add to wishlist" event
Por ejemplo, para registrar que un usuario agregó un artículo a su lista de deseos:
[[AppsFlyerLib shared] logEvent: AFEventAddToWishlist withValues: @{
AFEventParamPrice: @20,
AFEventParamContentId: @"123456"
}]
AppsFlyerLib.shared().logEvent(AFEventAddToWishlist,
withValues: [
AFEventParamPrice: 20,
AFEventParamContentId: "123456"
]);
In the above logEvent
invocation:
- El nombre del evento es
AFEventAddToWishlist
- The event value is a
NSDictionary
containing these event parameters:- AFEventParamPrice: el precio del artículo que el usuario agregó a su lista de deseos
- AFEventParamContentId: el identificador del artículo agregado
Implementing in-app event definitions
Según la definición de ejemplo proporcionada en Comprender las definiciones de la estructura de eventos, el evento debe implementarse de la siguiente manera:
[[AppsFlyerLib shared] logEvent: AFEventContentView withValues: @{
AFEventParamContentId: <ITEM_SKU>,
AFEventParamContentType: <ITEM_TYPE>,
AFEventParamPrice: <ITEM_PRICE>
}]
AppsFlyerLib.shared().logEvent(AFEventAddToCart,
withValues: [
AFEventParamContent: <ITEM_NAME>
AFEventParamContentId: <ITEM_SKU>
AFEventParamPrice: <ITEM_PRICE>
]);
Handling event submission success and failure
You can pass a completionHandler
to logEvent
when recording in-app events. The handler allows you to define logic for two scenarios:
- Un evento in-app registrado correctamente
- Se produjo un error al registrar el evento in-app
[[AppsFlyerLib shared] logEventWithEventName:AFEventPurchase
eventValues: @{
AFEventParamRevenue: @200,
AFEventParamCurrency: @"USD",
AFEventParamQuantity: @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"
}
completionHandler:^(NSDictionary<NSString *,id> * _Nullable dictionary, NSError * _Nullable error){
if(dictionary != nil) {
NSLog(@"In app callback success:");
for(id key in dictionary){
NSLog(@"Callback response: key=%@ value=%@", key, [dictionary objectForKey:key]);
}
}
if(error != nil) {
NSLog(@"In app callback error:", error);
}
}];
AppsFlyerLib.shared().logEvent(name: "In app event name", values: ["id": 12345, "name": "John doe"], completionHandler: { (response: [String : Any]?, error: Error?) in
if let response = response {
print("In app event callback Success: ", response)
}
if let error = error {
print("In app event callback ERROR:", error)
}
})
}
En caso de que se produzca un error durante la grabación del evento in-app, se proporciona un código de error y una descripción de la cadena, como se indica en la tabla que figura a continuación.
Código del error | Descripción (NSError) |
---|---|
10 | "Event timeout. Check 'minTimeBetweenSessions' param" ("Tiempo de espera del evento agotado. Comprueba el parámetro 'minTimeBetweenSessions'") |
11 | "Skipping event because 'isStopTracking' enabled" ("Se omite el evento porque 'isStopTracking' está activado") |
40 | Network error: Error description comes from Android (Error de red: la descripción del error viene de Android) |
41 | "No dev key" ("No hay clave de desarrollador") |
50 | "Status code failure" + actual response code from the server ("Fallo del código de estado" + código de respuesta real del servidor) |
Recording offline events
El SDK puede registrar los eventos que ocurren cuando no hay conexión a Internet disponible. Consulta Eventos in-app sin conexión para obtener más detalles.
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.
Si hay varios eventos en el caché, se envían al servidor uno tras otro (sin lotes, una solicitud de red por evento).
Nota
If the SDK is initialized,
logEvent
invocations will call SKAdNetwork'supdateConversionValue
even ifstart
wasn't called orisStopped
is set totrue
(in both SDK and S2S modes).
Registro de ingresos
af_revenue
is the only event parameter that AppsFlyer counts as real revenue in the dashboard and reports.
You can send revenue with any in-app event. Use the AFEventParameterRevenue
constant to include revenue in the in-app event. You can populate it with any numeric value, positive or negative.
El valor de los ingresos no debe contener comas separadoras, signos de divisas ni texto. Por ejemplo, un evento generador de ingresos debería ser similar a 1234.56.
Example: Purchase event with revenue
[[AppsFlyerLib shared] logEvent: AFEventPurchase
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @200,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent(AFEventPurchase,
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: 200,
AFEventParamCurrency:"USD"
]);
Nota
No agregues símbolos de divisa al valor de los ingresos.
Configuring revenue currency
You can set the currency code for an event's revenue by using the af_currency
predefined event parameter:
[[AppsFlyerLib shared] logEvent: AFEventPurchase
withValues:@{
AFEventParamRevenue: @200,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent(AFEventPurchase,
withValues: [
AFEventParamRevenue: 200,
AFEventParamCurrency:"USD"
]);
- El código de divisa debe ser un código ISO 4217 de 3 caracteres.
- La divisa predeterminada es USD
Para obtener información sobre la configuración, visualización y conversión de divisas, consulta nuestra guía sobre las divisas de los ingresos.
Logging negative revenue
Puede haber situaciones en las que quieras registrar ingresos negativos. Ejemplo: un usuario recibe un reembolso o cancela una suscripción.
Para registrar ingresos negativos:
[[AppsFlyerLib shared] logEvent: @"cancel_purchase"
withValues:@{
AFEventParamContentId:@"1234567",
AFEventParamContentType : @"category_a",
AFEventParamRevenue: @-1.99,
AFEventParamCurrency:@"USD"
}];
AppsFlyerLib.shared().logEvent("cancel_purchase",
withValues: [
AFEventParamContentId:"1234567",
AFEventParamContentType : "category_a",
AFEventParamRevenue: -1.99,
AFEventParamCurrency:"USD"
]);
Observe lo siguiente en el código anterior:
- El valor de ingresos está precedido por un signo de menos
- The event name is a custom event called
cancel_purchase
- that's how the marketer identifies negative revenue events in the dashboard and raw-data reports
Validación de compras
AppsFlyer provides server verification for in-app purchases. The validateAndLogInAppPurchase
method takes care of validating and logging the purchase event.
Purchase validation using validateAndLogInAppPurchase
validateAndLoginInAppPurchase
toma estos argumentos:
- (void) validateAndLogInAppPurchase:(NSString *) productIdentifier,
price:(NSString *) price
currency:(NSString *) currency
transactionId:(NSString *) tranactionId
additionalParameters:(NSDictionary *) params
success:(void (^)(NSDictionary *response)) successBlock
failure:(void (^)(NSError *error, id reponse)) failedBlock;
validateAndLog(inAppPurchase: String?,
price: String?,
currency: String?,
transactionId: String?,
additionalParameters: [AnyHashable : Any]?,
success: ([AnyHashable : Any]) -> Void)?,
failure: ((Error?, Any?) -> Void)?)
Upon successful validation, a NSDictionary
is returned with the receipt validation data (provided by Apple servers).
Nota
Calling
validateAndLogInAppPurchase
generates anaf_purchase
in-app event upon successful validation. Sending this event yourself creates duplicate event reporting.
Example: Validate in-app purchase
[[AppsFlyerLib shared] validateAndLogInAppPurchase:@"ProductIdentifier" price:@"price"
currency:@"USD"
transactionId:@"transactionID"
additionalParameters:@{@"test": @"val" , @"test1" : @"val 1"}
success:^(NSDictionary *result){
NSLog(@"Purchase succeeded And verified! response: %@", result[@"receipt"]);
} failure:^(NSError *error, id response) {
NSLog(@"response = %@", response);
if([response isKindOfClass:[NSDictionary class]]) {
if([response[@"status"] isEqualToString:@"in_app_arr_empty"]){
// retry with 'SKReceiptRefreshRequest' because
// Apple has returned an empty response
// <YOUR CODE HERE>
}
} else {
//handle other errors
return;
}
}];
AppsFlyerLib.shared().validateAndLogInAppPurchase (
inAppPurchase: "productIdentifier",
price: "price",
currency: "currency",
transactionId: "transactionId",
additionalParameters: [:],
success: {
guard let dictionary = $0 as? [String:Any] else { return }
dump(dictionary)
},
failure: { error, result in
guard let emptyInApp = result as? [String:Any],
let status = emptyInApp["status"] as? String,
status == "in_app_arr_empty" else {
// Try to handle other errors
return
}
})
Prueba de validación de compra en el modo de entorno de pruebas
Para probar la validación de la compra mediante un entorno de pruebas, agrega el siguiente código:
[AppsFlyerLib shared].useReceiptValidationSandbox = YES;
AppsFlyerLib.shared().useReceiptValidationSandbox = true
Nota
Este código debe eliminarse de tus compilaciones de producción.
Validating an in-app purchase automatically generates and sends an in-app purchase event to AppsFlyer. Its eventValues
will look something like this:
{
"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
}
Constantes de eventos
Predefined event names
Predefined event name constants follow a AFEventEventName
naming convention. For example, AFEventAddToCart
.
Nombre del evento | Nombre de constante de iOS |
---|---|
"af_level_achieved" | AFEventLevelAchieved |
"af_add_payment_info" | AFEventAddPaymentInfo |
"af_add_to_cart" | AFEventAddToCart |
"af_add_to_wishlist" | AFEventAddToWishlist |
"af_complete_registration" | AFEventCompleteRegistration |
"af_tutorial_completion" | AFEventTutorial_completion |
"af_initiated_checkout" | AFEventInitiatedCheckout |
"af_purchase" | AFEventPurchase |
"af_rate" | AFEventRate |
"af_search" | AFEventSearch |
"af_spent_credits" | AFEventSpentCredits |
"af_achievement_unlocked" | AFEventAchievementUnlocked |
"af_content_view" | AFEventContentView |
"af_list_view" | AFEventListView |
"af_travel_booking" | AFEventTravelBooking |
AFEventShare | |
"af_invite" | AFEventInvite |
"af_login" | AFEventLogin |
"af_re_engage" | AFEventReEngage |
"af_update" | AFEventUpdate |
"af_opened_from_push_notification" | AFEventOpenedFromPushNotification |
"af_location_coordinates" | AFEventLocation |
"af_customer_segment" | AFEventCustomerSegment |
"af_subscribe" | AFEventSubscribe |
"af_start_trial" | AFEventStartTrial |
"af_ad_click" | AFEventAdClick |
"af_ad_view" | AFEventAdView |
Predefined event parameters
Predefined event parameter constants follow a AFEventParamParameterName
naming convention. For example, AFEventParamRevenue
.
Nombre del parámetro del evento | Nombre de constante de iOS |
---|---|
"af_content" | AFEventParamContent |
"af_achievement_id" | AFEventParamAchievementId |
"af_level" | AFEventParamLevel |
"af_score" | AFEventParamScore |
"af_success" | AFEventParamSuccess |
"af_price" | AFEventParamPrice |
"af_content_type" | AFEventParamContentType |
"af_content_id" | AFEventParamContentId |
"af_content_list" | AFEventParamContentList |
"af_currency" | AFEventParamCurrency |
"af_quantity" | AFEventParamQuantity |
"af_registration_method" | AFEventParamRegistrationMethod |
"af_payment_info_available" | AFEventParamPaymentInfoAvailable |
"af_max_rating_value" | AFEventParamMaxRatingValue |
"af_rating_value" | AFEventParamRatingValue |
"af_search_string" | AFEventParamSearchString |
"af_date_a" | AFEventParamDateA |
"af_date_b" | AFEventParamDateB |
"af_destination_a" | AFEventParamDestinationA |
"af_destination_b" | AFEventParamDestinationB |
"af_description" | AFEventParamDescription |
"af_class" | AFEventParamClass |
"af_event_start" | AFEventParamEventStart |
"af_event_end" | AFEventParamEventEnd |
"af_lat" | AFEventParamLat |
"af_long" | AFEventParamLong |
"af_customer_user_id" | AFEventParamCustomerUserId |
"af_validated" | AFEventParamValidated |
"af_revenue" | AFEventParamRevenue |
"af_projected_revenue" | AFEventProjectedParamRevenue |
"af_receipt_id" | AFEventParamReceiptId |
"af_tutorial_id" | AFEventParamTutorialId |
"af_virtual_currency_name" | AFEventParamVirtualCurrencyName |
"af_deep_link" | AFEventParamDeepLink |
"af_old_version" | AFEventParamOldVersion |
"af_new_version" | AFEventParamNewVersion |
"af_review_text" | AFEventParamReviewText |
"af_coupon_code" | AFEventParamCouponCode |
"af_order_id" | AFEventParamOrderId |
"af_param_1" | AFEventParam1 |
"af_param_2" | AFEventParam2 |
"af_param_3" | AFEventParam3 |
"af_param_4" | AFEventParam4 |
"af_param_5" | AFEventParam5 |
"af_param_6" | AFEventParam6 |
"af_param_7" | AFEventParam7 |
"af_param_8" | AFEventParam8 |
"af_param_9" | AFEventParam9 |
"af_param_10" | AFEventParam10 |
"af_departing_departure_date" | AFEventParamDepartingDepartureDate |
"af_returning_departure_date" | AFEventParamReturningDepartureDate |
"af_destination_list" | AFEventParamDestinationList //array of string |
"af_city" | AFEventParamCity |
"af_region" | AFEventParamRegion |
"af_country" | AFEventParamCountry |
"af_departing_arrival_date" | AFEventParamDepartingArrivalDate |
"af_returning_arrival_date" | AFEventParamReturningArrivalDate |
"af_suggested_destinations" | AFEventParamSuggestedDestinations //array of string |
"af_travel_start" | AFEventParamTravelStart |
"af_travel_end" | AFEventParamTravelEnd |
"af_num_adults" | AFEventParamNumAdults |
"af_num_children" | AFEventParamNumChildren |
"af_num_infants" | AFEventParamNumInfants |
"af_suggested_hotels" | AFEventParamSuggestedHotels //array of string |
"af_user_score" | AFEventParamUserScore |
"af_hotel_score" | AFEventParamHotelScore |
"af_purchase_currency" | AFEventParamPurchaseCurrency |
"af_preferred_star_ratings" | AFEventParamPreferredStarRatings //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values" |
"af_preferred_price_range" | AFEventParamPreferredPriceRange //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values" |
"af_preferred_neighborhoods" | AFEventParamPreferredNeighborhoods //array of string |
"af_preferred_num_stops" | AFEventParamPreferredNumStops |
"af_adrev_ad_type" | AFEventParamAdRevenueAdType |
"af_adrev_network_name" | AFEventParamAdRevenueNetworkName |
"af_adrev_placement_id" | AFEventParamAdRevenuePlacementId |
"af_adrev_ad_size" | AFEventParamAdRevenueAdSize |
"af_adrev_mediated_network_name" | AFEventParamAdRevenueMediatedNetworkName |
Actualizado hace aproximadamente 1 año