feat(onboarding): invite 3 friends, get free Plus funnel step#6366
Draft
tsahimatsliah wants to merge 1 commit into
Draft
feat(onboarding): invite 3 friends, get free Plus funnel step#6366tsahimatsliah wants to merge 1 commit into
tsahimatsliah wants to merge 1 commit into
Conversation
Adds a FunnelStepType.InviteFriends onboarding step that fires referral
intent at the highest-motivation moment: invite friends via the generic
referral campaign, with a 0/3 progress indicator from referredUsersCount
and a confetti celebration when the target is reached. Skip is always
available, the reward copy ({reward} placeholder, default "1 month") is
A/B-able straight from the funnel JSON, and the whole step is gated
behind the new onboarding_invite_reward flag (default false).
Frontend-only: the step needs the backend funnel JSON to include it and
a backend Plus-grant mechanism to award the reward; no Plus state is
ever set client-side.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A new onboarding funnel step — "Invite 3 friends, get 1 month of Plus on us" — that fires referral intent at the highest-motivation moment of the funnel. Part of the sharing-visibility initiative (PR 20), based on PR #6343.
FunnelStepType.InviteFriends('inviteFriends') +FunnelStepInviteFriendstyped step, registered inFunnelStepper'sstepComponentMap.useReferralCampaign(ReferralCampaignKey.Generic),InviteLinkInput,SocialShareList(native share sheet feature-detected on mobile viauseShareOrCopyLink), and the existingGivebackConfettiBurstfor the 3/3 celebration.0/3 friends joined) readsreferredUsersCount; reaching the target swaps to a celebratory reveal (confetti + headline) with a Continue CTA.skiptransition; onboarding is never hard-gated on inviting.{count}/{reward}placeholders (default "1 month"), so the 1-month vs 3-months arms are A/B-able from the funnel JSON alone — no frontend change needed.FunnelTargetIdvalues (invite friends,invite friends copy,invite friends share,invite friends skip) on the tracked elements, plus the standard transition events carrying{ referredUsersCount, targetReached, invited }details. ExistingLogEvent.CopyReferralLink/LogEvent.InviteReferralfire withTargetId.Onboarding(nolog.tschanges needed).Flag
onboarding_invite_reward(featureOnboardingInviteReward), defaultfalse. Evaluated viauseConditionalFeaturewithshouldEvaluateonly when a logged-in user mounts a funnel containing the step, so enrollment matches exposure. Intentionally not gated onuseSharingVisibility()— this is an onboarding experiment with its own lifecycle. Flag off (or step absent from the funnel JSON) → the step auto-registers as skipped and the funnel behaves exactly as before.This PR is frontend-only by explicit decision. Two hard backend dependencies must land before this can be enabled for anyone:
1. Funnel JSON (
/boot/funnels/:key)Onboarding steps are emitted by the backend funnel JSON. The new step will not appear in any real flow until the backend adds it. Required shape:
{ "id": "invite_friends", "type": "inviteFriends", "parameters": { // all optional — sensible defaults ship in the component "headline": "Invite {count} friends, get {reward} of Plus on us", "explainer": "...", "celebrationHeadline": "...", "celebrationExplainer": "...", "celebrationCta": "Continue", "reward": "1 month", // A/B lever: "1 month" vs "3 months" (copy only) "targetCount": 3 }, "transitions": [ { "on": "complete", "destination": "<next-step-or-finish>" }, { "on": "skip", "destination": "<next-step-or-finish>" } // REQUIRED — the in-step skip button only renders when this transition exists ] }The step must be placed after registration (it auto-skips for anonymous users because referral links are per-user).
2. Plus grant mechanism
There is no frontend path to grant Plus —
isPlusis backend-set and this PR deliberately never fakes or sets any Plus state client-side. Backend needs a new reward mechanism. The frontend contract it should build against:referredUsersCountsemantics of the generic referral campaign (referralCampaign(referralOrigin: "generic")) — a user who signs up through the inviter's referral link/token. The step reads this exact field for progress, so grant eligibility and the progress UI stay in sync by construction.referredUsersCountreaches the target (3), backend grants the reward automatically (server-side observer on referral attribution — not triggered by any frontend call). The step'scompletetransition details ({ referredUsersCount, targetReached, invited }) are analytics, not a grant request.rewardcopy parameter; the actual granted duration must be configured backend-side to match the arm the funnel JSON is serving.user.isPlusflips via boot as it does today; no new client API is required. (A follow-up notification/email when the reward lands would be a backend/product nicety, not required by this UI.)Testing
packages/shared/src/features/onboarding/steps/FunnelInviteFriends.spec.tsx— 12 tests: progress fromreferredUsersCount(0/3, 1/3), reward-copy A/B parameter, copy → clipboard + toast, mobile →navigator.share, skip transition (+ JSON-provided skip copy), funnel target ids, 3/3 celebration → complete, flag-off / anonymous auto-skip registration, flag-on registration.FunnelStepper.spec.tsx— 2 new tests: the registered step renders inside the stepper with the real flag plumbing on, and renders nothing with the flag off; all 18 pre-existing stepper tests untouched and passing (nostepComponentMapregression).stories/components/onboarding/FunnelInviteFriends.stories.tsx— 0/3, 1/3, 3/3 celebration, 3-months reward arm, and missing-skip-transition states (renders the unguarded step; flag gating is Jest-verified since the repo-wide Storybook flag mock can't represent flag-off).node ./scripts/typecheck-strict-changed.js✅ ·pnpm --filter shared lint✅ ·NODE_ENV=test pnpm --filter shared test→ 295 suites / 1999 tests ✅ ·NODE_ENV=test pnpm --filter webapp test→ 44 suites / 297 tests ✅🤖 Generated with Claude Code
Preview domain
https://claude-onboarding-invite-reward.preview.app.daily.dev