From 2be2f9e64fdde62157f3fdcc9d62f4dfb4364b35 Mon Sep 17 00:00:00 2001 From: Seth Onyango Date: Tue, 17 Sep 2024 14:15:41 +0300 Subject: [PATCH] Log interaction across pages --- .../IdentityVerificationFragmentFactory.kt | 6 ++++++ .../IdentityAnalyticsRequestBuilder.kt | 20 +++++++++++++++++++ .../capture/manual/ManualCaptureFragment.kt | 5 +++++ .../capture/scan/ScanCaptureFragment.kt | 7 +++++++ .../capture/upload/UploadCaptureFragment.kt | 6 ++++++ .../DocumentCaptureMethodsFragment.kt | 6 ++++++ .../documents/DocumentSelectionFragment.kt | 7 ++++++- .../identity/error/AbstractErrorFragment.kt | 15 +++++++++++++- .../io/falu/identity/error/ErrorFragment.kt | 4 +++- .../error/ScanCaptureErrorFragment.kt | 4 +++- .../error/SelfieCaptureErrorFragment.kt | 5 ++++- .../io/falu/identity/selfie/SelfieFragment.kt | 9 +++++++++ .../falu/identity/support/SupportFragment.kt | 5 +++++ .../falu/identity/welcome/WelcomeFragment.kt | 3 +++ 14 files changed, 97 insertions(+), 5 deletions(-) diff --git a/identity/src/main/java/io/falu/identity/IdentityVerificationFragmentFactory.kt b/identity/src/main/java/io/falu/identity/IdentityVerificationFragmentFactory.kt index b89e9cb4..1976a355 100644 --- a/identity/src/main/java/io/falu/identity/IdentityVerificationFragmentFactory.kt +++ b/identity/src/main/java/io/falu/identity/IdentityVerificationFragmentFactory.kt @@ -10,6 +10,9 @@ import io.falu.identity.capture.upload.UploadCaptureFragment import io.falu.identity.confirmation.ConfirmationFragment import io.falu.identity.documents.DocumentCaptureMethodsFragment import io.falu.identity.documents.DocumentSelectionFragment +import io.falu.identity.error.ErrorFragment +import io.falu.identity.error.ScanCaptureErrorFragment +import io.falu.identity.error.SelfieCaptureErrorFragment import io.falu.identity.selfie.SelfieFragment import io.falu.identity.support.SupportFragment import io.falu.identity.verification.IdentificationVerificationFragment @@ -33,6 +36,9 @@ internal class IdentityVerificationFragmentFactory( ConfirmationFragment::class.java.name -> ConfirmationFragment(factory, callback) SupportFragment::class.java.name -> SupportFragment(factory) SelfieFragment::class.java.name -> SelfieFragment(factory) + ErrorFragment::class.java.name -> ErrorFragment(factory) + SelfieCaptureErrorFragment::class.java.name -> SelfieCaptureErrorFragment(factory) + ScanCaptureErrorFragment::class.java.name -> ScanCaptureErrorFragment(factory) IdentificationVerificationFragment::class.java.name -> IdentificationVerificationFragment(factory) TaxPinVerificationFragment::class.java.name -> TaxPinVerificationFragment(factory) else -> super.instantiate(classLoader, className) diff --git a/identity/src/main/java/io/falu/identity/analytics/IdentityAnalyticsRequestBuilder.kt b/identity/src/main/java/io/falu/identity/analytics/IdentityAnalyticsRequestBuilder.kt index e25b0af7..7fa7821e 100644 --- a/identity/src/main/java/io/falu/identity/analytics/IdentityAnalyticsRequestBuilder.kt +++ b/identity/src/main/java/io/falu/identity/analytics/IdentityAnalyticsRequestBuilder.kt @@ -125,6 +125,14 @@ internal class IdentityAnalyticsRequestBuilder( ) ) + fun screenPresented(scanType: ScanDisposition.DocumentScanType? = null, screenName: String) = createRequest( + EVENT_SCREEN_PRESENTED, + makeEventParameters( + KEY_DOCUMENT_SCAN_TYPE to scanType?.name, + KEY_SCREEN_NAME to screenName + ) + ) + companion object { const val CLIENT = "identity-sdk-mobile" const val ORIGIN = "falu-identity-android" @@ -137,6 +145,7 @@ internal class IdentityAnalyticsRequestBuilder( const val EVENT_CAMERA_PERMISSION_DENIED = "camera_permission_denied" const val EVENT_CAMERA_PERMISSION_GRANTED = "camera_permission_granted" const val EVENT_IDENTITY_DOCUMENT_TIMEOUT = "document_timeout" + const val EVENT_SCREEN_PRESENTED = "screen_presented" const val EVENT_SELFIE_TIMEOUT = "selfie_timeout" const val EVENT_MODEL_PERFORMANCE = "model_performance" const val EVENT_CAMERA_INFO = "camera_info" @@ -162,5 +171,16 @@ internal class IdentityAnalyticsRequestBuilder( const val KEY_FRAMES = "frames" const val KEY_CAMERA_ROTATION = "camera_rotation" const val KEY_VIEW_RESULT = "view_result" + const val KEY_SCREEN_NAME = "screen_name" + + const val SCREEN_NAME_ERROR = "error" + const val SCREEN_NAME_WELCOME = "welcome" + const val SCREEN_NAME_DOCUMENT_SELECTION = "document_selection" + const val SCREEN_NAME_DOCUMENT_CAPTURE_METHODS = "document_capture_methods" + const val SCREEN_NAME_MANUAL_CAPTURE = "manual_capture" + const val SCREEN_NAME_AUTO_CAPTURE = "auto_capture" + const val SCREEN_NAME_UPLOAD_CAPTURE = "upload_capture" + const val SCREEN_NAME_SUPPORT = "support" + const val SCREEN_NAME_SELFIE = "selfie" } } \ No newline at end of file diff --git a/identity/src/main/java/io/falu/identity/capture/manual/ManualCaptureFragment.kt b/identity/src/main/java/io/falu/identity/capture/manual/ManualCaptureFragment.kt index 73a48f3e..f3e9c5ef 100644 --- a/identity/src/main/java/io/falu/identity/capture/manual/ManualCaptureFragment.kt +++ b/identity/src/main/java/io/falu/identity/capture/manual/ManualCaptureFragment.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import io.falu.identity.R +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_MANUAL_CAPTURE import io.falu.identity.api.DocumentUploadDisposition import io.falu.identity.api.models.DocumentSide import io.falu.identity.api.models.IdentityDocumentType @@ -55,6 +56,10 @@ internal class ManualCaptureFragment(identityViewModelFactory: ViewModelProvider override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + identityViewModel.reportTelemetry( + identityViewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_MANUAL_CAPTURE) + ) + binding.cardDocumentBack.visibility = if (isPassport) View.GONE else View.VISIBLE binding.buttonContinue.isEnabled = false diff --git a/identity/src/main/java/io/falu/identity/capture/scan/ScanCaptureFragment.kt b/identity/src/main/java/io/falu/identity/capture/scan/ScanCaptureFragment.kt index cb8fdfe9..4581a491 100644 --- a/identity/src/main/java/io/falu/identity/capture/scan/ScanCaptureFragment.kt +++ b/identity/src/main/java/io/falu/identity/capture/scan/ScanCaptureFragment.kt @@ -15,6 +15,8 @@ import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R import io.falu.identity.ai.DocumentDetectionOutput import io.falu.identity.analytics.AnalyticsDisposition +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_AUTO_CAPTURE +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_MANUAL_CAPTURE import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.verification.Verification import io.falu.identity.api.models.verification.VerificationCapture @@ -54,6 +56,11 @@ internal class ScanCaptureFragment(identityViewModelFactory: ViewModelProvider.F override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + identityViewModel.reportTelemetry( + identityViewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_AUTO_CAPTURE) + ) + identityDocumentType = requireArguments().serializable(DocumentSelectionFragment.KEY_IDENTITY_DOCUMENT_TYPE)!! diff --git a/identity/src/main/java/io/falu/identity/capture/upload/UploadCaptureFragment.kt b/identity/src/main/java/io/falu/identity/capture/upload/UploadCaptureFragment.kt index 4d292d6d..f5089eb1 100644 --- a/identity/src/main/java/io/falu/identity/capture/upload/UploadCaptureFragment.kt +++ b/identity/src/main/java/io/falu/identity/capture/upload/UploadCaptureFragment.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.lifecycle.ViewModelProvider import io.falu.identity.R +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_UPLOAD_CAPTURE import io.falu.identity.api.DocumentUploadDisposition import io.falu.identity.api.models.DocumentSide import io.falu.identity.api.models.IdentityDocumentType @@ -30,6 +31,11 @@ internal class UploadCaptureFragment(identityViewModelFactory: ViewModelProvider override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + identityViewModel.reportTelemetry( + identityViewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_UPLOAD_CAPTURE) + ) + binding.cardDocumentBack.visibility = if (isPassport) View.GONE else View.VISIBLE binding.buttonContinue.isEnabled = false diff --git a/identity/src/main/java/io/falu/identity/documents/DocumentCaptureMethodsFragment.kt b/identity/src/main/java/io/falu/identity/documents/DocumentCaptureMethodsFragment.kt index 88bac146..4e5348ca 100644 --- a/identity/src/main/java/io/falu/identity/documents/DocumentCaptureMethodsFragment.kt +++ b/identity/src/main/java/io/falu/identity/documents/DocumentCaptureMethodsFragment.kt @@ -13,6 +13,7 @@ import androidx.navigation.fragment.findNavController import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R import io.falu.identity.analytics.AnalyticsDisposition +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_DOCUMENT_CAPTURE_METHODS import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.UploadMethod import io.falu.identity.api.models.verification.Verification @@ -39,6 +40,11 @@ internal class DocumentCaptureMethodsFragment(private val factory: ViewModelProv override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + viewModel.reportTelemetry( + viewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_DOCUMENT_CAPTURE_METHODS) + ) + identityDocumentType = (requireArguments().getSerializable(DocumentSelectionFragment.KEY_IDENTITY_DOCUMENT_TYPE) as IdentityDocumentType?)!! diff --git a/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt b/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt index 4b2b9b21..7ddb8be1 100644 --- a/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt +++ b/identity/src/main/java/io/falu/identity/documents/DocumentSelectionFragment.kt @@ -11,11 +11,12 @@ import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_DOCUMENT_SELECTION import io.falu.identity.api.models.IdentityDocumentType import io.falu.identity.api.models.country.SupportedCountry import io.falu.identity.api.models.verification.Verification -import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.api.models.verification.VerificationType +import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.countries.CountriesAdapter import io.falu.identity.databinding.FragmentDocumentSelectionBinding import io.falu.identity.utils.navigateToApiResponseProblemFragment @@ -43,6 +44,10 @@ class DocumentSelectionFragment(private val factory: ViewModelProvider.Factory) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + viewModel.reportTelemetry(viewModel.analyticsRequestBuilder + .screenPresented(screenName = SCREEN_NAME_DOCUMENT_SELECTION)) + viewModel.observerForSupportedCountriesResults( viewLifecycleOwner, onSuccess = { onSupportedCountriesListed(it.toList()) }, diff --git a/identity/src/main/java/io/falu/identity/error/AbstractErrorFragment.kt b/identity/src/main/java/io/falu/identity/error/AbstractErrorFragment.kt index b1afa022..f29cc417 100644 --- a/identity/src/main/java/io/falu/identity/error/AbstractErrorFragment.kt +++ b/identity/src/main/java/io/falu/identity/error/AbstractErrorFragment.kt @@ -6,13 +6,19 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.ViewModelProvider import io.falu.identity.IdentityVerificationResultCallback +import io.falu.identity.IdentityVerificationViewModel +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_ERROR import io.falu.identity.databinding.FragmentErrorBinding -internal abstract class AbstractErrorFragment : Fragment() { +internal abstract class AbstractErrorFragment(identityViewModelFactory: ViewModelProvider.Factory) : Fragment() { private var _binding: FragmentErrorBinding? = null protected val binding get() = _binding!! + private val identityViewModel: IdentityVerificationViewModel by activityViewModels { identityViewModelFactory } + protected lateinit var callback: IdentityVerificationResultCallback override fun onAttach(context: Context) { @@ -33,6 +39,13 @@ internal abstract class AbstractErrorFragment : Fragment() { return binding.root } + override fun onViewStateRestored(savedInstanceState: Bundle?) { + super.onViewStateRestored(savedInstanceState) + identityViewModel.reportTelemetry( + identityViewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_ERROR) + ) + } + override fun onDestroyView() { super.onDestroyView() _binding = null diff --git a/identity/src/main/java/io/falu/identity/error/ErrorFragment.kt b/identity/src/main/java/io/falu/identity/error/ErrorFragment.kt index ab38ec5c..0eeed886 100644 --- a/identity/src/main/java/io/falu/identity/error/ErrorFragment.kt +++ b/identity/src/main/java/io/falu/identity/error/ErrorFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.View import androidx.annotation.IdRes import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider import androidx.navigation.NavController import androidx.navigation.fragment.findNavController import io.falu.identity.IdentityVerificationResult @@ -14,7 +15,8 @@ import io.falu.identity.api.models.requirements.RequirementError.Companion.canNa import io.falu.identity.utils.getErrorDescription import software.tingle.api.HttpApiResponseProblem -internal class ErrorFragment : AbstractErrorFragment() { +internal class ErrorFragment(identityViewModelFactory: ViewModelProvider.Factory) : + AbstractErrorFragment(identityViewModelFactory) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/identity/src/main/java/io/falu/identity/error/ScanCaptureErrorFragment.kt b/identity/src/main/java/io/falu/identity/error/ScanCaptureErrorFragment.kt index 035eb44b..e4d3b3f3 100644 --- a/identity/src/main/java/io/falu/identity/error/ScanCaptureErrorFragment.kt +++ b/identity/src/main/java/io/falu/identity/error/ScanCaptureErrorFragment.kt @@ -2,10 +2,12 @@ package io.falu.identity.error import android.os.Bundle import android.view.View +import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import io.falu.identity.R -internal class ScanCaptureErrorFragment : AbstractErrorFragment() { +internal class ScanCaptureErrorFragment(identityViewModelFactory: ViewModelProvider.Factory) : + AbstractErrorFragment(identityViewModelFactory) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/identity/src/main/java/io/falu/identity/error/SelfieCaptureErrorFragment.kt b/identity/src/main/java/io/falu/identity/error/SelfieCaptureErrorFragment.kt index 6e670a46..122f63cc 100644 --- a/identity/src/main/java/io/falu/identity/error/SelfieCaptureErrorFragment.kt +++ b/identity/src/main/java/io/falu/identity/error/SelfieCaptureErrorFragment.kt @@ -2,11 +2,14 @@ package io.falu.identity.error import android.os.Bundle import android.view.View +import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import io.falu.identity.IdentityVerificationResult import io.falu.identity.R -internal class SelfieCaptureErrorFragment : AbstractErrorFragment() { +internal class SelfieCaptureErrorFragment(identityViewModelFactory: ViewModelProvider.Factory) : + AbstractErrorFragment(identityViewModelFactory) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) diff --git a/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt b/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt index c223924d..b799fc7a 100644 --- a/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt +++ b/identity/src/main/java/io/falu/identity/selfie/SelfieFragment.kt @@ -17,6 +17,7 @@ import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R import io.falu.identity.ai.FaceDetectionOutput import io.falu.identity.analytics.AnalyticsDisposition +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_SELFIE import io.falu.identity.api.models.UploadMethod import io.falu.identity.api.models.verification.Verification import io.falu.identity.api.models.verification.VerificationSelfieUpload @@ -56,6 +57,14 @@ internal class SelfieFragment(identityViewModelFactory: ViewModelProvider.Factor override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + identityViewModel.reportTelemetry( + identityViewModel.analyticsRequestBuilder.screenPresented( + scanType = ScanDisposition.DocumentScanType.SELFIE, + screenName = SCREEN_NAME_SELFIE + ) + ) + verificationRequest = requireNotNull(VerificationUploadRequest.getFromBundle(requireArguments())) { "Verification upload request is null" diff --git a/identity/src/main/java/io/falu/identity/support/SupportFragment.kt b/identity/src/main/java/io/falu/identity/support/SupportFragment.kt index 09388755..df045c62 100644 --- a/identity/src/main/java/io/falu/identity/support/SupportFragment.kt +++ b/identity/src/main/java/io/falu/identity/support/SupportFragment.kt @@ -11,6 +11,7 @@ import androidx.fragment.app.activityViewModels import androidx.lifecycle.ViewModelProvider import io.falu.core.exceptions.ApiException import io.falu.identity.IdentityVerificationViewModel +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_SUPPORT import io.falu.identity.api.models.Support import io.falu.identity.databinding.FragmentSupportBinding import io.falu.identity.utils.navigateToApiResponseProblemFragment @@ -35,6 +36,10 @@ internal class SupportFragment( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.reportTelemetry( + viewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_SUPPORT) + ) + viewModel.observeForVerificationResults( viewLifecycleOwner, onSuccess = { diff --git a/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt b/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt index c4be42fc..2c8b5605 100644 --- a/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt +++ b/identity/src/main/java/io/falu/identity/welcome/WelcomeFragment.kt @@ -15,6 +15,7 @@ import io.falu.identity.IdentityVerificationResultCallback import io.falu.identity.IdentityVerificationViewModel import io.falu.identity.R import io.falu.identity.analytics.AnalyticsDisposition +import io.falu.identity.analytics.IdentityAnalyticsRequestBuilder.Companion.SCREEN_NAME_WELCOME import io.falu.identity.api.models.verification.Verification import io.falu.identity.api.models.verification.VerificationUpdateOptions import io.falu.identity.databinding.FragmentWelcomeBinding @@ -44,6 +45,8 @@ internal class WelcomeFragment( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewModel.reportTelemetry(viewModel.analyticsRequestBuilder.screenPresented(screenName = SCREEN_NAME_WELCOME)) + viewModel.observeForVerificationResults( viewLifecycleOwner, onSuccess = { onVerificationSuccessful(it) },