Avaliar o engajamento do usuário

Este guia explica como medir os indicadores de engajamento das guias personalizadas do Chrome. Se o app mostra links para conteúdo da Web regularmente aos usuários, por exemplo, em um feed de notícias, é importante saber quais links os usuários acham valiosos e quais não são. Nas guias personalizadas, você pode medir o engajamento do usuário em uma sessão específica pelo número de navegações, mudanças na direção de rolagem e profundidade de rolagem. Para conferir os indicadores de engajamento em ação, confira o app de demonstração de guias personalizadas no GitHub (link em inglês).

Demonstração dos indicadores de engajamento da guia personalizada.

As guias personalizadas oferecem dois retornos de chamada diferentes para avaliar o engajamento do usuário:

  • CustomTabsCallback para rastrear eventos de navegação básicos, como "NAVIGATION_STARTED" ou "NAVIGATION_FINISHED".
  • EngagementSignalsCallback para acompanhar o engajamento específico do usuário na página, como a direção ou a porcentagem de rolagem.

Ambos exigem um CustomTabsServiceConnection ativo. Consulte o guia anterior do CustomTabsService para saber como se conectar a uma CustomTabsService.

Para medir o engajamento do usuário, primeiro crie uma instância de CustomTabsCallback e de EngagementSignalsCallback. O CustomTabsCallback recebe uma constante navigationEvent que descreve o tipo de navegação que aconteceu:

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

O EngagementSignalsCallback oferece suporte a três callbacks diferentes:

onVerticalScrollEvent()
Chamado toda vez que o usuário muda a direção de rolagem, em que isDirectionUp (o primeiro argumento) indica a direção.
  1. onGreatestScrollPercentageIncreased: a guia "Personalizada" indica a profundidade de rolagem em intervalos de 5% até 100% quando o usuário chega ao fim da página. O callback só é invocado quando o usuário para de rolar a tela. O valor é redefinido como 0% a cada nova navegação.
  2. onSessionEnded: a guia personalizada dispara esse evento quando ele para de enviar indicadores de engajamento (por exemplo, depois que o usuário fechou a guia personalizada). didUserInteract será verdadeiro se o usuário interagiu com a página de alguma forma (rolagem, clique no botão etc.).
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");
    }
};

Tanto o CustomTabsCallback quanto o EngagementSignalsCallback exigem uma conexão ativa de um serviço de guia personalizada. Quando o serviço estiver conectado, você poderá criar um novo CustomTabsSession chamando CustomTabsClient.newSession() e transmitindo o CustomTabsCallback.

Em seguida, chame isEngagementSignalsApiAvailable() para verificar se os indicadores de engajamento são compatíveis com o navegador atual. Se eles forem aceitos, registre seu EngagementSignalsCallback via 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;
    }
};

A única coisa que falta é vincular o 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);
}