본문 바로가기

한국어/구글 애널리틱스 4 (GA4)

[Firebase Analytics] WebView에서 items 배열이 로깅되지 않는 현상

🚨 문제: Firebase Analytics의 WebView에서 items 배열이 로깅되지 않는 현상

Firebase Analytics는 앱에서 발생하는 사용자 행동 데이터를 분석할 수 있는 강력한 도구입니다. 특히 E-commerce 데이터를 분석하려면 items 배열과 같은 세부 정보가 정확히 로깅되어야 합니다.

하지만, 특정 상황에서는 상품 데이터(items 배열)가 제대로 전송되지 않아 데이터 손실이 발생할 수 있습니다. 이 문제는 특히 앱 내에서 웹 콘텐츠를 표시하는 화면(WebView)에서 자주 나타납니다.

 


 

🛠 문제를 이해하기 쉽게 설명

 

WebView란?

  • WebView는 앱 안에서 웹페이지를 띄워주는 "미니 브라우저"라고 생각하면 됩니다.
  • 쇼핑몰 앱에서 상품 목록을 보여주는 페이지가 웹으로 구성된 경우, WebView를 사용해 해당 웹 콘텐츠를 표시합니다.
  • 사용자는 앱을 사용하는 것처럼 보이지만, 실제로는 앱과 웹이 데이터를 주고받는 환경입니다.

왼쪽은 웹에서 구현된 화면, 오른쪽은 해당 화면이 앱의 WebView를 통해 표시됨

 

문제가 발생하는 이유

  • 일반적으로 웹 환경에서는 상품 데이터를 다음과 같은 방식으로 전송합니다:
dataLayer.push({ ecommerce: null });  // Clear the previous ecommerce object.
dataLayer.push({
  event: "view_item",
  ecommerce: {
    currency: "USD",
    value: 7.77,
    items: [
      {
        item_id: "SKU_12345",
        item_name: "Stan and Friends Tee",
        affiliation: "Google Merchandise Store",
        coupon: "SUMMER_FUN",
        discount: 2.22,
        index: 0,
        item_brand: "Google",
        item_category: "Apparel",
        item_category2: "Adult",
        item_category3: "Shirts",
        item_category4: "Crew",
        item_category5: "Short sleeve",
        item_list_id: "related_products",
        item_list_name: "Related Products",
        item_variant: "green",
        location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
        price: 9.99,
        quantity: 1
      }
    ]
  }
});

 

 

위 코드는 웹에서 정상적으로 작동하지만, WebView 환경에서는 앱과 웹 사이에 데이터 전달 방식이 제한적이기 때문에 items 배열 데이터가 Firebase Analytics로 누락됩니다.

 


 

🛠 해결 방법

이 문제를 해결하려면 앱 개발자가 items 배열 데이터를 JSON 문자열로 변환하여 Firebase Analytics에 전달해야 합니다. 아래는 Android와 iOS에서 이를 구현하는 방법입니다.

 

Android: JSON 문자열로 변환 후 Firebase로 전송

Android에서는 JSONArray와 JSONObject를 활용하여 items 배열을 JSON 문자열로 변환합니다.

import android.os.Bundle
import android.util.Log
import com.google.firebase.analytics.FirebaseAnalytics
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject

private fun createEcommerceBundle(jsonParams: String): Bundle {
    val ecommerceParams = Bundle() // E-commerce 데이터를 담을 메인 Bundle
    try {
        val jsonObject = JSONObject(jsonParams) // JSON 문자열을 JSONObject로 변환

        // JSON 객체에서 "items" 배열 추출
        val itemsArray = jsonObject.optJSONArray("items")
        if (itemsArray != null) {
            // 각 item 데이터를 저장할 Bundle 배열 생성
            val itemBundles = Array(itemsArray.length()) { Bundle() }
            for (i in 0 until itemsArray.length()) {
                val itemJson = itemsArray.getJSONObject(i) // 개별 item을 JSONObject로 가져옴
                itemBundles[i] = createEcommerceItemBundle(itemJson) // item 데이터를 Bundle로 변환

                // 디버깅용 로그 출력
                Log.d("AnalyticsWebInterface", "Ecommerce Item $i: ${itemJson.toString()}")
            }

            // item Bundles 배열을 메인 e-commerce Bundle에 추가
            ecommerceParams.putParcelableArray(FirebaseAnalytics.Param.ITEMS, itemBundles)
        } else {
            // "items" 배열이 없거나 null인 경우 로그 출력
            Log.d("AnalyticsWebInterface", "Ecommerce Event - Items array is null!")
        }
    } catch (e: JSONException) {
        // JSON 파싱 중 에러 발생 시 로그에 에러 메시지 출력
        Log.e("AnalyticsWebInterface", "E-commerce 이벤트 JSON 파싱 중 오류 발생", e)
    }
    return ecommerceParams // 완성된 Bundle 반환
}

 

✅ iOS: JSONSerialization 를 활용하여 items 배열을 JSON 문자열로 변환합니다.

import FirebaseAnalytics

extension WebView.Coordinator {
    
    /// JSON 문자열에서 E-commerce 이벤트의 파라미터를 추출하고 딕셔너리로 변환
    private func createEcommerceBundle(jsonString: String) -> [String: Any]? {
        // JSON 키를 보정하여 유효한 JSON 문자열로 변환
        let cleanedJsonString = addQuotesToJsonKeys(jsonString)

        // JSON 문자열을 Data로 변환
        guard let data = cleanedJsonString.data(using: .utf8) else {
            print("Ecommerce Event - Failed to convert JSON string to Data.")
            return nil
        }

        // JSON 데이터를 딕셔너리로 파싱
        do {
            if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
                print("Ecommerce Event - Parsed JSON into dictionary: \(jsonObject)")

                // items 배열 추출
                if let itemsArray = jsonObject["items"] as? [[String: Any]] {
                    print("Ecommerce Event - Items array found: \(itemsArray)")

                    // 각 item을 개별적으로 처리 가능
                    for (index, item) in itemsArray.enumerated() {
                        print("Ecommerce Event - Item \(index): \(item)")
                    }
                } else {
                    print("Ecommerce Event - Items array is null or invalid.")
                }

                return jsonObject
            }
        } catch {
            print("Ecommerce Event - Failed to parse JSON: \(error)")
        }

        return nil
    }
}

 


🎯 문제 해결

위 코드를 적용한 결과, WebView에서도 items 배열 데이터가 Firebase Analytics에 성공적으로 전송됩니다.
Firebase DebugView나 BigQuery에서 items 데이터를 확인하여 심층적인 분석이 가능해졌습니다.

 


🧠 중요 개념 설명

 

1. JSON 직렬화(Serialization): GA4에서는 items와 같은 복잡한 배열 데이터를 JSON 문자열로 변환하여 전달해야 로깅됩니다.

2. Firebase Analytics 제한 사항: 이벤트 파라미터 글자 수 제한(파라미터명 길이: 최대 40자, 파라미터값 길이: 최대 100자)과 데이터 타입(JSON 문자열) 규정을 준수해야 합니다.

 


🌟 비즈니스적 시사점

items 배열이 누락될 경우, 제품 클릭, 장바구니 담기, 구매와 같은 사용자 행동 데이터를 부분적으로 분석할 수는 있지만, 어떤 상품에 대한 행동인지에 대한 세부적인 정보가 손실됩니다. 이로 인해 다음과 같은 문제들이 발생할 수 있습니다.

1. 상품별 성과 분석 불가

- 특정 상품의 클릭률, 장바구니 추가율, 구매 전환율 등의 데이터를 파악할 수 없습니다.

- 어떤 상품이 사용자에게 인기 있는지, 또는 프로모션 효과를 분석하기 어렵습니다.

2. 사용자 여정 파악의 정확도 저하

- 사용자가 어떤 상품을 클릭했는지에 대한 정보가 없으므로 사용자 여정을 상품별로 세분화하여 분석할 수 없습니다.

- 전반적인 여정을 추적할 수는 있지만, 구체적인 상품별 데이터를 기반으로 한 전략적 의사결정이 어렵습니다.

3. 마케팅 캠페인 평가의 정확성 저하

- 특정 상품이 포함된 프로모션 캠페인 또는 광고의 효과를 측정할 수 없습니다.

- "어떤 상품이 캠페인 성과에 가장 크게 기여했는가?"라는 질문에 대한 답을 얻기 어렵습니다.

4. ROI 계산의 어려움

- 상품별 판매 데이터를 기반으로 캠페인 ROI를 정확히 계산하기 힘듭니다.

- 예산 배분과 캠페인 최적화에 대한 의사결정이 데이터 부족으로 인해 부정확할 가능성이 높아집니다.

 


 

💡 전문가의 한마디

Firebase Analytics에서 items 배열은 단순히 데이터의 일부가 아니라, 상품별 행동 데이터를 기반으로 비즈니스 가치를 창출하는 핵심 요소입니다. 누락된 경우 전반적인 사용자 여정을 파악할 수는 있지만, 상품별 상세 분석 및 전략적 의사결정에는 한계가 발생합니다.