Eventos in-app para aplicativos híbridos

Visão geral: grave eventos in-app de usuários que têm seu aplicativo instalado, mas realizam um evento no seu site mobile, e não no aplicativo.

Introdução

Eventos in-app que ocorrem dentro do aplicativo são reportados usando o SDK. E os eventos que ocorrem fora do aplicativo?

Existem alguns cenários nos quais os eventos ocorrem fora do contexto do aplicativo:

  • Eventos que ocorrem no seu site: implemente o people-based attribution (PBA) para obter uma visão unificada das jornadas do cliente em todos os canais, plataformas, incluindo o site e dispositivos. Isso fornece análises de Web-to-App, caminhos de conversão e dados brutos. 
  • Servidores de back-end: os eventos ocorrem independentemente da ação do usuário no site ou no aplicativo. Por exemplo, renovação automática de assinatura
  • Híbrido:  o evento ocorre em seu site mobile em um dispositivo com o aplicativo, conforme descrito neste artigo. Os eventos in-app são registrados chamando a API do SDK da AppsFlyer usando Javascript.

Este guia está relacionado ao cenário híbrido. Saiba como preencher a lacuna entre a visualização HTML e as visualizações nativas, permitindo que você grave eventos na visualização HTML e os envie para o aplicativo. 

 Exemplo

Você tem um aplicativo híbrido que oferece inscrições. Você implementa o formulário de inscrição em uma exibição da web que na verdade carrega a partir do seu site.

Você pode gravar o evento in-app de inscrição na visualização da web e enviar dados relacionados a ele, como tipo de assinatura ou preço, para o código nativo.

O código nativo coleta os dados e usa o SDK da AppsFlyer para enviar o evento in-app de inscrição.

Registro de eventos in-app em aplicativos híbridos

Neste guia, oferecemos dois métodos para registrar eventos in-app em aplicativos híbridos:

  • [Recomendado] Interface JavaScript: usa a interface JavaScript nativa para estabelecer comunicação entre o HTML ou Web View e o código nativo. Dessa forma, você pode enviar dados relacionados a eventos in-app do web view para o código nativo. Depois que o código nativo obtém os dados, ele os envia para a AppsFlyer usando o SDK.
  • Carregamento de URL: nesse método, o código nativo ouve os eventos de carregamento de URL. Você pode definir o código nativo para ouvir eventos de carregamento de URLs específicos e extrair dados dos parâmetros de URL. Em seguida, os dados são passados para o SDK.

Interface Javascript

Tanto o Android quanto o iOS têm interfaces Javascript nativas que permitem que as exibições da web façam chamadas para o código nativo.

Vantagens de usar a interface JavaScript nativa em relação ao carregamento de URL:

  • Não requer a implementação de lógica para o carregamento de URL.
  • Interfaces nativas são preferíveis a outras implementações.
  • Não há necessidade de analisar os parâmetros do URL.
  • Há menos código e, portanto, menos manutenção necessária.

A implementação consiste nas seguintes etapas:

  1. Código HTML para visualização da web ou página da web
  2. Implementação de código nativo para webview

Android

Código HTML para Android

Adicione o seguinte código HTML à exibição da web ou página da 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>

Ao transferir o valor do evento, lembre-se do seguinte:

  • Certifique-se de transferir o valor do evento como JSON em string.
    "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
  • Para evitar eventuais problemas o AppsFlyer recomenda usar apenas caracteres alfanuméricos minúsculos (a-z e 0-9) para nomes de eventos no aplicativo.

Classe WebActivity

Crie uma classe de atividade da web com o seguinte código:

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");
 }
}

O código acima cria um objeto chamado app que atua como a ponte entre a exibição da web e o código nativo.

Classe de interface JavaScript

Crie uma classe MainJSInterface para implementar recordEvent() como 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);
 }
}

O código acima declara um método recordEvent que pode ser chamado na exibição da web usando Javascript.

No código HTML, você pode ver que o método é chamado usando app.recordEvent(EventName, EventParams). Lembre-se de que configuramos o aplicativo para atuar como a ponte entre a visualização da web e o código nativo. É por isso que o app pode chamar o método recordEvent que definimos na classe MainJsInterface.

iOS

Código HTML para iOS

Adicione o seguinte código HTML à exibição da web ou página da 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>

O código acima define uma função a ser acionada quando um botão é clicado. A função define as variáveis eventName e eventParams e as transmite para o código nativo usando webkit.messageHandlers.

Ao transferir o valor do evento, lembre-se do seguinte:

  • Certifique-se de transferir o valor do evento como JSON em string.
    "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
  • Para evitar eventuais problemas o AppsFlyer recomenda usar apenas caracteres alfanuméricos minúsculos (a-z e 0-9) para nomes de eventos no aplicativo.

 Nota

O código HTML é para Objective C e Swift.

Objetivo c

Controlador de exibição da web

Em seu controlador de exibição da web, adicione o seguinte código no controlador de exibição.

-(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];

}

O código acima recebe a mensagem da visualização da web. A mensagem contém o nome e o valor do evento. Quando o código detecta a mensagem recebida, ele a transmite para o método recordEvent, que analisa os valores e chama o método logEvent do SDK nativo.

Controlador WebView Swift

Em seu controlador de exibição da web, adicione o seguinte código no método 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)
 }

}

O código acima recebe a mensagem da visualização da web. A mensagem contém o nome e o valor do evento. Quando o código detecta a mensagem recebida, ele a transmite para o método recordEvent, que analisa os valores e chama o método logEvent do SDK da AppsFlyer.

Carregamento de URL

Tanto o Android quanto o iOS implementam um método nativo que escuta eventos de carregamento de URL. Este método permite que você faça o seguinte:

  • Ouça um evento de carregamento de uma URL específica
  • Extraia parâmetros que são anexados à URL
  • Use esses parâmetros no código nativo

A implementação a seguir consiste em duas etapas:

  1. Código HTML para visualização da web ou página da web
  2. Implementação de código nativo para carregamento de URL

Implementação do WebView

Código HTML (tanto para o Android WebView quanto para o iOS WKWebView)

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

O código acima pode ser parte de uma página da web real ou carregado nativamente na visualização da web.

O código define uma função a ser acionada quando um botão é clicado. A função em si cria um elemento iframe que carrega uma URL personalizada. É esse carregamento de URL que aciona o método nativo do Android ou iOS que chama o método logEvent do SDK da AppsFlyer.

Todos os parâmetros necessários (nome do evento e valores do evento) são anexados à URL. Os exemplos de código Android e iOS abaixo demonstram como extrair esses parâmetros e passá-los para o método logEvent do SDK da AppsFlyer.

Ao transferir o valor do evento, lembre-se do seguinte:

  • Certifique-se de transferir o valor do evento como JSON em string.
    "{\"af_revenue\":\"6.72\", \"af_content_type\": \"wallets\", \"af_content_id\": \"15854\"}"
  • Para evitar eventuais problemas o AppsFlyer recomenda usar apenas caracteres alfanuméricos minúsculos (a-z e 0-9) para nomes de eventos no aplicativo.

Implementação nativa

Android iOS

Implementação do Android

O Android WebView usa um WebViewClient que recebe notificações da exibição da web. Em shouldOverrideUrlLoading, você pode manipular eventos de carregamento de URL que vêm da exibição da 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;

}