usdigitalresponse / usdr-gost

USDR-hosted grants management tools
http://grants.usdigitalresponse.org
Apache License 2.0
26 stars 20 forks source link

[GDP] Instrument key user actions #2589

Open jsandlund opened 5 months ago

jsandlund commented 5 months ago

User Story

  1. As UDSR, we'd like to track key user actions on the GDP so that we can better understand user behavior and continually improve their experience.
  2. As USDR, we'd like to set and use a standard convention for how we instrument user actions sitewide so that events are easier to maintain and lookup.

Requirements Instrument the following actions on the GDP using GA4s Custom Events: https://support.google.com/analytics/answer/12229021?hl=en

  1. "Grants.gov btn clicked": When a User clicks the primary Grants.gov CTA
  2. "Print button clicked": When a User clicks the print btn
  3. "Copy link button clicked": When a User clicks the copy link btn
  4. "assign team to grant": When a User assigns a grant by selecting an option and successfully submitting the assign grant form
  5. "remove team assignment from grant": When a User deletes a previous grant assignment by clicking the delete icon
  6. "submit team status for grant": When a User updates their Teams' Status by selecting a status and successfully submitting the status form.
  7. "remove team status for grant": When a User deletes a previous status by clicking the delete icon

Assets

  1. Event Tracking Plan: https://docs.google.com/spreadsheets/d/1blps0ddj7s_p95aNKS4-UcZEvtoVYcayrieqxQ4VI98/edit#gid=367769533

Implementation Details

Modify the GrantDetails.vue view as follows:

  1. In packages/client/src/helpers/gtag.js, create a new function gtagEvent(eventName, eventParams) that wraps a call of window.gtag('event', eventName, eventParams) when the following conditions are true:

    1. window.gtag is a function
    2. window.APP_CONFIG?.GOOGLE_TAG_ID is truthy
      • Note: This same conditional check already exists in the gtagConfig() function, which is defined in the same file.
      • The purpose of this new function is to emit a Google Analytics event with name eventName and optional parameters eventParams when GA is initialized.
      • Nice to have: When window.APP_CONFIG?.GOOGLE_ANALYTICS_DEBUG is truthy, log the event name and any parameters to the console so that it is easy for developers to check how instrumented events are being emitted, e.g.
        console.log(`Emit Google Analytics event "${eventName}" with params:`, eventParams);

        Bonus points for firing this log even when the event itself was not emitted (because GA is disabled), but indicate whether that was/wasn't the case.

  2. Make the gtagEvent() function available in the packages/client/src/views/GrantDetails.vue view view by mapping it to the view's data option.

  3. In the same GrantDetails.vue view, add @click (feel free to use different events if more appropriate) event handlers to the following elements (left side) that calls the new gtagEvent() with the corresponding event (right side):

    • "Apply on Grants.gov" button: Grants.gov btn clicked
    • "Print" button: Print btn clicked
    • "Copy" button: Copy btn clicked
  4. In the same GrantDetails.vue view file, add data-dd-action-name attributes to the following elements (left side) with the corresponding attribute values (right side):

    • "Print" button: Print btn
    • "Copy" button: Copy btn
    • Note: do not add "clicked" to these values
  5. Update the following GrantDetails.vue methods to call gtagEvent() and datadogRum.addAction() as-follows:

    • assignAgenciesToGrant()
      • Event name: assign team to grant
      • Params: (none)
    • unassignAgenciesToGrant()
      • Event name: remove team assignment from grant
      • Params: (none)
    • markGrantAsInterested(), within the this.selectedInterestedCode !== null conditional block
      • Event name: submit team status for grant
      • Params: { status_name: statusName }, where statusName is derived by filtering the this.interestedOptions array for the entry with .id matching this.selectedInterestedCode (see code sample below)
    • unmarkGrantAsInterested()
      • Event name: remove team status for grant
      • Params: (none)

Relevant code samples

jsandlund commented 5 months ago

FYI @ClaireValdivia @TylerHendrickson Backlogged this ticket for consideration.

jsandlund commented 5 months ago

Creating a thread on Question #1:

Is there an existing instrumentation convention that should be used? If not, a couple fwiw thoughts on approaches:

  1. Specific events: 1 event per key action ("Copy link btn clicked", "Print btn lnk clicked")
  2. Generalized events w/ rich properties: 1 event per interaction type, e.g. "Button Clicked" w/ a "button_name" property)

I lean towards 2. I think the benefit of reducing the number of distinct events > the con of end users needing to filter events by properties. But just a thought :).

jsandlund commented 5 months ago

Notes from weekly:

DD advantages of GA

  1. Easier to instrument specific client-side events -- DD uses html attributes vs. GA requires calling its gtag API
  2. Already set up

DD disadvantages:

  1. Distinct events approach (one event per action) creates more events; may not scale as well -- Given relatively low # of clients, may not be a significant issue though.
  2. DD may have a lower ease of use. If so, may reduce adoption & usage -- However, DD is improving their product analytics capabilities, w/ easier charting, etc.

DD cost not a factor, acceptably low. Benefit to consolidating tooling.

Next steps:

  1. What P0 questions are most important to answer? Recurring (e.g. MAU) vs. Ad hoc questions (page-level behavior to inform a design decision)
  2. Based on #1, are they answerable in both tools?
  3. Based on #1, are there major usability concerns w/ GA or DD that may limit adoption and usage?
ClaireValdivia commented 5 months ago

Next steps - Ty to add implementation steps to this issue for consistency in execution

jsandlund commented 5 months ago

@TylerHendrickson I updated the requirements based on the Tracking plan. Added definitions to clarify when the events should emit. Lmk if any of them need clarified. I didn't add custom properties to any of the events (e.g. "status_name", etc.). I think that's OK for v1: first see feature usage frequency (n times per User) and breadth (% of Users who use). If high, can then layer in more properties.

TylerHendrickson commented 4 months ago

@ClaireValdivia @jsandlund Added implementation details for the ticket and spreadsheet in its current state. However, before this is moved to "Ready", I'd like to resolve outstanding comments on the tracking spreadsheet.

Also should note: all of these events are currently being captured in Datadog RUM. As noted in some of the spreadsheet comments, the event names diverge slightly.

Posterity edit: resolved!