Skip to content

feat(onboarding): add "where you found us" referral-source step - #188

Merged
paulocastellano merged 1 commit into
mainfrom
feat/onboarding-referral-source
Jul 18, 2026
Merged

feat(onboarding): add "where you found us" referral-source step#188
paulocastellano merged 1 commit into
mainfrom
feat/onboarding-referral-source

Conversation

@paulocastellano

Copy link
Copy Markdown
Contributor

What

Adds a "Where did you find us?" step to onboarding, between the goals and connect steps:

/onboarding (persona) → /onboarding/goals/onboarding/referral-source (new) → /onboarding/connect

Users pick a single source (Google, X, LinkedIn, YouTube, TikTok, Instagram, Reddit, Product Hunt, AI assistant, Friend, Blog, Other). The choice is stored on users.referral_source and mirrored to PostHog — exactly the way persona and goals already work.

Why

Attribution: understand which channels bring new signups, using the same lightweight onboarding pattern we already have.

Changes

Backend

  • App\Enums\User\ReferralSource — 12 string-backed cases
  • Migration: nullable referral_source column on users + $fillable/cast on User
  • StoreOnboardingReferralSourceRequestrequired + Rule::enum
  • OnboardingController::referralSource() / storeReferralSource() — same guard ladder as the sibling steps (self-hosted → calendar, subscribed → calendar, no persona → onboarding, no goals → goals), saves + PostHog::identify(['referral_source' => …])
  • connect() now requires a referral source before rendering; storeGoals() now advances to the new step
  • Routes app.onboarding.referral-source[.store]

Frontend

  • resources/js/pages/onboarding/ReferralSource.vue — single-select page mirroring Goals.vue, Tabler brand icons per source

i18n

  • referral_source_title, referral_source_description, and 12 source labels across all 15 locales

Self-hosted

Never sees the screen — the first guard is self_hosted → calendar, same as every other onboarding step.

Tests

  • OnboardingControllerTest: render, all guards, self-hosted, subscribed, validation (required + invalid enum), store + PostHog + redirect, and the new connect() guard. Existing connect / full-flow / self-hosted tests updated for the new required field.
  • Full suite: 2623 passed, 0 failed. LocalizationParityTest green. pint + eslint clean.

Notes

  • Wayfinder route helper is generated (gitignored) — regenerated by php artisan wayfinder:generate / the vite plugin.
  • checkout() is intentionally left without a referral_source guard, matching how persona/goals are handled today (gated at the connect() GET, not at the checkout POST).

Adds a single-select referral-source step between the goals and connect
steps of onboarding. The choice is stored on users.referral_source and
mirrored to PostHog, mirroring the existing persona and goals steps.

- ReferralSource enum (12 sources) + nullable users.referral_source column
- referralSource()/storeReferralSource() controller actions with the same
  self-hosted, subscribed, persona and goals guards as the sibling steps
- connect() now requires a referral source before rendering
- Single-select ReferralSource.vue page mirroring the goals step
- Localized across all 15 locales
@paulocastellano
paulocastellano merged commit 60c4c53 into main Jul 18, 2026
5 checks passed
@paulocastellano
paulocastellano deleted the feat/onboarding-referral-source branch July 18, 2026 19:11
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.

1 participant