Implementa Google Analytics para Firebase en WebView de Android

1. Introducción

Última actualización: 3/2/2022

8cef5cc6581b73d0.png

Qué aprenderás

  • Cómo crear un WebView muy simple en Android
  • Cómo enviar eventos de WebView a Firebase

Requisitos

  • Proyecto de Firebase con el SDK de Analytics implementado
  • Android Studio versión 4.2 o posterior
  • Android Emulator con Android 5.0 o versiones posteriores
  • Familiaridad con el lenguaje de programación Java
  • Familiaridad con el lenguaje de programación JavaScript

2. Cómo crear una WebView simple en Android

Cómo agregar WebView en el diseño de la actividad

Para agregar una WebView a tu app en el diseño, agrega el siguiente código al archivo en formato XML de diseño de tu actividad:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".WebActivity"
>
  <WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
  />
</androidx.constraintlayout.widget.ConstraintLayout>;

Cómo agregar una WebView en onCreate()

Para cargar una página web en WebView, usa loadUrl(). La WebView se debe crear en la actividad negra. Por ejemplo, implementaré esto en el método onCreate:

public class WebActivity extends AppCompatActivity {
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);
        // Navigate to site
        myWebView.loadUrl("https://bittererhu.glitch.me");
 }
}

Sin embargo, para que esto funcione, la app debe tener acceso a Internet. Para obtener acceso a Internet, solicita el permiso de INTERNET en el archivo de manifiesto. Por ejemplo:

<uses-permission android:name="android.permission.INTERNET" />

Eso es todo lo que necesitas para una WebView básica que muestre una página web.

Cómo usar JavaScript en WebViews

si la página web que planeas cargar en tu WebView usa JavaScript, debes habilitarlo para tu WebView. Una vez que JavaScript esté habilitado, también podrás crear interfaces entre el código de la app y el de JavaScript.

JavaScript está inhabilitado de forma predeterminada en un componente WebView. Puedes habilitarlo a través de WebSettings adjunto a tu WebView. Puedes recuperar WebSettings con getSettings() y luego habilitar JavaScript con setJavaScriptEnabled().

Por ejemplo:

WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

Actividad actualizada :

public class WebActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web);
        WebView myWebView = (WebView) findViewById(R.id.webview);
        if(myWebView != null) {
            WebSettings webSettings = myWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
        }
        // Navigate to site
        myWebView.loadUrl("https://bittererhu.glitch.me");
  }
}

be627fcc51a6179f.png

3. Implementa la interfaz de puente de JavaScript

Controlador de Javacript

El primer paso para usar Google Analytics en WebView es crear funciones de JavaScript para reenviar eventos y propiedades del usuario al código nativo. En el siguiente ejemplo, se muestra cómo hacerlo de una manera compatible con el código nativo de Android y Apple:

En este ejemplo, creé un archivo JavaScript llamado script.js que incluye lo siguiente:

function logEvent(name, params) {
  if (!name) {
    return;
  }
  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'logEvent',
      name: name,
      parameters: params
    };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}


function setUserProperty(name, value) {
  if (!name || !value) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.setUserProperty(name, value);
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'setUserProperty',
      name: name,
      value: value
   };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}

Interfaz nativa

Para invocar código nativo de Android desde JavaScript, implementa una clase con métodos marcados con @JavaScriptInterface. En el siguiente ejemplo, creé una nueva clase de Java llamada AnalyticsWebInterfcae.java:

public class AnalyticsWebInterface {

    public static final String TAG = "AnalyticsWebInterface";
    private FirebaseAnalytics mAnalytics;

    public AnalyticsWebInterface(Context context) {
        mAnalytics = FirebaseAnalytics.getInstance(context);
    }

    @JavascriptInterface
    public void logEvent(String name, String jsonParams) {
        LOGD("logEvent:" + name);
        mAnalytics.logEvent(name, bundleFromJson(jsonParams));
    }

    @JavascriptInterface
    public void setUserProperty(String name, String value) {
        LOGD("setUserProperty:" + name);
        mAnalytics.setUserProperty(name, value);
    }

    private void LOGD(String message) {
        // Only log on debug builds, for privacy
        if (BuildConfig.DEBUG) {
            Log.d(TAG, message);
        }
    }

    private Bundle bundleFromJson(String json) {
        // ...
    }
}

Once you have created the native interface, register it with your WebView so that it is visible to JavaScript code running in the WebView:

// Only add the JavaScriptInterface on API version JELLY_BEAN_MR1 and above, due to
// security concerns, see link below for more information:
// https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%20java.lang.String)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    mWebView.addJavascriptInterface(
            new AnalyticsWebInterface(this), AnalyticsWebInterface.TAG);
} else {
    Log.w(TAG, "Not adding JavaScriptInterface, API Version: " + Build.VERSION.SDK_INT);
}

Código final :

// [START analytics_web_interface]
public class AnalyticsWebInterface {

    public static final String TAG = "AnalyticsWebInterface";
    private FirebaseAnalytics mAnalytics;

    public AnalyticsWebInterface(Context context) {
        mAnalytics = FirebaseAnalytics.getInstance(context);
    }
    @JavascriptInterface
    public void logEvent(String name, String jsonParams) {
        LOGD("logEvent:" + name);
        mAnalytics.logEvent(name, bundleFromJson(jsonParams));
    }
    @JavascriptInterface
    public void setUserProperty(String name, String value) {
        LOGD("setUserProperty:" + name);
        mAnalytics.setUserProperty(name, value);
    }
    private void LOGD(String message) {
        // Only log on debug builds, for privacy
        if (BuildConfig.DEBUG) {
            Log.d(TAG, message);
        }
    }
    private Bundle bundleFromJson(String json) {
        // [START_EXCLUDE]
        if (TextUtils.isEmpty(json)) {
            return new Bundle();
        }

        Bundle result = new Bundle();
        try {
            JSONObject jsonObject = new JSONObject(json);
            Iterator<String> keys = jsonObject.keys();

            while (keys.hasNext()) {
                String key = keys.next();
                Object value = jsonObject.get(key);
                if (value instanceof String) {
                    result.putString(key, (String) value);
                } else if (value instanceof Integer) {
                    result.putInt(key, (Integer) value);
                } else if (value instanceof Double) {
                    result.putDouble(key, (Double) value);
                } else {
                    Log.w(TAG, "Value for key " + key + " not one of [String, Integer, Double]");
                }
            }
        } catch (JSONException e) {
            Log.w(TAG, "Failed to parse JSON, returning empty Bundle.", e);
            return new Bundle();
        }
        return result;
        // [END_EXCLUDE]
    }

Ahora que configuraste la interfaz de JavaScript, ya puedes comenzar a enviar eventos de Analytics.

4. Envía eventos a través de la interfaz

Como puedes ver, mi WebView es muy simple, tiene tres botones, dos de los cuales registrarán un evento y el otro registrará una propiedad del usuario:

7a00ed1192151b19.png

Una vez que haga clic en los botones, se llamará a mi archivo "script.js" y se ejecutará el siguiente código:

document.getElementById("event1").addEventListener("click", function() {
    console.log("event1");
    logEvent("event1", { foo: "bar", baz: 123 });
});

document.getElementById("event2").addEventListener("click", function() {
  console.log("event2");
    logEvent("event2", { size: 123.456 });
});

document.getElementById("userprop").addEventListener("click", function() {
    console.log("userprop");
    setUserProperty("userprop", "custom_value");
});

Archivo script.js final :

/* If you're feeling fancy you can add interactivity 
    to your site with Javascript */

// prints "hi" in the browser's dev tools console
console.log("hi");

// [START log_event]
function logEvent(name, params) {
  if (!name) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.logEvent(name, JSON.stringify(params));
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'logEvent',
      name: name,
      parameters: params
    };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}
// [END log_event]

// [START set_user_property]
function setUserProperty(name, value) {
  if (!name || !value) {
    return;
  }

  if (window.AnalyticsWebInterface) {
    // Call Android interface
    window.AnalyticsWebInterface.setUserProperty(name, value);
  } else if (window.webkit
      && window.webkit.messageHandlers
      && window.webkit.messageHandlers.firebase) {
    // Call iOS interface
    var message = {
      command: 'setUserProperty',
      name: name,
      value: value
   };
    window.webkit.messageHandlers.firebase.postMessage(message);
  } else {
    // No Android or iOS interface found
    console.log("No native APIs found.");
  }
}
// [END set_user_property]

document.getElementById("event1").addEventListener("click", function() {
    console.log("event1");
    logEvent("event1", { foo: "bar", baz: 123 });
});

document.getElementById("event2").addEventListener("click", function() {
  console.log("event2");
    logEvent("event2", { size: 123.456 });
});

document.getElementById("userprop").addEventListener("click", function() {
    console.log("userprop");
    setUserProperty("userprop", "custom_value");
});

Esta es la forma básica de enviar eventos a Analytics.

5. Cómo depurar eventos de Webview en Firebase

La depuración de eventos de WebView en tu app funciona de la misma manera que la depuración de cualquier parte nativa de tu SDK:

Para habilitar el modo de depuración, usa los siguientes comandos en la consola de Android Studio:

adb shell setprop debug.firebase.analytics.app package_name

Cuando termines, puedes probar y ver cómo cobran vida tus eventos de WebView :

d230debf4ccfddad.png

6. Felicitaciones

Felicitaciones, creaste correctamente un WebView en tu app para Android. Puedes enviar y medir los eventos de embudo clave en tu app que se realizan a través de WebViews. Para aprovechar al máximo esta función, también te sugerimos que te conectes a Google Ads y que importes estos eventos como conversiones.

Aprendiste lo siguiente:

  • Cómo enviar eventos de WebView a Firebase
  • Cómo configurar y crear un WebView simple en Android

Documentos de referencia