Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore/track analytics consent screen view and selection rates #2784 #2793

Conversation

edu-stx
Copy link
Contributor

@edu-stx edu-stx commented Nov 3, 2022

Try out this version of the Hiro Wallet - download extension builds.

Segment is always on. Segment can only be turned on, it can’t be turned off once it’s turned on. Therefore, in order to be able to capture the analytics acceptance rate (and then nothing else should the user opt out of analytics), Segment needs to be turned on as soon as the app loads. The user’s consent response is respected by modifying the behavior of the methods we use to interact with Segment: if the user accepts, they work as expected and capture analytics, otherwise, they’re converted into no-ops and calling those functions won’t capture any analytics.

Segment only captures consent page load and consent response by default. These are the only two analytics that Segment will capture by default. Should the user opt out of analytics, Segment will not capture anything further.

Users can’t manually navigate to pages other than the consent screen without having provided their consent response. Users may try to navigate to any part of the app by typing the address in the URL bar. However, given Segment is on by default, until they provide a response to the analytics consent, they will always be redirected to the consent page and aren’t allowed to view other pages or interact with the app in any way (and therefore avoid data collection).

Sentry code has been commented removed given it was disabled to avoid interfering with this PR, will be taken care of as part of #2822.

FYI @fbwoolf, using settings slice as recommended in comment.

Closes #2784

@vercel vercel bot temporarily deployed to Preview November 3, 2022 19:22 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch 2 times, most recently from 5b99d43 to fa75907 Compare November 7, 2022 14:04
@markmhendrickson markmhendrickson linked an issue Nov 7, 2022 that may be closed by this pull request
@vercel vercel bot temporarily deployed to Preview November 7, 2022 14:09 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from fa75907 to 44def92 Compare November 7, 2022 16:57
@vercel vercel bot temporarily deployed to Preview November 7, 2022 16:58 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 44def92 to 8f9bada Compare November 7, 2022 17:00
@vercel vercel bot temporarily deployed to Preview November 7, 2022 17:01 Inactive
@edu-stx edu-stx marked this pull request as ready for review November 7, 2022 17:02
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 8f9bada to 7740433 Compare November 7, 2022 17:10
@vercel vercel bot temporarily deployed to Preview November 7, 2022 17:11 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 7740433 to bc6de31 Compare November 7, 2022 17:25
@vercel vercel bot temporarily deployed to Preview November 7, 2022 17:25 Inactive
@edu-stx edu-stx requested review from fbwoolf and kyranjamie and removed request for fbwoolf November 7, 2022 17:26
src/app/pages/allow-diagnostics/allow-diagnostics.tsx Outdated Show resolved Hide resolved
src/app/pages/allow-diagnostics/allow-diagnostics.tsx Outdated Show resolved Hide resolved
src/app/routes/app-routes.tsx Outdated Show resolved Hide resolved
src/app/common/hooks/analytics/use-analytics.ts Outdated Show resolved Hide resolved
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch 2 times, most recently from be17456 to 5c5e373 Compare November 8, 2022 15:38
@vercel vercel bot temporarily deployed to Preview November 8, 2022 15:38 Inactive
src/app/store/settings/settings.slice.ts Show resolved Hide resolved
src/shared/utils/analytics.ts Show resolved Hide resolved
src/app/routes/app-routes.tsx Outdated Show resolved Hide resolved
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 5c5e373 to 03af30e Compare November 8, 2022 16:24
@vercel vercel bot temporarily deployed to Preview November 8, 2022 16:27 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 03af30e to de1da50 Compare November 8, 2022 16:31
@vercel vercel bot temporarily deployed to Preview November 8, 2022 16:32 Inactive
src/shared/utils/analytics.ts Outdated Show resolved Hide resolved
src/shared/workers/index.ts Outdated Show resolved Hide resolved
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from b2f120b to ccc82fa Compare November 10, 2022 17:23
@vercel vercel bot temporarily deployed to Preview November 10, 2022 17:26 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch 2 times, most recently from fffb8fc to 03de36e Compare November 10, 2022 17:34
@vercel vercel bot temporarily deployed to Preview November 10, 2022 17:35 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 03de36e to 0547cf0 Compare November 10, 2022 17:42
@vercel vercel bot temporarily deployed to Preview November 10, 2022 17:43 Inactive
@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from 0547cf0 to a0418c8 Compare November 10, 2022 19:05
@edu-stx
Copy link
Contributor Author

edu-stx commented Nov 10, 2022

@markmhx issues with page views not being reported correctly are now fixed, feel free to try it out.

Copy link
Collaborator

@kyranjamie kyranjamie left a comment

Choose a reason for hiding this comment

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

Nice approach Edu. Appreciate the time spent trying different solutions 👍🏼

@markmhendrickson
Copy link
Collaborator

The data is now showing up for me during testing in the Segment debugger 🙏

I did try loading another route (/buy) upon installing the build and before responding to either consent option, and the view was tracked even though the page redirected properly back to the /request_diagnostics screen.

Could we make this airtight in that this buy page view wouldn't get reported in this scenario in addition to the subsequent request-diagnostics one?

image

Copy link
Contributor

@fbwoolf fbwoolf left a comment

Choose a reason for hiding this comment

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

Nice work @edu-stx! 👍

@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from a0418c8 to f14dcf5 Compare November 11, 2022 14:20
@vercel vercel bot temporarily deployed to Preview November 11, 2022 14:20 Inactive
@edu-stx
Copy link
Contributor Author

edu-stx commented Nov 11, 2022

@kyranjamie @markmhx the page views are being tracked by this line whenever the path changes,

https://github.com/hirosystems/stacks-wallet-web/blob/8414602e1954bf1d7678be866acc9a39149a79cf/src/app/routes/app-routes.tsx#L51

Even if a user goes to /a-page-that-doesnt-exist, it will still get picked up. To make it airtight while adhering to the conventions currently in place, I've wrapped the app in a component solely dedicated to the consent screen. Looks roughly like,

function AppRoutesAfterAnalyticsConsentAnswered() {
  // All routes as they were, unchanged
}

function AppRoutes() {
  if (!hasResponded) return <AllowDiagnosticsPage />

  return <AppRoutesAfterAnalyticsConsentAnswered />
}

Copy link
Collaborator

@kyranjamie kyranjamie left a comment

Choose a reason for hiding this comment

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

Great that you've changed the page tracking events, this is an improvement. Have a search for .page( though, as in some places we still call this manually.

Comment on lines 202 to 220
export function AppRoutes() {
const hasStateRehydrated = useHasStateRehydrated();
const hasResponded = useHasUserRespondedToAnalyticsConsent();

if (!hasStateRehydrated) return <LoadingSpinner />;

if (!hasResponded) {
return (
<Routes>
<Route path={RouteUrls.RequestDiagnostics} element={<AllowDiagnosticsPage />} />
<Route path="*" element={<Navigate replace to={RouteUrls.RequestDiagnostics} />} />
</Routes>
);
}
return <AppRoutesAfterAnalyticsConsentAnswered />;
}
Copy link
Collaborator

@kyranjamie kyranjamie Nov 14, 2022

Choose a reason for hiding this comment

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

What happened to using the route guard?

If we do do it this way: Wouldn't it make more sense to flip it: creating a separate component for the RequestDiagnosticsPage, and leave the existing routes here?

if (!hasResponded) return <AppRoutesBeforeAnalyticsConsentAnswered />;

return <AllTheRoutesAsTheyWereBefore>...

The exception is the Request Diagnostics routes, so I'd make a component for that, not the rest of the entire app's routing.


More generally, if this pattern has advantages for this case, I'm okay with it. But for example, why don't we do the same for creating an account?

if (!hasCreatedAccount) {
  return <Routes><OnlyRoutesForMakingAnAccount /><Routes/>
}

It's more common in my exp. to define all the routes statically, and implement route guards to prevent navigation to restricted pages, than it is conditionally creating a route config.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great that you've changed the page tracking events, this is an improvement. Have a search for .page( though, as in some places we still call this manually.

Thank you :) Do you mean in general in the codebase or as part of this PR? Code unrelated to this feature seems out of scope. This PR has a .page() call for the analytics consent page, given the “catch all” routes’ .page() seen below is not yet loaded when the consent screen loads.

https://github.com/hirosystems/stacks-wallet-web/blob/8414602e1954bf1d7678be866acc9a39149a79cf/src/app/routes/app-routes.tsx#L51

What happened to using the route guard?

Using the route guard caused page views to still be picked up by the above before users answered the analytics consent. We would have ended up collecting any routes the users manually navigated to before they responded to the analytics consent, meaning we would not be making the data collection “airtight”, i.e. strictly contained to the analytics page & response prior to user acceptance.

If we do do it this way: Wouldn't it make more sense to flip it: creating a separate component for the RequestDiagnosticsPage, and leave the existing routes here?

This is the approach taken in an earlier commit, albeit rendering the elements directly. It seemed from an earlier discussion that we should not follow this pattern, and in any case it doesn’t work with the above catch all .page() hook.

More generally, if this pattern has advantages for this case [...]

It not so much it having advantages, as it is fulfilling the objectives at hand,

  • From the feature: strictly ensure only views and responses to consent are collected prior to acceptance
  • From earlier feedback: keep as close to the existing patterns as possible

I’m sure there are better ways of doing this, although I can’t see how we’d go about it without, for example, refactoring how we collect page views to collect only what is expected. Incidentally, the current implementation will collect not just page views, but any random string the user types in the URL.

But for example, why don't we [...]

Seems that it’s a matter of convention: what conventions do we have and follow, and to what extent do the conventions we adopt allow us to implement the features we want? In this PR, I tried my best to follow existing conventions while implementing the feature 😇

Copy link
Collaborator

@kyranjamie kyranjamie Nov 14, 2022

Choose a reason for hiding this comment

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

Sorry if this wasn't clear.

useEffect(() => void analytics.page('view', `${pathname}`), [analytics, pathname]);

This effect improves the page tracking, but in some places page tracking is handled manually, which means this addition will double log page views. As this PR introduces this behaviour, I think it should be fixed before merging. Edit: Edu pointed out this is already in dev
Example 1. Example 2. All that's required is removing these page tracking events.

The other point was just a small one on component organisation, rather than anything relating to a previous conversation.
As a developer, when I come to <AppRoutes /> I expect to see the app's routes. But now, the main responsibility of the component is handling the edge case regarding the request diagnostics page. It makes more sense to create an abstraction around the edge case, and move that to its own component, rather than the entire app's routes. Here's a clearer example:

function AppRoutesBeforeUserHasConsented() {
  return (
    <Routes>
      <Route path={RouteUrls.RequestDiagnostics} element={<AllowDiagnosticsPage />} />
      <Route path="*" element={<Navigate replace to={RouteUrls.RequestDiagnostics} />} />
    </Routes>
  );
}
export function AppRoutes() {
  const hasStateRehydrated = useHasStateRehydrated();
  const hasResponded = useHasUserRespondedToAnalyticsConsent();

  if (!hasStateRehydrated) return <LoadingSpinner />;

  if (!hasResponded) {
    return <AppRoutesBeforeUserHasConsented />
  }

  return <AllTheAppsRoutesAsComponentNameSuggests />;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll re-arrange app routes

@edu-stx edu-stx force-pushed the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch from f14dcf5 to f7142ed Compare November 14, 2022 16:08
@vercel vercel bot temporarily deployed to Preview November 14, 2022 16:08 Inactive
@edu-stx edu-stx merged commit 8f7d61d into dev Nov 14, 2022
@edu-stx edu-stx deleted the chore/Track-analytics-consent-screen-view-and-selection-rates-#2784 branch November 14, 2022 16:30
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.

Track analytics consent screen view and selection rates
4 participants