feat(hutch): auto-save the first article for new signups#943
feat(hutch): auto-save the first article for new signups#943FagnerMartinsBrack wants to merge 1 commit into
Conversation
|
@claude Review this PR. Use your Read tool to read the local file Context
|
|
Claude finished @FagnerMartinsBrack's task in 9m 58s —— View job Reviewing PR #943 — first-article auto-save for new signups
Verdict: 0 High · 0 Medium. The change is well-constructed and mirrors the existing
Detailed review posted below by the automation. A few low-priority notes included there. Note: I could not execute the test suite here — the |
High Priority Issues (Must Fix)None found. I traced the complete runtime path (anonymous
Medium Priority IssuesNone found. Test coverage is comprehensive: unit tests for the pure resolver (return-wins, fallback, autosave, utm marker, and tampered Low Priority Suggestions1. The
|
|
@claude Resolve conflicts. Use your Read tool to read the local file Context
|
|
Claude finished @FagnerMartinsBrack's task in 20m 42s —— View job ✅ Merge conflicts resolved
Branch is now a clean descendant of the latest What conflictedOne file: Root cause: Resolution: kept the PR's new imports (
Second rebase (main advanced mid-fix)While resolving, VerificationFull
|
ef5975f to
3db3260
Compare
3db3260 to
687a445
Compare
|
@claude Review this PR. Use your Read tool to read the local file Context
|
|
Claude finished @FagnerMartinsBrack's task in 8m 4s —— View job Reviewing PR #943 — first-article auto-save for new signups
Verdict: 0 High · 0 Medium. Re-reviewed at the rebased tip (
Three low-priority notes in the detailed review below (Apple state-cookie size growth, the end-to-end persistence test boundary, and the Note: I relied on static analysis + full runtime trace rather than re-running the suite — the conflict-fixer already ran |
High Priority Issues (Must Fix)None found. I traced the complete runtime chain at the rebased tip (
Medium Priority IssuesNone found. CLAUDE.md conventions are respected: named-param objects ( Low Priority Suggestions1. Tunneling the article URL grows the Apple
|
Only ~4 of 35 new users per month read anything, and 23 of 34 signups arrive without a pending save (they clicked a nav/homepage signup CTA, not "Save on the reader"). A new user who lands on an empty queue has nothing to do; one whose queue already holds the article that brought them has an immediate reason to come back. On an anonymous /view open (behind the same isbot gate as view_opened), set a 2h httpOnly hutch_lastview cookie with the article URL. On signup success, when the redirect would default to /queue (no explicit ?return=) and the cookie is present and passes validateSaveableUrl, redirect to /queue?url=<article>&utm_source=signup-autosave so the existing auto-submit save form drops the first article into the new queue. A shared resolvePostSignupRedirect helper keeps the three signup paths (email, Google, Apple) consistent; Apple tunnels the URL through its signed state because its cross-site form_post callback drops the Lax cookie. Cookie is cleared on consume and on logout; an explicit ?return= (the /save round-trip) always wins so nothing double-saves. Claude-Session: https://claude.ai/code/session_01En2uUiiwQoRQKWenCnkPi9
687a445 to
d7a8928
Compare
|
@claude Review this PR. Use your Read tool to read the local file Context
|
|
Claude finished @FagnerMartinsBrack's task in 6m 27s —— View job Reviewing PR #943 — first-article auto-save for new signups
Verdict: 0 High · 0 Medium. Reviewed at the squashed tip (
CLAUDE.md conventions are respected (no |
High Priority Issues (Must Fix)None found. I traced the complete runtime chain at the squashed tip (
Medium Priority IssuesNone found. CLAUDE.md conventions are respected: named-param objects ( Low Priority Suggestions1. Tunneling the article URL grows the Apple
|
First-article auto-save for new signups
Hypothesis. A new user whose queue already contains the article that brought them to Readplace is far likelier to activate (read something) than one who lands on an empty queue. If we quietly save that article at signup, the queue is non-empty on first sight and the "there's nothing here" cold-start is gone.
Evidence (production). Only 4 of 35 new users ever read anything. 23 of 34 signups arrive without a pending save — they clicked a nav/homepage "Sign up" CTA, not the reader's "Save to My Queue" button — so the existing pending-save round-trip (which already carries a held save through signup) never fires for them. Those 23 are exactly the cohort this change targets: they were reading an article on
/viewimmediately before signing up, but nothing captured it.What this changes.
/viewopen, set a short-lived httpOnlyhutch_lastviewcookie (2h, SameSite=Lax, Secure per origin) holding the validated article URL. It sits behind the sameisbotgate that emits the existingview_openedevent, so crawlers and prefetches never set it, and authenticated viewers don't either./queue(no explicit?return=) and a validhutch_lastviewcookie is present, redirect to/queue?url=<article>&utm_source=signup-autosaveinstead. The existing/queue?url=…auto-submit save form then saves the article into the brand-new queue — reusing the stub-save + async-enrich pipeline, so the card appears immediately and fills in.resolvePostSignupRedirect({ returnUrl, lastViewUrl })is consulted at all three sites so they can't drift. It never auto-saves when an explicit?return=is present (the/saveround-trip already saves in that case — no double-save) or when the cookie is absent/tampered (URL re-validated with the samevalidateSaveableUrlused everywhere else).POST /logout. For Apple's cross-siteform_postcallback (which drops first-party Lax cookies) the URL is tunneled inside the existing HMAC-signedstate, exactly likependingSaveIdalready is.Estimated result. The 23/34 no-pending-save signups start with a 1-article queue instead of an empty one. If even a fraction of that cold-start friction is what suppresses the current 4/35 (~11%) read rate, moving first-article-in-queue to ~100% of eligible signups should lift first-week activation meaningfully. We'll read the actual lift from the funnel below rather than guess a number.
How to measure (CloudWatch Logs Insights, hutch log group
/aws/lambda/hutch-handler). No new analytics event is added — attribution rides the existingpageviewstream via theutm_source=signup-autosavemarker on the post-signup/queueload (the save form's action is a fixed internal-tracking link, so the marker lands on the pageview, not onview_save_intent; each such pageview is 1:1 with an autosave trigger and joins to the resulting save byvisitor_id).To confirm each autosave actually persisted, join the marker pageview to the follow-on save on the same visitor:
Activation lift is then the read-rate (
event = "article_read") among thesignup-autosavevisitor_idcohort vs. the historical 4/35 baseline.Analytics note. This change introduces no new analytics event and no new dashboard widget, so the analytics-dashboard widget-count test is intentionally untouched. (If a reviewer prefers a dedicated
first_article_autosavedevent so the metric doesn't lean on autm_sourcestring, that would add oneANALYTICS_EVENTSentry and require bumping the dashboard widget-count assertion — called out here so the trade-off is explicit.)https://claude.ai/code/session_01En2uUiiwQoRQKWenCnkPi9