Guides

Appsflyer 연동

1. Appsflyer SDK 통합

iOS

Appsflyer SDK 설치

CocoaPods를 사용하여 Appsflyer SDK를 설치합니다.

# Podfile
platform :ios, '10.0'
target 'YourApp' do
  use_frameworks!
  pod 'AppsFlyerFramework'
end

터미널에서 pod install을 실행합니다.

Appsflyer SDK 초기 설정

AppDelegate.swift 파일을 수정하여 SDK를 초기화합니다.

import UIKit
import AppsFlyerLib

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        AppsFlyerLib.shared().appsFlyerDevKey = "YOUR_DEV_KEY"
        AppsFlyerLib.shared().appleAppID = "YOUR_APP_ID"
        AppsFlyerLib.shared().delegate = self
        AppsFlyerLib.shared().isDebug = true
        return true
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        AppsFlyerLib.shared().handleOpen(url, options: options)
        return true
    }

    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
        return true
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        AppsFlyerLib.shared().start()
    }
}

extension AppDelegate: AppsFlyerLibDelegate {
    func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
        // Conversion data received
    }

    func onConversionDataFail(_ error: Error) {
        // Conversion data failed
    }

    func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
        // App open attribution data received
    }

    func onAppOpenAttributionFailure(_ error: Error) {
        // App open attribution data failed
    }
}

Android

Appsflyer SDK 설치

build.gradle 파일을 수정하여 Appsflyer SDK를 추가합니다.

dependencies {
    implementation 'com.appsflyer:af-android-sdk:6.+'
}

Appsflyer SDK 초기 설정

MyApplication.kt 파일을 수정하여 SDK를 초기화합니다.

import android.app.Application
import com.appsflyer.AppsFlyerLib
import com.appsflyer.AppsFlyerConversionListener
import org.json.JSONObject

class MyApplication : Application() {

    companion object {
        private const val AF_DEV_KEY = "YOUR_DEV_KEY"
    }

    override fun onCreate() {
        super.onCreate()

        AppsFlyerLib.getInstance().init(AF_DEV_KEY, object : AppsFlyerConversionListener {
            override fun onConversionDataSuccess(conversionData: Map<String, Any>) {
                // Conversion data received
            }

            override fun onConversionDataFail(errorMessage: String) {
                // Conversion data failed
            }

            override fun onAppOpenAttribution(attributionData: Map<String, String>) {
                // App open attribution data received
            }

            override fun onAttributionFailure(errorMessage: String) {
                // App open attribution data failed
            }
        }, this)
        AppsFlyerLib.getInstance().start(this)
    }
}

2. 웹뷰와 브릿지 설정

iOS

WKWebView 설정

ViewController.swift 파일에서 WKWebView를 설정하고 단일 브릿지를 추가합니다.

import WebKit
import AppsFlyerLib

class ViewController: UIViewController, WKScriptMessageHandler {

    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let contentController = WKUserContentController()
        contentController.add(self, name: "sauceflexSendAppsFlyerEvent")

        let config = WKWebViewConfiguration()
        config.userContentController = contentController

        webView = WKWebView(frame: self.view.bounds, configuration: config)
        self.view.addSubview(webView)

        if let url = URL(string: "https://yourwebsite.com") {
            webView.load(URLRequest(url: url))
        }
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if let messageBody = message.body as? String,
           let data = messageBody.data(using: .utf8),
           let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
           let event = json["event"] as? String,
           let params = json["params"] as? [String: Any] {
            handleEvent(event, params)
        }
    }

    func handleEvent(_ event: String, _ params: [String: Any]) {
        AppsFlyerLib.shared().logEvent(event, withValues: params)
    }
}

Android

WebView 설정

MainActivity.kt 파일에서 WebView를 설정하고 단일 브릿지를 추가합니다.

import android.os.Bundle
import android.webkit.JavascriptInterface
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import com.appsflyer.AppsFlyerLib
import org.json.JSONObject

class MainActivity : AppCompatActivity() {

    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById(R.id.webView)
        val webSettings: WebSettings = webView.settings
        webSettings.javaScriptEnabled = true
        webView.webViewClient = WebViewClient()
        webView.loadUrl("https://yourwebsite.com")

        webView.addJavascriptInterface(WebAppInterface(), "sauceflexSendAppsFlyerEvent")
    }

    private class WebAppInterface {

        @JavascriptInterface
        fun sauceflexSendAppsFlyerEvent(message: String) {
            try {
                val json = JSONObject(message)
                val event = json.getString("event")
                val params = json.getJSONObject("params")
                AppsFlyerLib.getInstance().logEvent(this@MainActivity, event, toMap(params))
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        private fun toMap(jsonObj: JSONObject): Map<String, Any> {
            val map = mutableMapOf<String, Any>()
            val keys: Iterator<String> = jsonObj.keys()
            while (keys.hasNext()) {
                val key = keys.next()
                val value = jsonObj.get(key)
                map[key] = value
            }
            return map
        }
    }
}

3.이벤트 호출 성공 여부 확인

iOS

Appsflyer의 logEvent 메서드에는 완료 핸들러가 있습니다. 이벤트 호출이 성공했는지 여부를 확인하려면 다음과 같이 핸들러를 사용합니다.

func handleEvent(_ event: String, _ params: [String: Any]) {
    AppsFlyerLib.shared().logEvent(event, withValues: params) { (response, error) in
        if let error = error {
            print("Event failed: \(error.localizedDescription)")
        } else {
            print("Event succeeded: \(response ?? [:])")
        }
    }
}

Android

Android에서는 logEvent 메서드의 콜백을 사용하여 이벤트 호출의 성공 여부를 확인할 수 있습니다.

@JavascriptInterface
fun sauceflexSendAppsFlyerEvent(message: String) {
    try {
        val json = JSONObject(message)
        val event = json.getString("event")
        val params = json.getJSONObject("params")
        AppsFlyerLib.getInstance().logEvent(this@MainActivity, event, toMap(params)) { eventName, eventValue, error ->
            if (error != null) {
                println("Event failed: $error")
            } else {
                println("Event succeeded: $eventValue")
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}