이 가이드에서는 Chrome 맞춤 탭의 참여 신호를 측정하는 방법을 설명합니다. 앱에서 뉴스 피드와 같이 사용자에게 웹 콘텐츠 링크를 정기적으로 표시하는 경우 사용자가 가치 있다고 생각하는 링크와 그렇지 않은 링크를 파악하는 것이 중요할 수 있습니다. 맞춤 탭에서는 탐색 횟수, 스크롤 방향 변경, 스크롤 깊이를 통해 세션별 사용자 참여도를 측정할 수 있습니다. 참여 신호가 작동하는 모습을 보려면 GitHub의 맞춤 탭 데모 앱을 확인하세요.
맞춤 탭은 사용자 참여도를 측정하기 위한 두 가지 콜백을 제공합니다.
"NAVIGATION_STARTED"또는"NAVIGATION_FINISHED"와 같은 기본 탐색 이벤트를 추적하는CustomTabsCallback- 스크롤 방향 또는 스크롤 비율과 같은 페이지별 사용자 참여도를 추적하는 
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는 다음과 같은 세 가지 콜백을 지원합니다.
onVerticalScrollEvent()- 사용자가 스크롤 방향을 변경할 때마다 호출되며 여기서 
isDirectionUp(첫 번째 인수)는 방향을 나타냅니다. 
onGreatestScrollPercentageIncreased: 맞춤 탭은 사용자가 페이지 하단에 도달하면 5% 간격으로 최대 100% 까지 스크롤 심도를 신호합니다. 콜백은 사용자가 스크롤을 중지한 후에만 호출됩니다. 이 값은 새로운 탐색이 있을 때마다 0% 로 재설정됩니다.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 모두 활성 맞춤 탭 서비스 연결이 필요합니다. 서비스가 연결되면 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);
}