Sekilas: Rekam in-app event Aplikasi dari pengguna yang menginstal aplikasi Anda, tetapi melakukan event di situs web seluler Anda, dan bukan aplikasinya.
Pengantar
In-app event yang terjadi dalam aplikasi dilaporkan menggunakan SDK. Bagaimana dengan event yang terjadi di luar aplikasi?
Ada beberapa skenario di mana event terjadi di luar konteks aplikasi:
- Event yang terjadi di situs web Anda: Implementasikan Atribusi Berbasis Orang (PBA) untuk mendapatkan tinjauan terpadu tentang perjalanan pelanggan di seluruh channel, platform termasuk situs web, dan perangkat. Ini menyediakan Web-to-App, Analisis jalur konversi, dan data lengkap.
- Server backend: Event terjadi secara independen dari tindakan pengguna di situs web atau aplikasi. Misalnya, perpanjangan langganan otomatis
- Hybrid: Event berlangsung di situs web seluler Anda pada perangkat yang memiliki aplikasi seperti yang dijelaskan dalam artikel. In-app event direkam dengan memanggil AppsFlyer SDK API menggunakan Javascript.
Panduan ini berkaitan dengan skenario hybrid. Pelajari cara menjembatani kesenjangan antara tampilan HTML dan tampilan asli, memungkinkan Anda merekam event dalam tampilan HTML dan mengirimkannya ke aplikasi.
Contoh
Anda memiliki aplikasi hybrid yang menawarkan berlangganan. Anda menerapkan formulir berlangganan dalam web view (tampilan web) yang sebenarnya dimuat dari situs web Anda.
Anda dapat merekam in-app event langganan di tampilan web dan mengirim data yang terkait dengannya, seperti jenis atau harga langganan, ke kode native.
Kode native mengumpulkan data dan menggunakan SDK AppsFlyer untuk mengirim in-app event langganan.
Mencatat in-app event di aplikasi hybrid
Dalam panduan ini kami menyediakan dua metode untuk mencatat in-app event di aplikasi hybrid:
- [Direkomendasikan] Antarmuka JavaScript : Menggunakan antarmuka JavaScript native untuk membangun komunikasi antara HTML atau Tampilan Web dan kode native.Dengan cara ini Anda dapat mengirim data terkait peristiwa dalam aplikasi dari tampilan web ke kode native. Setelah kode native mendapatkan data, kode ini mengirimkannya ke AppsFlyer menggunakan SDK.
- Pemuatan URL: Dalam metode ini, kode native mendengarkan event pemuatan URL.Anda dapat menyetel kode asli untuk mendengarkan event pemuatan URL tertentu dan mengekstrak data dari parameter URL. Data tersebut kemudian diteruskan ke SDK.
Antarmuka Javascript
Baik Android dan iOS memiliki antarmuka Javascript asli yang memungkinkan tampilan web memanggil kode asli.
- Android: JavascriptInterface
- iOS: JavaScriptCore
Keuntungan menggunakan antarmuka JavaScript native dibandingkan pemuatan URL:
- Antarmuka ini tidak memerlukan penerapan logika yang memproses pemuatan URL.
- Antarmuka native lebih disukai daripada implementasi lain.
- Tidak perlu mengurai parameter dari URL.
- Ada lebih sedikit kode sehingga lebih sedikit perawatan yang diperlukan.
Implementasinya terdiri dari langkah-langkah berikut:
- Kode HTML untuk tampilan web atau halaman web
- Implementasi kode asli untuk tampilan web
Android
Kode HTML untuk Android
Tambahkan kode HTML berikut ke tampilan web atau halaman web:
<h1>Recording Event From Web View</h1>
<div id="main">
<button id="recordEvent" onclick="recordEvent()"> Record Event </button>
</div>
<script type="text/javascript">
function recordEvent(){
var eventName = "af_purchase"
var eventParams = "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}";
app.recordEvent(eventName, eventParams)
}
</script>
Saat meneruskan nilai event, perhatikan hal berikut:
- Pastikan untuk meneruskan nilai event sebagai JSON stringify.
"{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
- Untuk menghindari terjadinya masalah, AppsFlyer menyarankan penggunaan karakter alfanumerik huruf kecil (a-z dan 0-9) untuk nama event in-app.
Kelas Aktivitas Web
Buat kelas aktivitas web dengan kode berikut:
public class WebActivity extends AppCompatActivity {
WebView web;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
web = (WebView) findViewById(R.id.webView);
web.getSettings().setJavaScriptEnabled(true);
web.addJavascriptInterface(new MainJsInterface(getApplicationContext()), "app");
web.loadUrl("https://yourwebsite.com");
}
}
Kode di atas membuat obyek bernama aplikasi yang bertindak sebagai jembatan antara tampilan web dan kode asli.
Kelas antarmuka JavaScript
Buat kelas MainJsInterface untuk mengimplementasikan recordEvent()
sebagai JavascriptInterface
public class MainJsInterface {
Context mContext;
MainJsInterface(Context c) {
mContext = c;
}
@JavascriptInterface
public void recordEvent(String name, String json){
Map<String, Object> params = null;
if(json!=null) {
try {
JSONObject jsonObject = new JSONObject(json);
params = new HashMap<>();
Iterator keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next();
Object value = jsonObject.opt(key);
params.put(key, value);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
AppsFlyerLib.getInstance().logEvent(this.mContext, name, params);
}
}
Kode di atas mendeklarasikan metode recordEvent
yang dapat dipanggil dalam tampilan web menggunakan Javascript.
Dalam kode HTML, Anda dapat melihat bahwa metode tersebut dipanggil menggunakan app.recordEvent(eventName, eventParams)
. Ingatlah bahwa kami mengatur aplikasi untuk bertindak sebagai jembatan antara tampilan web dan kode native. Inilah sebabnya mengapa aplikasi dapat memanggil metode recordEvent
yang kita definisikan di kelas MainJsInterface.
iOS
Kode HTML untuk iOS
Tambahkan kode HTML berikut ke tampilan web atau halaman web:
<body>
<h1>Recroding Event From Web View</h1>
<div id="main">
<button id="recordEvent" onclick="recordEvent()"> Record Event </button>
</div>
<script type="text/javascript">
function recordEvent(){
var eventName = "af_purchase"
var eventParams = "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}";
webkit.messageHandlers.event.postMessage(eventName + "+" + eventParams);
}
</script>
</body>
Kode di atas menetapkan fungsi yang akan dipicu saat tombol diklik. Fungsi ini mengatur variabel eventName
dan eventParams
dan meneruskannya ke kode asli menggunakan webkit.messageHandlers
.
Saat meneruskan nilai event, perhatikan hal berikut:
- Pastikan untuk meneruskan nilai event sebagai JSON stringify.
"{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
- Untuk menghindari terjadinya masalah, AppsFlyer menyarankan penggunaan karakter alfanumerik huruf kecil (a-z dan 0-9) untuk nama event in-app.
Catatan
Kode HTML untuk Objective C dan Swift.
Tujuan c
Pengontrol tampilan web
Di pengontrol web view (tampilan web) Anda, tambahkan kode berikut di pengontrol tampilan.
-(void)loadView{
[super loadView];
WKWebViewConfiguration *configuration =
[[WKWebViewConfiguration alloc] init];
[configuration.userContentController
addScriptMessageHandler:self name:@"event"];
_webView = [[WKWebView alloc] initWithFrame:self.view.frame
configuration:configuration];
[self.view addSubview:_webView];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString* page = @"https://yourwebsite.com";
NSURL *url = [NSURL URLWithString:page];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
}
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
NSString* messageBody = message.body;
NSString* eventName = [messageBody componentsSeparatedByString:@"+"][0];
NSString* eventValue = [messageBody componentsSeparatedByString:@"+"][1];
[self recordEvent:eventName eventValue:eventValue];
}
- (void)recordEvent:(NSString*)eventName eventValue:(NSString*)eventValue{
NSData *eventValuedata = [eventValue dataUsingEncoding:(NSUTF8StringEncoding)];
NSDictionary *eventValueDict = [NSJSONSerialization JSONObjectWithData:eventValuedata options:NSJSONReadingMutableContainers error:nil];
[[AppsFlyerLib shared] logEvent:eventName withValues:eventValueDict];
}
Kode di atas menerima pesan dari tampilan web. Pesan tersebut berisi nama event dan nilai event. Saat kode mendeteksi pesan masuk, kode akan meneruskannya ke metode recordEvent
yang mengurai nilai dan memanggil metode logEvent
SDK native.
Pengontrol Swift WebView
Di pengontrol web view (tampilan web) Anda, tambahkan kode berikut dalam metode viewDidLoad
import WebKit
import UIKit
import AppsFlyerLib
import JavaScriptCore
class JSViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let messageBody = message.body as? String
let eventName = messageBody?.components(separatedBy: "+")[0]
let eventValue = messageBody?.components(separatedBy: "+")[1]
recordEvent(eventName: eventName!, eventValue: eventValue!)
}
var webView: WKWebView!
override func loadView(){
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://yourwebsite.com")!
webView.load(URLRequest(url: url))
webView.configuration.userContentController.add(self, name:"event")
}
func recordEvent(eventName: String, eventValue: String) {
var eventValueDict = [String: String]()
let eventValuesData = eventValue.data(using: String.Encoding.utf8)
do {
eventValueDict = try (JSONSerialization.jsonObject(with: eventValuesData!, options:[]) as? [String: String])!
} catch let error as NSError{
print(error)
}
AppsFlyerLib.shared().logEvent(eventName as String?, withValues: eventValueDict)
}
}
Kode di atas menerima pesan dari tampilan web. Pesan tersebut berisi nama event dan nilai event. Saat kode mendeteksi pesan masuk, kode akan meneruskannya ke metode recordEvent
yang mengurai nilai dan memanggil metode logEvent
SDK.
Pemuatan URL
Baik Android dan iOS menerapkan metode asli yang merespons event pemuatan url. Metode ini memungkinkan Anda melakukan hal berikut:
- Dengarkan event pemuatan URL tertentu
- Ekstrak parameter yang ditambahkan ke URL
- Gunakan parameter ini dalam kode asli
Implementasi di bawah ini terdiri dari dua langkah:
- Kode HTML untuk tampilan web atau halaman web
- Penerapan kode asli untuk pemuatan URL
Implementasi Tampilan Web
Kode HTML (untuk Android WebView dan iOS UIWebView)
<html>
<head>
</head>
<body>
<h1>Recording From Web View</h1>
<div id="main">
<input id="button" type="button" value="Record Event" />
</div>
<script type="text/javascript">
function recordEvent(eventName,eventValue){
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "af-event://inappevent?eventName="+eventName+"&eventValue="+eventValue);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
var button = document.getElementById("button");
button.onclick = function(event) {
var eventName = "af_purchase";
var eventValue = "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}";
recordEvent(eventName, eventValue);
}
</script>
</body>
</html>
Kode di atas dapat menjadi bagian dari halaman web yang sebenarnya atau dimuat secara native ke tampilan web.
Kode di atas menetapkan fungsi yang akan dipicu saat tombol diklik. Fungsi itu sendiri membuat elemen iframe yang memuat URL khusus. Pemuatan URL inilah yang memicu metode native Android atau iOS yang kemudian memanggil metode logEvent SDK logEvent
.
Semua parameter yang diperlukan (nama event dan nilai event) ditambahkan ke URL. Contoh kode Android dan iOS di bawah ini menunjukkan cara mengekstrak parameter ini dan meneruskannya ke metode SDK logEvent
.
Saat meneruskan nilai event, perhatikan hal berikut:
- Pastikan untuk meneruskan nilai event sebagai JSON stringify.
"{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
- Untuk menghindari terjadinya masalah, AppsFlyer menyarankan penggunaan karakter alfanumerik huruf kecil (a-z dan 0-9) untuk nama event in-app.
Implementasi asli
Implementasi Android
Android WebView menggunakan WebViewClient yang menerima notifikasi dari tampilan web. Di shouldOverrideUrlLoading
, Anda dapat menangani peristiwa pemuatan URL yang berasal dari tampilan web:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("af-event://")) {
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
String eventName = null;
HashMap<String, Object> eventValue = new HashMap<>();
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = pair[0];
if (pair.length > 1) {
if ("eventName".equals(key)){
eventName = pair[1];
} else if ("eventValue".equals(key)){
JSONObject event;
JSONArray keys;
try {
event = new JSONObject(pair[1]);
keys = event.names();
for (int i = 0; i < keys.length(); i++){
eventValue.put(keys.getString(i), event.getString(keys.getString(i)));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
AppsFlyerLib.getInstance().logEvent(getApplicationContext(),eventName,eventValue);
}
return true;
}
view.loadUrl(url);
return true;
}
Implementasi iOS
Di pengontrol tampilan web Anda, tambahkan kode berikut dalam metode shouldStartLoadWithRequest
- (void)viewDidLoad {
[super viewDidLoad];
NSString *page = @"https://yourwebsite.com";
NSURL *url = [NSURL URLWithString:page];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
_webView = [[WKWebView alloc] initWithFrame:self.view.frame];
_webView.navigationDelegate = self;
[_webView loadRequest:request];
_webView.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:_webView];
}
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction* )navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler(WKNavigationActionPolicyAllow);
NSString *url = navigationAction.request.URL.absoluteString;
if([url containsString:(@"af-event")]){
[self recordEvent:(url)];
}
}
- (void)recordEvent:(NSString*)url{
NSString *eventNameAndEventValueString = [url componentsSeparatedByString: @"?"][1];
NSArray *eventNameAndEventValueArray = [eventNameAndEventValueString componentsSeparatedByString: @"&"];
NSString *eventName = [eventNameAndEventValueArray[0] componentsSeparatedByString: @"="][1];
NSString *eventValueParams = [eventNameAndEventValueArray[1] componentsSeparatedByString: @"="][1];
NSString *decodedValueParams = [eventValueParams stringByRemovingPercentEncoding];
NSData *eventValuedata = [decodedValueParams dataUsingEncoding:(NSUTF8StringEncoding)];
NSDictionary *eventValue = [NSJSONSerialization JSONObjectWithData:eventValuedata options:NSJSONReadingMutableContainers error:nil];
if (eventName != nil){
[[AppsFlyerLib shared] logEvent:eventName withValues:eventValue];
}
}
Kode di atas mendengarkan pemuatan URL apa pun. Jika URL dengan "af-event" di dalamnya dimuat, itu akan memicu metode recordEvent
asli. Metode recordEvent
native mengekstrak parameter yang diperlukan (eventName dan eventValue) dan meneruskannya ke metode logEvent
SDK native.
Di pengontrol tampilan web Anda, tambahkan kode berikut di metode webView
import WebKit
import UIKit
import AppsFlyerLib
class WebViewController: UIViewController, WKNavigationDelegate {
var webView: WKWebView!
override func loadView(){
webView = WKWebView()
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://yourwebsite.com")!
webView.load(URLRequest(url: url))
}
func webView(_ view: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: ((WKNavigationActionPolicy) -> Void)) {
decisionHandler(.allow)
let pageUrl = navigationAction.request.url?.absoluteString
if(pageUrl?.hasPrefix("af-event://") ?? false){
let scanner = Scanner(string: pageUrl!)
scanner.charactersToBeSkipped = CharacterSet(charactersIn: "&?")
scanner.scanUpTo("?", into: nil)
var tempString, eventName : NSString?
var eventValue: [String: String] = Dictionary()
while(scanner.scanUpTo("&", into: &tempString)){
if let tempString = tempString {
if(tempString.hasPrefix("eventName=") && tempString.length > 10){
eventName = tempString.substring(from: 10) as NSString
}
if(tempString.hasPrefix("eventValue=") && tempString.length > 11){
let eventValues = tempString.components(separatedBy: "=")[1].removingPercentEncoding
let eventValuesData = eventValues?.data(using: String.Encoding.utf8)
do {
eventValue = try (JSONSerialization.jsonObject(with: eventValuesData!, options:[]) as? [String: String])!
} catch let error as NSError{
print(error)
}
}
}
}
if(eventName != nil){
if let eventName = eventName {
// record event
AppsFlyerLib.shared().logEvent(eventName as String?, withValues: eventValue)
}
}
}
}
}
Kode di atas mendengarkan pemuatan URL apa pun. Jika URL dengan "af-event" di dalamnya dimuat, ini mengekstrak parameter yang diperlukan (eventName dan eventValue) dan meneruskannya ke metode logEvent
SDK native.