In-App Event
Pelajari cara bekerja dengan in-app event di iOS SDK.
Overview
Dokumen ini adalah panduan tentang penerapan in-app event di iOS SDK. Sebagai pengantar in-app event bagi programmer, lihat In-app event.
Sebelum Anda memulai:
Anda harus mengintegrasikan SDK .
Mencatat in-app event
SDK memungkinkan Anda mencatat tindakan pengguna yang terjadi dalam konteks aplikasi Anda. Ini biasanya disebut sebagai in-app event .
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
membutuhkan 3 argumen:
- (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)
Catatan
eventValues
(second argument) must be a validNSDictionary
. For more information, see Foundation JSONSerialization.
Example: Send "add to wishlist" event
Misalnya, untuk mencatat bahwa pengguna menambahkan item ke wishlist mereka:
[[AppsFlyerLib shared] logEvent: AFEventAddToWishlist withValues: @{
AFEventParamPrice: @20,
AFEventParamContentId: @"123456"
}]
AppsFlyerLib.shared().logEvent(AFEventAddToWishlist,
withValues: [
AFEventParamPrice: 20,
AFEventParamContentId: "123456"
]);
In the above logEvent
invocation:
- Nama eventnya adalah
AFEventAddToWishlist
- The event value is a
NSDictionary
containing these event parameters:- AFEventParamPrice: Harga item yang ditambahkan pengguna ke wishlist mereka
- AFEventParamContentId: Pengenal item yang ditambahkan
Implementing in-app event definitions
Berdasarkan contoh definisi yang diberikan dalam Memahami definisi struktur event , event tersebut harus diterapkan sebagai berikut:
[[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:
- In-app event berhasil dicatat.
- Terjadi kesalahan saat mencatat in-app event.
[[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: AFEventAddToWishlist,
values: [
AFEventParamPrice: 20,
AFEventParamContentId: "123456"
],
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)
}
});
Jika terjadi kesalahan saat merekam in-app event, muncul kode kesalahan dan deskripsi string, seperti yang ditunjukkan pada tabel berikut.
Kode Error | Deskripsi (NSError) |
---|---|
10 | "Event timeout (batas waktu event). Periksa parameter 'minTimeBetweenSessions'" |
11 | "Skipping event because 'isStopTracking' enabled" (Lewati event karena 'isStopTracking' diaktifkan) |
40 | Network error: Error description comes from iOS |
41 | "No dev key" (tidak ada kode pengembang) |
50 | "Status code failure" (kode status gagal)+ kode respons aktual dari server |
Recording offline events
SDK dapat merekam event yang terjadi saat tidak ada koneksi internet yang tersedia. Lihat In-app event offline untuk rinciannya.
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.
Jika ada beberapa event dalam cache, event ini dikirim ke server satu per satu (tidak di-batch, satu permintaan jaringan per event).
Catatan
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).
Mencatat pendapatan
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.
Nilai pendapatan tidak boleh mengandung pemisah koma, simbol mata uang, atau teks. Misalnya, event pendapatan harus serupa dengan 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"
]);
Catatan
Jangan menambahkan simbol mata uang ke nilai pendapatan.
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"
]);
- Kode mata uang harus berupa kode ISO 4217 3 karakter
- Mata uang defaultnya adalah USD
Untuk mempelajari tentang pengaturan mata uang, tampilan, dan konversi mata uang, lihat panduan tentang mata uang pendapatan.
Logging negative revenue
Mungkin ada situasi di mana Anda ingin mencatat pendapatan negatif. Misalnya, pengguna menerima pengembalian dana atau membatalkan berlangganan.
Untuk mencatat pendapatan negatif:
[[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"
]);
Pada kode di atas, perhatikan beberapa hal berikut:
- Nilai pendapatan didahului dengan tanda minus
- 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
Memvalidasi pembelian
AppsFlyer provides server verification for in-app purchases. The validateAndLogInAppPurchase
method takes care of validating and logging the purchase event.
Catatan
The legacy function
validateAndLogInAppPurchase
can be replaced by the newer and fully automatic purchase SDK connector. To learn how to integrate the connector, see in Github iOS purchase SDK connector
Purchase validation using validateAndLogInAppPurchase
validateAndLoginInAppPurchase
mengambil argumen ini:
- (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).
Catatan
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
}
})
Menguji validasi pembelian dalam mode Sandbox
Untuk menguji validasi pembelian menggunakan lingkungan sandbox, tambahkan kode berikut:
[AppsFlyerLib shared].useReceiptValidationSandbox = YES;
AppsFlyerLib.shared().useReceiptValidationSandbox = true
Catatan
Kode ini harus dihapus dari build produksi Anda.
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
}
Konstanta event
Predefined event names
Predefined event name constants follow a AFEventEventName
naming convention. For example, AFEventAddToCart
.
eventName | Nama konstanta 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
.
Nama parameter event | Nama konstanta iOS | Jenis |
---|---|---|
"af_content" | AFEventParamContent | String |
"af_achievement_id" | AFEventParamAchievementId | String |
"af_level" | AFEventParamLevel | String |
"af_score" | AFEventParamScore | String |
"af_success" | AFEventParamSuccess | String |
"af_price" | AFEventParamPrice | float |
"af_content_type" | AFEventParamContentType | String |
"af_content_id" | AFEventParamContentId | String |
"af_content_list" | AFEventParamContentList | String[] |
"af_currency" | AFEventParamCurrency | String |
"af_quantity" | AFEventParamQuantity | int |
"af_registration_method" | AFEventParamRegistrationMethod | String |
"af_payment_info_available" | AFEventParamPaymentInfoAvailable | String |
"af_max_rating_value" | AFEventParamMaxRatingValue | String |
"af_rating_value" | AFEventParamRatingValue | String |
"af_search_string" | AFEventParamSearchString | String |
"af_date_a" | AFEventParamDateA | String |
"af_date_b" | AFEventParamDateB | String |
"af_destination_a" | AFEventParamDestinationA | String |
"af_destination_b" | AFEventParamDestinationB | String |
"af_description" | AFEventParamDescription | String |
"af_class" | AFEventParamClass | String |
"af_event_start" | AFEventParamEventStart | String |
"af_event_end" | AFEventParamEventEnd | String |
"af_lat" | AFEventParamLat | String |
"af_long" | AFEventParamLong | String |
"af_customer_user_id" | AFEventParamCustomerUserId | String |
"af_validated" | AFEventParamValidated | boolean |
"af_revenue" | AFEventParamRevenue | float |
"af_projected_revenue" | AFEventProjectedParamRevenue | float |
"af_receipt_id" | AFEventParamReceiptId | String |
"af_tutorial_id" | AFEventParamTutorialId | String |
"af_virtual_currency_name" | AFEventParamVirtualCurrencyName | |
"af_deep_link" | AFEventParamDeepLink | String |
"af_old_version" | AFEventParamOldVersion | String |
"af_new_version" | AFEventParamNewVersion | String |
"af_review_text" | AFEventParamReviewText | String |
"af_coupon_code" | AFEventParamCouponCode | String |
"af_order_id" | AFEventParamOrderId | String |
"af_param_1" | AFEventParam1 | String |
"af_param_2" | AFEventParam2 | String |
"af_param_3" | AFEventParam3 | String |
"af_param_4" | AFEventParam4 | String |
"af_param_5" | AFEventParam5 | String |
"af_param_6" | AFEventParam6 | String |
"af_param_7" | AFEventParam7 | String |
"af_param_8" | AFEventParam8 | String |
"af_param_9" | AFEventParam9 | String |
"af_param_10" | AFEventParam10 | String |
"af_departing_departure_date" | AFEventParamDepartingDepartureDate | String |
"af_returning_departure_date" | AFEventParamReturningDepartureDate | String |
"af_destination_list" | AFEventParamDestinationList | String[] |
"af_city" | AFEventParamCity | String |
"af_region" | AFEventParamRegion | String |
"af_country" | AFEventParamCountry | String |
"af_departing_arrival_date" | AFEventParamDepartingArrivalDate | String |
"af_returning_arrival_date" | AFEventParamReturningArrivalDate | String |
"af_suggested_destinations" | AFEventParamSuggestedDestinations | String[] |
"af_travel_start" | AFEventParamTravelStart | String |
"af_travel_end" | AFEventParamTravelEnd | String |
"af_num_adults" | AFEventParamNumAdults | String |
"af_num_children" | AFEventParamNumChildren | String |
"af_num_infants" | AFEventParamNumInfants | String |
"af_suggested_hotels" | AFEventParamSuggestedHotels | String[] |
"af_user_score" | AFEventParamUserScore | String |
"af_hotel_score" | AFEventParamHotelScore | String |
"af_purchase_currency" | AFEventParamPurchaseCurrency | String |
"af_preferred_neighborhoods" | AFEventParamPreferredNeighborhoods //array of string | String[] |
"af_preferred_num_stops" | AFEventParamPreferredNumStops | String |
"af_adrev_ad_type" | AFEventParamAdRevenueAdType | String |
"af_adrev_network_name" | AFEventParamAdRevenueNetworkName | String |
"af_adrev_placement_id" | AFEventParamAdRevenuePlacementId | String |
"af_adrev_ad_size" | AFEventParamAdRevenueAdSize | String |
"af_adrev_mediated_network_name" | AFEventParamAdRevenueMediatedNetworkName | String |
"af_preferred_price_range" | AFEventParamPreferredPriceRange | int[] - basically a tuple(min,max) but we'll use array of int and use two values |
"af_preferred_star_ratings" | AFEventParamPreferredStarRatings | int[] - basically a tuple(min,max) but we'll use array of int and use two values |
Diperbarui 10 hari yang lalu