מדידת מעורבות המשתמשים

במדריך הזה מוסבר איך למדוד את אותות ההתעניינות בכרטיסיות בהתאמה אישית ב-Chrome. אם האפליקציה שלכם מציגה למשתמשים באופן קבוע קישורים לתוכן מהאינטרנט, למשל בפיד חדשות, חשוב לדעת אילו קישורים מעניינים את המשתמשים ואילו לא. בכרטיסיות בהתאמה אישית אפשר למדוד את התעניינות המשתמשים באופן ספציפי לסשן לפי מספר הניווטים, שינויים בכיוון הגלילה ועומק הגלילה. כדי לראות את אותות המעורבות בפעולה, אפשר לעיין באפליקציית ההדגמה של כרטיסיות מותאמות אישית ב-GitHub.

הדגמה של אותות מעורבות בכרטיסייה 'מותאם אישית'.

כרטיסיות מותאמות אישית מספקות שתי קריאות חוזרות (callback) שונות למדידת מעורבות המשתמשים:

  • CustomTabsCallback למעקב אחר אירועי ניווט בסיסיים, כמו "NAVIGATION_STARTED" או "NAVIGATION_FINISHED".
  • EngagementSignalsCallback למעקב אחר התעניינות משתמשים ספציפית לדף, כמו כיוון גלילה או אחוז גלילה.

בשניהם נדרש CustomTabsServiceConnection פעיל. במדריך הקודם של CustomTabsService מוסבר איך להתחבר אל CustomTabsService.

כדי למדוד התעניינות של משתמשים, קודם צריך ליצור מופע של CustomTabsCallback ומופע של EngagementSignalsCallback. השדה 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 יש תמיכה בשלושה קריאות חוזרות (callback):

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

גם ל-CustomTabsCallback וגם ל-EngagementSignalsCallback נדרש חיבור פעיל לשירות של כרטיסייה מותאמת אישית. לאחר חיבור השירות, ניתן ליצור CustomTabsSession חדש על ידי התקשרות אל CustomTabsClient.newSession() והעברת CustomTabsCallback.

אחר כך צריך להתקשר אל isEngagementSignalsApiAvailable() כדי לבדוק אם אותות המעורבות נתמכים בדפדפן הנוכחי. אם הן נתמכות, אפשר לרשום את EngagementSignalsCallback דרך 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;
    }
};

כל מה שנשאר לעשות הוא לקשר את 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);
}