diff --git a/app/controllers/frontend_log_controller.rb b/app/controllers/frontend_log_controller.rb index 11efab30328..fbf416618a0 100644 --- a/app/controllers/frontend_log_controller.rb +++ b/app/controllers/frontend_log_controller.rb @@ -53,6 +53,7 @@ class FrontendLogController < ApplicationController idv_sdk_selfie_image_capture_closed_without_photo idv_sdk_selfie_image_capture_failed idv_sdk_selfie_image_capture_opened + idv_sdk_selfie_image_re_taken idv_selfie_image_added idv_selfie_image_clicked phone_input_country_changed diff --git a/app/javascript/packages/document-capture/components/acuant-capture.tsx b/app/javascript/packages/document-capture/components/acuant-capture.tsx index b9e6fdac223..1e2c3e7b7e5 100644 --- a/app/javascript/packages/document-capture/components/acuant-capture.tsx +++ b/app/javascript/packages/document-capture/components/acuant-capture.tsx @@ -553,7 +553,6 @@ function AcuantCapture( trackEvent('idv_selfie_image_added', { captureAttempts, selfie_attempts: selfieAttempts.current, - extra: { here: true }, }); onChangeAndResetError(image, analyticsPayload); @@ -586,6 +585,13 @@ function AcuantCapture( setIsCapturingEnvironment(false); } + function onSelfieRetaken() { + trackEvent('idv_sdk_selfie_image_re_taken', { + captureAttempts, + selfie_attempts: selfieAttempts.current, + }); + } + function onAcuantImageCaptureSuccess(nextCapture: AcuantSuccessResponse) { const { image, dpi, moire, glare, sharpness, cardType } = nextCapture; @@ -732,6 +738,7 @@ function AcuantCapture( onImageCaptureClose={onSelfieCaptureClosed} onImageCaptureFeedback={onImageCaptureFeedback} onSelfieTaken={onSelfieTaken} + onSelfieRetaken={onSelfieRetaken} > void; + /** + * Selfie captured by user initiated retake + */ + onSelfieRetaken: () => void; /** * React children node */ @@ -84,6 +88,7 @@ function AcuantSelfieCamera({ onImageCaptureClose = () => {}, onImageCaptureFeedback = () => {}, onSelfieTaken = () => {}, + onSelfieRetaken = () => {}, children, }: AcuantSelfieCameraContextProps) { const { isReady, setIsActive } = useContext(AcuantContext); @@ -119,6 +124,7 @@ function AcuantSelfieCamera({ }, onPhotoRetake: () => { // Triggered when retake button is tapped + onSelfieRetaken(); }, onCaptured: (base64Image) => { // Triggered when accept button is tapped diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 737aabe12d8..aa189336762 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -3280,6 +3280,25 @@ def idv_sdk_selfie_image_capture_opened( **extra, ) end + + # User opened the SDK to take a selfie + # @param [String] acuant_version + # @param [Integer] captureAttempts number of attempts to capture / upload an image + # @param [Integer] selfie_attempts number of selfie captured by SDK + def idv_sdk_selfie_image_re_taken( + acuant_version:, + captureAttempts: nil, + selfie_attempts: nil, + **extra + ) + track_event( + :idv_sdk_selfie_image_re_taken, + acuant_version: acuant_version, + captureAttempts: captureAttempts, + selfie_attempts: selfie_attempts, + **extra, + ) + end # rubocop:enable Naming/VariableName,Naming/MethodParameterName # User took a selfie image with the SDK, or uploaded a selfie using the file picker diff --git a/spec/javascript/packages/document-capture/components/acuant-capture-spec.jsx b/spec/javascript/packages/document-capture/components/acuant-capture-spec.jsx index 7cb5236f397..0fbb10acf3d 100644 --- a/spec/javascript/packages/document-capture/components/acuant-capture-spec.jsx +++ b/spec/javascript/packages/document-capture/components/acuant-capture-spec.jsx @@ -1222,6 +1222,30 @@ describe('document-capture/components/acuant-capture', () => { 'idv_selfie_image_added', sinon.match({ captureAttempts: sinon.match.number, + selfie_attempts: sinon.match.number, + }), + ); + }); + + it('calls trackEvent from onSelfieRetake', () => { + // In real use the `start` method opens the Acuant SDK full screen selfie capture window. + // Because we can't do that in test (AcuantSDK does not allow), this doesn't attempt to load + // the SDK. Instead, it simply calls the callback that happens when a photo is captured. + // This allows us to test everything about that callback -except- the Acuant SDK parts. + initialize({ + selfieStart: sinon.stub().callsFake((callbacks) => { + callbacks.onPhotoTaken(); + callbacks.onPhotoRetake(); + }), + }); + + expect(trackEvent).to.be.calledWith('idv_selfie_image_clicked'); + expect(trackEvent).to.be.calledWith('IdV: Acuant SDK loaded'); + expect(trackEvent).to.be.calledWith( + 'idv_sdk_selfie_image_re_taken', + sinon.match({ + captureAttempts: sinon.match.number, + selfie_attempts: sinon.match.number, }), ); });