인앱 이벤트

iOS SDK에서 인앱이벤트를 다루는 법을 배웁니다.

개요

이 문서는 iOS SDK에서 인앱이벤트를 구현하는 가이드입니다. 개발자를 위한 인앱이벤트에 대한 소개는 인앱이벤트를 참조하세요.

시작하기 전에

SDK를 연동해야 합니다.

인앱이벤트를 기록하기

SDK를 사용하면 앱의 컨텍스트에서 발생하는 사용자 행동을 기록할 수 있습니다. 이것을 일반적으로 인앱이벤트라고 부릅니다.

The logEvent method

The 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 인수 3개를 갖습니다.

- (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 parameters NSDictionary
  • The third argument (completionHandler) is an optional completion handler (useful for Handling event submission success/failure)

📘

참고

eventValues (second argument) must be a valid NSDictionary. For more information, see Foundation JSONSerialization.

Example: Send "add to wishlist" event

예를 들어, 사용자가 아이템을 찜한 목록에 추가한 것을 기록하는 방법은 다음과 같습니다.

[[AppsFlyerLib shared]  logEvent: AFEventAddToWishlist withValues: @{
    AFEventParamPrice: @20,
    AFEventParamContentId: @"123456"
}]
AppsFlyerLib.shared().logEvent(AFEventAddToWishlist,
  withValues: [
     AFEventParamPrice: 20,
     AFEventParamContentId: "123456"
]);

In the above logEvent invocation:

Implementing in-app event definitions

이벤트 구조 정의 이해하기에 제공된 예제 정의에 따라 이벤트를 다음과 같이 구현해야 합니다.

[[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:

  • 인앱이벤트가 성공적으로 기록되었습니다.
  • 인앱 이벤트를 기록하는 동안 오류가 발생했습니다
[[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)
             }
           })
        }

인앱 이벤트를 기록할 때 에러가 발생하면, 아래와 같이 에러 코드와 설명이 제공됩니다.

오류 코드설명(NSError)
10"Event timeout. Check 'minTimeBetweenSessions' param
11"Skipping event because 'isStopTracking' enabled"
40Network error: Error description comes from Android
41"No dev key"
50"Status code failure" + 서버에서 받은 실제 응답 코드

Recording offline events

SDK는 인터넷 연결이 없을 때 발생하는 인앱이벤트를 기록할 수 있습니다. 더 자세한 내용은 오프라인 인앱이벤트 문서에서 찾아볼 수 있습니다.

Logging events before calling start

If you initialized the SDK but didn't call start, the SDK will cache in-app events until start is invoked.

캐시에 다수의 이벤트가 있는 경우에는, 순서대로 하나씩 서버로 전송됩니다(배치되지 않은 것으로, 이벤트당 네트워크 요청 하나).

📘

참고

If the SDK is initialized, logEvent invocations will call SKAdNetwork's updateConversionValue even if start wasn't called or isStopped is set to true (in both SDK and S2S modes).

수익 기록하기

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.

수익 값에는 쉼표 구분 기호, 통화 기호 또는 텍스트가 절대로 포함되면 안됩니다. 예를 들어, 수익 값은 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"
]);

📘

참고

통화 기호를 수익 값에 추가하지 않습니다.

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"
]);
  • 통화 코드는 3문자 ISO 4217 코드여야 합니다.
  • 기본 설정 통화는 USD입니다.

통화 설정, 표시 및 통화 변환에 대한 자세한 내용은 수익 통화에 대한 안내서를 참조하십시오.

Logging negative revenue

마이너스 수익을 기록해야하는 상황이 있을 수 있습니다. 예를 들어 사용자가 환불을 받거나 구독을 취소하는 경우,

마이너스 수익을 기록하는 방법:

[[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"
]);

위의 코드에서 다음 사항을 참고하세요.

  • 수익 값은 마이너스 기호와 함께 표시됩니다.
  • 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

구매 검증

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 인수 4개를 갖습니다.

- (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).

📘

참고

Calling validateAndLogInAppPurchase generates an af_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
    }     
    })

샌드박스 모드에서 구매 검증 테스트하기

샌드박스 환경에서 구매 검증을 테스트할 때, 다음 코드를 추가합니다:

[AppsFlyerLib shared].useReceiptValidationSandbox = YES;
AppsFlyerLib.shared().useReceiptValidationSandbox = true

📘

참고

이 코드는 프로덕션 빌드에서 제거해야 합니다.

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
}

이벤트 상수

Predefined event names

Predefined event name constants follow a AFEventEventName naming convention. For example, AFEventAddToCart.

이벤트 이름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
AFEventSearch
"af_spent_credits"
AFEventSpentCredits
"af_achievement_unlocked"
AFEventAchievementUnlocked
"af_content_view"
AFEventContentView
"af_list_view"
AFEventListView
"af_travel_booking"
AFEventTravelBooking
"af_share"
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.

이벤트 파라미터 이름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
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