feat: Guided Tours Completion Metrics#2412
Conversation
🎩 PreviewA preview build has been created at: |
2cfbe6e to
586e87d
Compare
61e99a7 to
e5de95e
Compare
586e87d to
6bffb2c
Compare
e5de95e to
9551233
Compare
6bffb2c to
18c2dd3
Compare
9551233 to
1e6793c
Compare
18c2dd3 to
0e1b241
Compare
1e6793c to
f89c2a4
Compare
0e1b241 to
7f552ac
Compare
f89c2a4 to
c487762
Compare
3b6725f to
cf9670d
Compare
46e18c1 to
e3b0dd6
Compare
72758f7 to
076c6dd
Compare
076c6dd to
9195f97
Compare
96f0bf2 to
1632bef
Compare
9195f97 to
4fd1034
Compare
1632bef to
19bac1e
Compare
4fd1034 to
c1d1d2e
Compare
19bac1e to
0d1cd7a
Compare
c1d1d2e to
8e73648
Compare
0d1cd7a to
3f17435
Compare
8e73648 to
4f37373
Compare
4f4db72 to
dd06708
Compare
09b89a1 to
db0230b
Compare
dd06708 to
893f173
Compare
db0230b to
edb2a50
Compare
745d62c to
893a662
Compare
df55905 to
3ae4c3b
Compare
21b6c60 to
4e5942b
Compare
3ae4c3b to
d5e8d45
Compare
4e5942b to
3bfbe19
Compare
| }, | ||
| }); | ||
|
|
||
| return (tourId: string): RecordedCompletion => { |
There was a problem hiding this comment.
🤖 This is an AI-generated code review comment.
useRecordTourCompletion returns completionCount and previouslyCompleted from the current React Query cache before the mutation fetches and merges the authoritative settings map. When the cache is cold, stale, or still loading, TourTelemetryBridge immediately emits learning_hub.tours.completed with completion_count: 1 and previously_completed: false even if the server record already has prior completions. The PATCH later writes the correct merged count, but the analytics event for this completion is already wrong.
Suggestion: Make recording return the authoritative result used by the mutation (for example, expose an async mutateAsync/recordCompletion that resolves after ensureQueryData, then track completed from that result), or synchronously seed/update the cache before building the analytics payload so the emitted metrics match the persisted value.
Rule: tangle-ui-review: General quality / proper server-state handling for user-facing analytics

Description
Tours can now be marked as completed and restarted, and we capture progression telemetry so we can see how tours are used and where people bounce off.
Completion state is persisted per user on the backend via
/api/users/me/settings(key:completed_tours) — read with TanStack Query and updated with a read-modify-write PATCH, so it survives across sessions/devices and sits alongside any other user settings without overwriting them. There is no local-storage layer: when no backend is available (e.g. offline / GitHub Pages) completion state simply doesn't surface, which is acceptable for this low-stakes feature and can be revisited later.We deliberately do not resume partially-finished tours — restarting always begins from the first step — so no in-progress state is surfaced.
User-facing
Telemetry (analytics events, independent of the settings store)
learning_hub.tours.start— now carriesis_restartto distinguish redos from first runs.learning_hub.tours.step_viewed— fired once per step reached (step_index,step_count,interaction); gives a step-by-step drop-off funnel.learning_hub.tours.completed— on reaching the final step (step_count,completion_count,previously_completed,duration_ms).learning_hub.tours.exited— on leaving before completion (furthest_step,percent_complete,duration_ms,previously_completed) — the "bounce" signal.Together these cover issue 640's item 2 (how many started/completed, and how far users get before exiting).
Related Issue and Pull requests
Closes https://github.com/Shopify/oasis-frontend/issues/640
Note
Cross-device persistence depends on the backend
/api/users/me/settingsroute doing a key-level merge of thesettingsdict (confirmed) socompleted_toursis appended alongside other keys rather than replacing them.Type of Change
Checklist
Screenshots (if applicable)
Test Instructions
/api/users/me/settings). In DevTools, theGET .../api/users/me/settings?setting_names=completed_toursreturns thecompleted_toursmap; completing a tour fires aPATCHthat includes the full map undersettings.completed_tours.learning_hub.tours.exitedevent fires withfurthest_step. Walk a tour to the end →learning_hub.tours.completedfires; each step emitsstep_viewed.Additional Comments
completed_tourswrite is last-write-wins against the cached map within a session — a completion added by another tab/device between our GET and PATCH could be missed. Negligible here; true per-entry safety would require the backend to deep-mergecompleted_tours.