衡量用户互动度

本指南介绍了如何衡量 Chrome 自定义标签页的互动信号。如果您的应用会定期向用户显示指向网络内容的链接(例如在新闻 Feed 中),那么了解哪些链接对用户有价值,哪些链接没有价值可能非常重要。在自定义标签页中,您可以通过导航次数、滚动方向更改次数和滚动深度来衡量会话专用用户互动情况。如需查看互动信号的实际运作方式,请参阅 GitHub 上的自定义标签页演示应用

自定义标签页互动信号演示。

Custom Tabs 提供了两种不同的回调来衡量用户互动度:

  • CustomTabsCallback,用于跟踪基本导航事件,例如 "NAVIGATION_STARTED""NAVIGATION_FINISHED"
  • EngagementSignalsCallback,用于跟踪特定网页的用户互动情况,例如滚动方向或滚动百分比。

这两种方式都需要有效的 CustomTabsServiceConnection。如需详细了解如何连接到 CustomTabsService,请参阅之前的 CustomTabsService 指南

如需衡量用户互动度,请先创建 CustomTabsCallbackEngagementSignalsCallback 实例。CustomTabsCallback 会收到一个 navigationEvent 常量,用于描述发生了哪种导航:

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 支持三种不同的回调:

onVerticalScrollEvent()
每当用户更改滚动方向时都会调用,其中 isDirectionUp(第一个参数)表示方向。
  1. onGreatestScrollPercentageIncreased:当用户到达页面底部时,自定义标签页会以 5% 的间隔(最高 100%)发出滚动深度信号。只有在用户停止滚动后,系统才会调用回调。每次重新导航时,此值都会重置为 0%。
  2. onSessionEnded:自定义标签页在停止发送互动信号时触发此事件(例如,在用户关闭自定义标签页后)。如果用户以任何方式(滚动、点击按钮等)与网页互动,didUserInteract 将为 true。
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");
    }
};

CustomTabsCallbackEngagementSignalsCallback 都需要有效的自定义标签页服务连接。服务连接后,您可以通过调用 CustomTabsClient.newSession() 并传递 CustomTabsCallback 来创建新的 CustomTabsSession

之后,您应调用 isEngagementSignalsApiAvailable() 以检查当前浏览器是否支持互动信号。如果受支持,您可以通过 CustomTabsSession.setEngagementSignalsCallback() 注册 EngagementSignalsCallback

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

剩下唯一要做的就是绑定 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);
}