Cómo medir la participación de los usuarios

En esta guía, se explica cómo medir los indicadores de participación de las pestañas personalizadas de Chrome. Si tu app suele mostrar vínculos a contenido web para los usuarios (por ejemplo, en un feed de noticias), es importante que sepas cuáles son los vínculos que los usuarios consideran valiosos y cuáles no. En las pestañas personalizadas, puedes medir la participación del usuario específica de la sesión a través de la cantidad de navegaciones, los cambios en la dirección de desplazamiento y la profundidad de desplazamiento. Para ver los indicadores de participación en acción, consulta la app de demostración de pestañas personalizadas en GitHub.

Demostración de los indicadores de participación de la pestaña personalizada.

Las pestañas personalizadas proporcionan dos devoluciones de llamada diferentes para medir la participación del usuario:

  • CustomTabsCallback para hacer un seguimiento de eventos de navegación básicos, como "NAVIGATION_STARTED" o "NAVIGATION_FINISHED"
  • EngagementSignalsCallback para hacer un seguimiento de la participación del usuario específica de la página, como la dirección o el porcentaje de desplazamiento

Ambos requieren una CustomTabsServiceConnection activa. Consulta la guía anterior de CustomTabsService para obtener detalles sobre cómo conectarte a un CustomTabsService.

Para medir la participación de los usuarios, primero crea una instancia de CustomTabsCallback y una de EngagementSignalsCallback. CustomTabsCallback recibe una constante navigationEvent que describe el tipo de navegación que se llevó a cabo:

private CustomTabsCallback mCustomTabsCallback = new CustomTabsCallback() {
    @Override
    public void onNavigationEvent(int navigationEvent, @Nullable Bundle extras) {
        String event;
        switch (navigationEvent) {
            case CustomTabsCallback.NAVIGATION_ABORTED:
                event = "NAVIGATION_ABORTED";
                break;
            case CustomTabsCallback.NAVIGATION_FAILED:
                event = "NAVIGATION_FAILED";
                break;
            case CustomTabsCallback.NAVIGATION_FINISHED:
                event = "NAVIGATION_FINISHED";
                break;
            case CustomTabsCallback.NAVIGATION_STARTED:
                event = "NAVIGATION_STARTED";
                break;
            case CustomTabsCallback.TAB_SHOWN:
                event = "TAB_SHOWN";
                break;
            case CustomTabsCallback.TAB_HIDDEN:
                event = "TAB_HIDDEN";
                break;
            default:
                event = String.valueOf(navigationEvent);
        }
        Log.d(TAG, "onNavigationEvent (navigationEvent=" + event + ')');
        mTextNavigation.setText("onNavigationEvent " + event);
    }
};

EngagementSignalsCallback admite tres devoluciones de llamada diferentes:

onVerticalScrollEvent()
Se llama cada vez que el usuario cambia la dirección de desplazamiento, donde isDirectionUp (el primer argumento) indica la dirección.
  1. onGreatestScrollPercentageIncreased: La pestaña personalizada indica la profundidad de desplazamiento en intervalos de 5% hasta el 100% cuando el usuario llega a la parte inferior de la página. Solo se invoca la devolución de llamada una vez que el usuario deja de desplazarse. El valor se restablece al 0% con cada navegación nueva.
  2. onSessionEnded: La pestaña personalizada activa este evento cuando deja de enviar indicadores de participación (por ejemplo, después de que el usuario cierra la pestaña personalizada). El valor de didUserInteract será verdadero si el usuario interactuó con la página de alguna manera (desplazamiento, clic en un botón, etcétera).
private EngagementSignalsCallback mEngagementSignalsCallback = new EngagementSignalsCallback() {
    @Override
    public void onVerticalScrollEvent(boolean isDirectionUp, @NonNull Bundle extras) {
        Log.d(TAG, "onVerticalScrollEvent (isDirectionUp=" + isDirectionUp + ')');
        mTextVerticalScroll.setText("vertical scroll " + (isDirectionUp ? "UP️" : "DOWN"));
    }

    @Override
    public void onGreatestScrollPercentageIncreased(int scrollPercentage, @NonNull Bundle extras) {
        Log.d(TAG, "scroll percentage: " + scrollPercentage + "%");
        mTextGreatestPercentage.setText("scroll percentage: " + scrollPercentage + "%");
    }

    @Override
    public void onSessionEnded(boolean didUserInteract, @NonNull Bundle extras) {
        Log.d(TAG, "onSessionEnded (didUserInteract=" + didUserInteract + ')');
        mTextSessionEnd.setText(didUserInteract ? "session ended with user interaction" : "session ended without user interaction");
    }
};

CustomTabsCallback y EngagementSignalsCallback requieren una conexión activa del servicio de pestaña personalizada. Una vez que se conecte el servicio, podrás crear una CustomTabsSession nueva llamando a CustomTabsClient.newSession() y pasando el CustomTabsCallback.

A continuación, deberás llamar a isEngagementSignalsApiAvailable() para verificar si los indicadores de participación son compatibles con el navegador actual. Si son compatibles, puedes registrar tu EngagementSignalsCallback a través de CustomTabsSession.setEngagementSignalsCallback().

private CustomTabsClient mCustomTabsClient;
private CustomTabsSession mCustomTabsSession;

private final CustomTabsServiceConnection mServiceConnectionCallback = new CustomTabsServiceConnection() {

    @Override
    public void onCustomTabsServiceConnected(@NonNull ComponentName name, @NonNull CustomTabsClient client) {
        mCustomTabsClient = client;
        mCustomTabsSession = mCustomTabsClient.newSession(mCustomTabsCallback);
        try {
            boolean engagementSignalsApiAvailable = mCustomTabsSession.isEngagementSignalsApiAvailable(Bundle.EMPTY);
            if (!engagementSignalsApiAvailable) {
                Log.d(TAG, "CustomTab Engagement signals not available, make sure to use the " +
                        "latest Chrome version and enable via chrome://flags/#cct-real-time-engagement-signals");
                return;
            }
            mCustomTabsSession.setEngagementSignalsCallback(mEngagementSignalsCallback, Bundle.EMPTY);
        } catch (RemoteException e) {
            Log.w(TAG, "The Service died while responding to the request.", e);
        } catch (UnsupportedOperationException e) {
            Log.w(TAG, "Engagement Signals API isn't supported by the browser.", e);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mCustomTabsClient = null;
        mConnection = null;
        mCustomTabsSession = null;
    }
};

Lo único que queda por hacer es vincular el CustomTabsService:

@Override
protected void onStart() {
    super.onStart();
    bindCustomTabsService();
}

private void bindCustomTabsService() {
    String packageName = CustomTabsHelper.getPackageNameToUse(this);
    if (packageName == null) return;
    CustomTabsClient.bindCustomTabsService(this, packageName, mConnection);
}