Mierzenie zaangażowania użytkowników

Z tego przewodnika dowiesz się, jak mierzyć sygnały zaangażowania w przypadku niestandardowych kart Chrome. Jeśli Twoja aplikacja regularnie udostępnia użytkownikom linki do treści internetowych, np. w kanale z wiadomościami, warto wiedzieć, które linki są wartościowe, a które nie. W przypadku kart niestandardowych możesz mierzyć zaangażowanie użytkowników w dane sesji za pomocą liczby nawigacji, zmian kierunku przewijania i głębi przewijania. Aby zobaczyć, jak w praktyce działają sygnały zaangażowania, otwórz aplikację demonstracyjną kart niestandardowych na GitHubie.

Wersja demonstracyjna sygnałów zaangażowania na karcie niestandardowej.
.
.

Karty niestandardowe udostępniają 2 różne wywołania zwrotne do pomiaru zaangażowania użytkowników:

  • CustomTabsCallback do śledzenia podstawowych zdarzeń związanych z nawigacją, np. "NAVIGATION_STARTED" lub "NAVIGATION_FINISHED".
  • EngagementSignalsCallback – do śledzenia zaangażowania użytkowników na określonej stronie, np. kierunku przewijania lub procentu przewijania.

Oba wymagają aktywnego CustomTabsServiceConnection. Szczegółowe informacje o tym, jak połączyć się z CustomTabsService, znajdziesz w poprzednim przewodniku po CustomTabsService.

Aby mierzyć zaangażowanie użytkowników, najpierw utwórz instancję CustomTabsCallback i EngagementSignalsCallback. Urządzenie CustomTabsCallback otrzymuje stałą navigationEvent opisującą rodzaj nawigacji:

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 obsługuje 3 różne wywołania zwrotne:

onVerticalScrollEvent()
Wywoływane za każdym razem, gdy użytkownik zmieni kierunek przewijania, gdzie isDirectionUp (pierwszy argument) wskazuje kierunek.
  1. onGreatestScrollPercentageIncreased: karta niestandardowa sygnalizuje głębokość przewijania w odstępach 5%, do 100%, gdy użytkownik dotrze do dołu strony. Wywołanie zwrotne jest wywoływane dopiero wtedy, gdy użytkownik przestanie przewijać. Przy każdej nowej nawigacji ta wartość jest resetowana do 0%.
  2. onSessionEnded: karta niestandardowa uruchamia to zdarzenie, gdy przestanie wysyłać sygnały zaangażowania (np. gdy użytkownik zamknie kartę niestandardową). didUserInteract ma wartość true (prawda), jeśli użytkownik w jakikolwiek sposób wejdzie w interakcję ze stroną (przewijając, klikając przycisk itp.).
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");
    }
};

Zarówno interfejs CustomTabsCallback, jak i EngagementSignalsCallback wymagają połączenia z usługą karty niestandardowej. Po połączeniu usługi możesz utworzyć nowy CustomTabsSession, wywołując funkcję CustomTabsClient.newSession() i przekazując CustomTabsCallback.

Następnie wywołaj funkcję isEngagementSignalsApiAvailable(), by sprawdzić, czy obecna przeglądarka obsługuje sygnały zaangażowania. Jeśli są obsługiwane, możesz zarejestrować EngagementSignalsCallback w 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;
    }
};

Pozostało Ci już tylko powiązanie elementu 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);
}