Đo lường mức độ tương tác của người dùng

Hướng dẫn này giải thích cách đo lường các tín hiệu tương tác cho thẻ tuỳ chỉnh của Chrome. Nếu ứng dụng của bạn thường xuyên hiển thị đường liên kết đến nội dung web cho người dùng, chẳng hạn như trong nguồn cấp dữ liệu tin tức, thì bạn cần biết những đường liên kết nào mà người dùng thấy có giá trị và những đường liên kết nào không. Trong Thẻ tuỳ chỉnh, bạn có thể đo lường mức độ tương tác của người dùng trong một phiên cụ thể thông qua số lượt điều hướng, thay đổi hướng cuộn và mức độ cuộn. Để xem các tín hiệu tương tác trong thực tế, hãy xem ứng dụng minh hoạ Thẻ tuỳ chỉnh trên GitHub.

Bản minh hoạ về tín hiệu tương tác của Thẻ tuỳ chỉnh.

Thẻ tuỳ chỉnh cung cấp hai lệnh gọi lại khác nhau để đo lường mức độ tương tác của người dùng:

  • CustomTabsCallback để theo dõi các sự kiện điều hướng cơ bản, chẳng hạn như "NAVIGATION_STARTED" hoặc "NAVIGATION_FINISHED".
  • EngagementSignalsCallback để theo dõi mức độ tương tác của người dùng trên một trang cụ thể, chẳng hạn như hướng cuộn hoặc tỷ lệ phần trăm cuộn.

Cả hai đều yêu cầu một CustomTabsServiceConnection đang hoạt động. Hãy xem hướng dẫn về CustomTabsService trước đó để biết thông tin chi tiết về cách kết nối với CustomTabsService.

Để đo lường mức độ tương tác của người dùng, trước tiên, hãy tạo một thực thể CustomTabsCallbackEngagementSignalsCallback. CustomTabsCallback nhận một hằng số navigationEvent mô tả loại thao tác điều hướng đã xảy ra:

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 hỗ trợ 3 lệnh gọi lại khác nhau:

onVerticalScrollEvent()
Được gọi mỗi khi người dùng thay đổi hướng cuộn, trong đó isDirectionUp (đối số đầu tiên) cho biết hướng.
  1. onGreatestScrollPercentageIncreased: Thẻ tuỳ chỉnh báo hiệu độ sâu cuộn theo khoảng thời gian 5% lên đến 100% khi người dùng đã đến cuối trang. Lệnh gọi lại chỉ được gọi sau khi người dùng ngừng cuộn. Giá trị này được đặt lại thành 0% với mỗi thao tác điều hướng mới.
  2. onSessionEnded: Thẻ tuỳ chỉnh kích hoạt sự kiện này khi ngừng gửi tín hiệu tương tác (ví dụ: sau khi người dùng đóng Thẻ tuỳ chỉnh). didUserInteract sẽ có giá trị true nếu người dùng tương tác với trang theo bất kỳ cách nào (cuộn, nhấp vào nút, v.v.).
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");
    }
};

Cả CustomTabsCallbackEngagementSignalsCallback đều yêu cầu kết nối dịch vụ Thẻ tuỳ chỉnh đang hoạt động. Sau khi kết nối dịch vụ, bạn có thể tạo một CustomTabsSession mới bằng cách gọi CustomTabsClient.newSession() và truyền CustomTabsCallback.

Sau đó, bạn nên gọi isEngagementSignalsApiAvailable() để kiểm tra xem trình duyệt hiện tại có hỗ trợ các tín hiệu tương tác hay không. Nếu được hỗ trợ, bạn có thể đăng ký EngagementSignalsCallback thông qua 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;
    }
};

Việc duy nhất còn lại là liên kết 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);
}