Skip to content

feat: explore dash merchant search event tracking - #917

Merged
HashEngineering merged 8 commits into
masterfrom
feature-explore-dash-firebase-merchant-search
Mar 23, 2022
Merged

feat: explore dash merchant search event tracking#917
HashEngineering merged 8 commits into
masterfrom
feature-explore-dash-firebase-merchant-search

Conversation

@ClaudeHangui

@ClaudeHangui ClaudeHangui commented Mar 18, 2022

Copy link
Copy Markdown
Contributor

Use Firebase to track user interactions related to explore dash for merchants

Issue being fixed or feature implemented

Related PR's and Dependencies

Screenshots / Videos

How Has This Been Tested?

  • QA (Mobile Team)

Checklist:

  • I have performed a self-review of my own code and added comments where necessary
  • I have added or updated relevant unit/integration/functional/e2e tests

@ClaudeHangui ClaudeHangui changed the title feat: explore dash merchant search feat: explore dash merchant search event tracking Mar 18, 2022
)
}

map.setOnCameraMoveStartedListener { reason ->

@ClaudeHangui ClaudeHangui Mar 18, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are various reasons that can cause the camera to be in motion in a map: however our tracking only focuses on the Camera motion initiated in response to user gestures on the map including pinch to zoom and pan gestures. All other causes/reasons initiated or not by the user are to be ignored for the tracking

viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> {
viewModel.zoomLevelChangeCallback.call()
}
viewModel.hasCameraCenterChanged(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if a pan gesture was made: we rely on the coordinates (position) of the camera in the center of the map

val bounds = map.projection.visibleRegion.latLngBounds
if (cameraMovementReason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE){
when {
viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if the user zoomed (in/out) the map

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This entire when can be moved to the ViewModel. You're calling a viewModel check and then calling a viewModel event if the check is satisfied. Just call a triggerEventIfSatisfied(param, param) method once.
  2. This entire check is needed to trigger an event that is then observed from another fragment that logs the event. I don't quite get why can't you either
    • Log it from this fragment
    • Log it from the viewModel

@Syn-McJ Syn-McJ left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ClaudeHangui there are some problems with events being passed around from one fragment to another for no reason. This can be simplified greatly.

val bounds = map.projection.visibleRegion.latLngBounds
if (cameraMovementReason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE){
when {
viewModel.hasZoomLevelChanged(previousZoomLevel, map.cameraPosition.zoom) -> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This entire when can be moved to the ViewModel. You're calling a viewModel check and then calling a viewModel event if the check is satisfied. Just call a triggerEventIfSatisfied(param, param) method once.
  2. This entire check is needed to trigger an event that is then observed from another fragment that logs the event. I don't quite get why can't you either
    • Log it from this fragment
    • Log it from the viewModel

import androidx.lifecycle.*
import androidx.paging.*
import androidx.paging.PagingData
import com.google.android.gms.maps.model.LatLng

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The viewModel should not reference LatLng since it's implementation-dependent and we're working with an interface in case of UserLocationState. If the implementation of UserLocationState changed, you'll have to change a lot of related code in the viewModel as well. Please use GeoBounds instead.

analyticsService.logEvent(AnalyticsConstants.ExploreDash.ZOOM_MERCHANT_MAP, bundleOf())
}
}
viewModel.cameraCenterChangeCallback.observe(viewLifecycleOwner){

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SearchFragment doesn't have to know anything about the map, I don't get why this is here.

@ClaudeHangui

ClaudeHangui commented Mar 19, 2022

Copy link
Copy Markdown
Contributor Author

@Syn-McJ there was actually some reason for me handling the tracking of some events in SearchFragment: I originally had those events in the ExploreMapFragment but I realised that we are to implement these same events for the ATM Search as well (in another story), and since the SearchFragment is aware of the ExploreTopic I thought it was ideal for it to handle all the map-related trackings. Guess it was the wrong choice. Thanks for the feedback !

@Syn-McJ

Syn-McJ commented Mar 19, 2022

Copy link
Copy Markdown
Member

@ClaudeHangui I see, well there is no reason not to log events from the ViewModel - in fact, I would prefer not doing injections into fragments at all. But not all user interactions go into the ViewModel and so it might not be always convenient.

- update ExploreViewModelTest.kt to handle injected dependency AnalyticsService
map.cameraPosition.zoom
)
viewModel.previousZoomLevel = map.cameraPosition.zoom
viewModel.previousCameraGeoBounds = getGeoBounds()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using searchBounds in our triggerPanAndZoomEvents() gives us a NPE, I'm not sure I understand why; so I had to create another property to hold the current geobounds. Moreover, it appears this searchBounds var is no longer used in the ExploreMapFragment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ClaudeHangui if you pass the map instance into getGeoBounds, you can make the return value non-nullable. Then you won't have to accept nullable GeoBounds into the triggerPanAndZoomEvents. Then you won't have to use the !! operator on it down the line.
previousCameraGeoBounds also either shouldn't be nullable or shouldn't be unpacked with the !! operator - it's better to make use of kotlins null-safety features when you can.

- initialize previousCameraGeoBounds var with non-nullable value

@Syn-McJ Syn-McJ left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great

Comment on lines +105 to +118
const val WHERE_TO_SPEND = "portal_where_to_spend"
const val PORTAL_ATM = "portal_atm"
const val LEARN_MORE = "info_learn_more"
const val CONTINUE = "info_continue"
const val ONLINE_MERCHANTS = "online_merchants"
const val NEARBY_MERCHANTS = "nearby_merchants"
const val ALL_MERCHANTS = "all_merchants"
const val FILTER_MERCHANTS_TOP = "filter_merchants_top"
const val FILTER_MERCHANTS_BOTTOM = "filter_merchants_bottom"
const val SELECT_MERCHANT_LOCATION = "select_merchant_location"
const val SELECT_MERCHANT_MARKER = "select_merchant_marker"
const val INFO_EXPLORE_MERCHANT = "info_search"
const val PAN_MERCHANT_MAP = "pan_merchant_map"
const val ZOOM_MERCHANT_MAP = "zoom_merchant_map"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as #915, there should be a prefix, otherwise within the list of events, some explore dash events are at A and others at Z.

@HashEngineering HashEngineering left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add prefix to event names.

@HashEngineering HashEngineering left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent work

@HashEngineering
HashEngineering merged commit d55c432 into master Mar 23, 2022
@HashEngineering
HashEngineering deleted the feature-explore-dash-firebase-merchant-search branch July 20, 2022 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants