Skip to content

Commit

Permalink
Apply AnalyticsEventsEnhancer to more events
Browse files Browse the repository at this point in the history
Update AnalyticsEventsEnhancer so that it augments any event where the _method name_ starts with `^idv_` UNLESS it has been told not to.

changelog: Internal, Analytics, Add additional data to IdV analytics events by default.
  • Loading branch information
matthinz committed Mar 18, 2024
1 parent fd41a4a commit 6e0d041
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 58 deletions.
162 changes: 124 additions & 38 deletions app/services/idv/analytics_events_enhancer.rb
Original file line number Diff line number Diff line change
@@ -1,48 +1,134 @@
module Idv
module AnalyticsEventsEnhancer
DECORATED_METHODS = %i[
idv_cancellation_confirmed
idv_cancellation_go_back
idv_cancellation_visited
idv_forgot_password
idv_forgot_password_confirmed
idv_final
idv_gpo_address_letter_enqueued
idv_gpo_address_letter_requested
idv_in_person_ready_to_verify_visit
idv_letter_enqueued_visit
idv_personal_key_acknowledgment_toggled
idv_personal_key_downloaded
idv_personal_key_submitted
idv_personal_key_visited
idv_phone_confirmation_form_submitted
idv_phone_confirmation_otp_rate_limit_attempts
idv_phone_confirmation_otp_rate_limit_locked_out
idv_phone_confirmation_otp_rate_limit_sends
idv_phone_confirmation_otp_resent
idv_phone_confirmation_otp_sent
idv_phone_confirmation_otp_submitted
idv_phone_confirmation_otp_visit
idv_phone_confirmation_vendor_submitted
idv_phone_error_visited
idv_phone_of_record_visited
idv_phone_otp_delivery_selection_visit
idv_phone_otp_delivery_selection_submitted
idv_proofing_resolution_result_missing
idv_enter_password_submitted
idv_enter_password_visited
idv_please_call_visited
idv_start_over
IGNORED_METHODS = %i[
idv_acuant_sdk_loaded
idv_address_submitted
idv_address_visit
idv_back_image_added
idv_back_image_clicked
idv_barcode_warning_continue_clicked
idv_barcode_warning_retake_photos_clicked
idv_capture_troubleshooting_dismissed
idv_consent_checkbox_toggled
idv_doc_auth_agreement_submitted
idv_doc_auth_agreement_visited
idv_doc_auth_capture_complete_visited
idv_doc_auth_document_capture_submitted
idv_doc_auth_document_capture_visited
idv_doc_auth_exception_visited
idv_doc_auth_failed_image_resubmitted
idv_doc_auth_how_to_verify_submitted
idv_doc_auth_how_to_verify_visited
idv_doc_auth_hybrid_handoff_submitted
idv_doc_auth_hybrid_handoff_visited
idv_doc_auth_link_sent_submitted
idv_doc_auth_link_sent_visited
idv_doc_auth_randomizer_defaulted
idv_doc_auth_redo_ssn_submitted
idv_doc_auth_ssn_submitted
idv_doc_auth_ssn_visited
idv_doc_auth_submitted_image_upload_form
idv_doc_auth_submitted_image_upload_vendor
idv_doc_auth_submitted_pii_validation
idv_doc_auth_verify_proofing_results
idv_doc_auth_verify_submitted
idv_doc_auth_verify_visited
idv_doc_auth_warning_visited
idv_doc_auth_welcome_submitted
idv_doc_auth_welcome_visited
idv_exit_optional_questions
idv_front_image_added
idv_front_image_clicked
idv_gpo_confirm_start_over_before_letter_visited
idv_gpo_confirm_start_over_visited
idv_gpo_expired
idv_gpo_reminder_email_sent
idv_image_capture_failed
idv_in_person_email_reminder_job_email_initiated
idv_in_person_email_reminder_job_exception
idv_in_person_location_submitted
idv_in_person_location_visited
idv_in_person_locations_request_failure
idv_in_person_locations_searched
idv_in_person_prepare_submitted
idv_in_person_prepare_visited
idv_in_person_proofing_address_visited
idv_in_person_proofing_cancel_update_state_id
idv_in_person_proofing_enrollments_ready_for_status_check_job_completed
idv_in_person_proofing_enrollments_ready_for_status_check_job_ingestion_error
idv_in_person_proofing_enrollments_ready_for_status_check_job_started
idv_in_person_proofing_nontransliterable_characters_submitted
idv_in_person_proofing_redo_state_id_submitted
idv_in_person_proofing_residential_address_submitted
idv_in_person_proofing_state_id_submitted
idv_in_person_proofing_state_id_visited
idv_in_person_ready_to_verify_sp_link_clicked
idv_in_person_ready_to_verify_what_to_bring_link_clicked
idv_in_person_send_proofing_notification_attempted
idv_in_person_send_proofing_notification_job_completed
idv_in_person_send_proofing_notification_job_exception
idv_in_person_send_proofing_notification_job_skipped
idv_in_person_send_proofing_notification_job_started
idv_in_person_switch_back_submitted
idv_in_person_switch_back_visited
idv_in_person_usps_proofing_enrollment_code_email_received
idv_in_person_usps_proofing_results_job_completed
idv_in_person_usps_proofing_results_job_deadline_passed_email_exception
idv_in_person_usps_proofing_results_job_deadline_passed_email_initiated
idv_in_person_usps_proofing_results_job_email_initiated
idv_in_person_usps_proofing_results_job_enrollment_incomplete
idv_in_person_usps_proofing_results_job_enrollment_updated
idv_in_person_usps_proofing_results_job_exception
idv_in_person_usps_proofing_results_job_please_call_email_initiated
idv_in_person_usps_proofing_results_job_started
idv_in_person_usps_proofing_results_job_unexpected_response
idv_in_person_usps_proofing_results_job_user_sent_to_fraud_review
idv_in_person_usps_request_enroll_exception
idv_intro_visit
idv_ipp_deactivated_for_never_visiting_post_office
idv_link_sent_capture_doc_polling_complete
idv_link_sent_capture_doc_polling_started
idv_mail_only_warning_visited
idv_mobile_device_and_camera_check
idv_native_camera_forced
idv_not_verified_visited
idv_phone_use_different
idv_request_letter_visited
idv_sdk_selfie_image_capture_closed_without_photo
idv_sdk_selfie_image_capture_failed
idv_sdk_selfie_image_capture_opened
idv_selfie_image_added
idv_session_error_visited
idv_usps_auth_token_refresh_job_completed
idv_usps_auth_token_refresh_job_network_error
idv_usps_auth_token_refresh_job_started
idv_verify_by_mail_enter_code_submitted
idv_verify_by_mail_enter_code_visited
idv_verify_in_person_troubleshooting_option_clicked
idv_warning_action_triggered
idv_warning_shown
].freeze

DECORATED_METHODS.each do |method_name|
define_method(method_name) do |**kwargs|
super(**kwargs, **common_analytics_attributes)
def self.included(_mod)
raise 'this mixin is intended to be prepended, not included'
end

def self.prepended(mod)
mod.instance_methods.each do |method_name|
if should_enhance_method?(method_name)
mod.define_method method_name do |**kwargs|
super(**kwargs, **common_analytics_attributes)
end
end
end
end

def self.included(_mod)
raise 'this mixin is intended to be prepended, not included'
def self.should_enhance_method?(method_name)
return false unless /^idv_/.match?(method_name)

return false if IGNORED_METHODS.include?(method_name)

true
end

private
Expand Down
48 changes: 28 additions & 20 deletions spec/services/idv/analytics_events_enhancer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,47 @@
include AnalyticsEvents
prepend Idv::AnalyticsEventsEnhancer

def idv_final(**kwargs)
@called_kwargs = kwargs
end

attr_reader :user, :called_kwargs
attr_reader :called_kwargs

def initialize(user:)
@user = user
end

def track_event(_event, **kwargs)
@called_kwargs = kwargs
end
end
end
let(:analytics) { analytics_class.new(user: user) }

it 'includes decorated methods' do
expect(analytics.methods).to include(*described_class::DECORATED_METHODS)
expect(
analytics.methods.
intersection(described_class::DECORATED_METHODS).
map { |method| analytics.method(method).source_location.first }.
uniq,
).to eq([Idv::AnalyticsEventsEnhancer.const_source_location(:DECORATED_METHODS).first])
end
let(:test_method) { :idv_doc_auth_welcome_visited }

it 'enhances idv_ methods by default, but ignores those in IGNORED_METHODS' do
enhancer_source_file = described_class.const_source_location(:IGNORED_METHODS).first

idv_methods = analytics_class.instance_methods.filter { |method| /^idv_/.match?(method) }

it 'calls analytics method with original attributes' do
analytics.idv_final(extra: true)
expect(analytics.called_kwargs).to eq(extra: true)
idv_methods.each do |method_name|
method = analytics_class.instance_method(method_name)
method_source_file = method.source_location.first

should_be_ignored = described_class.const_get(:IGNORED_METHODS).include?(method_name)
if should_be_ignored
expect(method_source_file).not_to eql(enhancer_source_file),
"#{method_name} should not be enhanced"
else
expect(
method_source_file,
).to eql(enhancer_source_file), "#{method_name} should be enhanced"
end
end
end

context 'with anonymous analytics user' do
let(:user) { AnonymousUser.new }

it 'calls analytics method with original attributes' do
analytics.idv_final(extra: true)
analytics.send(test_method, extra: true)

expect(analytics.called_kwargs).to eq(extra: true)
end
Expand All @@ -54,7 +62,7 @@ def initialize(user:)

context 'without proofing component' do
it 'calls analytics method with original attributes' do
analytics.idv_final(extra: true)
analytics.send(test_method, extra: true)

expect(analytics.called_kwargs).to match(
extra: true,
Expand All @@ -68,7 +76,7 @@ def initialize(user:)
end

it 'calls analytics method with original attributes and proofing_components' do
analytics.idv_final(extra: true)
analytics.send(test_method, extra: true)

expect(analytics.called_kwargs).to match(
extra: true,
Expand Down

0 comments on commit 6e0d041

Please sign in to comment.