Cómo implementar 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
  • Un emulador de Android con Android 5.0 o versiones posteriores
  • Estar familiarizado con el lenguaje de programación Java
  • Tener conocimientos del 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 debería crearse 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 tu app y el código JavaScript.

De forma predeterminada, JavaScript está inhabilitado en un componente WebView. Puedes habilitarla a través de la configuración web adjunta 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. Cómo implementar 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 de 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 , tienes todo listo para comenzar a enviar eventos de análisis.

4. Cómo enviar eventos a través de la interfaz

Como puedes ver aquí, mi WebView es muy simple. Tiene tres botones: dos que registrarán un evento y el otro una propiedad del usuario:

7a00ed1192151b19.png

Cuando haga clic en los botones, se llamará a mi "script.js". y ejecuta 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 depurar 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 en tu app eventos del embudo clave que se producen a través de WebViews. Para aprovechar al máximo esta situación, también te sugerimos conectarte a Google Ads y, luego, importar estos eventos como conversiones.

Aprendiste lo siguiente:

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

Documentos de referencia