Product Spec: "Invite Friends" Flow
1. Overview
Goal
Increase successful invites (defined as: invitee downloads the app and completes onboarding) by shipping a low-friction, high-conversion invite flow within 4 weeks.
Design Principle
Optimize taps to first value. Every screen, every modal, every confirmation should be interrogated: "Can this be removed or combined?" The target is 2 taps from trigger to invite sent, and 2 taps from invite received to first value for the invitee.
Success Metrics
| Metric | Baseline | Target (8 weeks post-launch) |
|---|---|---|
| Invite send rate (% of MAU who send at least 1 invite) | N/A (new) | 15% |
| Invite acceptance rate (invitee opens link) | N/A | 40% |
| Invite conversion rate (invitee completes onboarding) | N/A | 25% |
| Time from invite tap to invite sent | N/A | < 8 seconds |
| Invitee time from link tap to first value | N/A | < 60 seconds |
Non-Goals
- Referral rewards or incentive programs (potential Phase 2)
- In-app social graph / contacts sync beyond invite flow
- Web or Android (iOS only for this phase)
2. User Flows
2.1 Sender Flow (Happy Path)
[Trigger Point] → [Share Sheet] → [Invite Sent] → [Confirmation]
Tap 1 Tap 2 (automatic) (inline toast)
Step-by-step:
-
Trigger (Tap 1): User taps an "Invite Friends" entry point (see Section 3 for placement). This opens the native iOS share sheet with a pre-composed message and deep link.
-
Share Sheet (Tap 2): User selects a contact or channel (iMessage, WhatsApp, copy link, AirDrop, etc.). The invite is sent immediately via the chosen channel.
-
Confirmation: An inline toast appears: "Invite sent! You'll be notified when [they] join." No blocking modal, no extra tap required.
Total sender taps: 2
2.2 Invitee Flow (Happy Path)
[Tap Link] → [App Store / App Open] → [Personalized Onboarding] → [First Value]
Tap 1 Tap 2 (Install) (streamlined) (immediate)
Step-by-step:
-
Tap Link (Tap 1): Invitee taps the deep link in their message. If the app is not installed, they land on a lightweight App Clip or App Store page. If installed, the app opens directly to a personalized welcome screen.
-
Install & Open (Tap 2): Invitee taps "Get" in the App Store. After install, the deferred deep link routes them to a personalized onboarding flow that references the inviter by name/avatar.
-
Streamlined Onboarding: The onboarding flow is condensed for invited users. Skip optional steps. Pre-fill context from the invite (e.g., shared content, group, or feature the sender was using). Target: 2-3 screens max, no sign-up wall before first value.
-
First Value: The invitee immediately sees the content, feature, or connection that motivated the invite. A "Connect with [Sender]" action is surfaced prominently.
Total invitee taps to first value: 2 (tap link + install) for new users; 1 for existing users
2.3 Sender Notification Flow
When an invitee joins:
- Push notification: "[Friend's name] just joined! Say hi."
- Tapping the notification opens a connection/interaction screen with the new user.
- This closes the loop and reinforces the behavior of inviting.
3. Entry Points & Triggers
3.1 Persistent Entry Points
| Location | Implementation | Rationale |
|---|---|---|
| Profile/Settings tab | "Invite Friends" row with icon | Discoverable for intentional inviters |
| Navigation bar / hamburger menu | "Invite Friends" row | Accessible from anywhere |
3.2 Contextual Triggers (High-Intent Moments)
These are the highest-leverage placements because the user has a natural reason to share:
| Trigger Moment | UX Pattern | Pre-composed Message |
|---|---|---|
| After completing a key action (e.g., finishing a workout, creating content, achieving a milestone) | Celebration screen with "Share with a friend" CTA | "[Name] just [accomplished X] on [App]. Try it out: [link]" |
| When viewing content that is better with others | Inline "Invite a friend to [do this together]" button | "I'm using [App] for [activity]. Join me: [link]" |
| Empty state in social/collaborative features | "Invite friends to get started" prompt with illustration | "Join me on [App]: [link]" |
| After the user's 3rd session (habit formation signal) | Soft prompt: "Enjoying [App]? Friends who join together stick around 2x longer" | Default share message with personalized context |
| Contact permission prompt (if applicable) | Suggest specific contacts the user messages frequently | Personalized per contact |
3.3 Trigger Frequency Rules
- Contextual prompts: Max 1 per session, max 3 per week.
- Never interrupt a core flow (no modals during primary tasks).
- Respect dismissals: If a user dismisses a contextual prompt twice, suppress for 30 days.
- Never show invite prompts before the user's 2nd session (let them find value first).
4. Deep Linking & Attribution
4.1 Link Structure
Use Universal Links (iOS) with a URL scheme fallback:
https://app.example.com/invite?ref={sender_user_id}&ctx={context_type}&cid={content_id}&sig={signature}
Parameters:
ref: Sender's user ID (for attribution and personalization)ctx: Context type (e.g., "achievement", "content", "generic")cid: Content or feature ID (for deep routing after install)sig: HMAC signature to prevent link tampering
4.2 Deferred Deep Linking
Use a deferred deep linking solution (Branch.io, Firebase Dynamic Links, or custom) to:
- Attribute installs to specific inviters even after App Store redirect
- Route new users to the correct in-app destination after onboarding
- Pass context through the install process (sender name, shared content, etc.)
4.3 App Clip (Optional, Recommended)
For the highest-value invite contexts (e.g., shared content, collaborative features):
- Provide an App Clip experience that delivers immediate value without full install
- Include a prominent "Get the Full App" CTA within the App Clip
- This dramatically reduces taps-to-first-value for the invitee (0 install taps)
5. Share Message Design
5.1 Principles
- Personal over promotional: Messages should feel like they're from a friend, not a brand.
- Context-rich: Include what the sender was doing, not just a generic "try this app."
- Rich previews: Use Open Graph / link preview metadata to show an engaging card in iMessage, WhatsApp, etc.
5.2 Message Templates
Generic Invite:
Check out [App Name] — I've been using it for [auto-detected primary use case]. Here's my invite link: [link]
Post-Achievement:
I just [achieved X] on [App Name]! You should try it: [link]
Content Share:
[Content title/preview] — thought you'd like this. Check it out on [App Name]: [link]
Collaborative:
Join me on [App Name] so we can [collaborative feature]. Here's my invite: [link]
5.3 Link Preview Card
- Title: "[Sender's first name] invited you to [App Name]"
- Subtitle: Contextual (e.g., "Join 50K+ people doing [core activity]")
- Image: Dynamic — sender's avatar or relevant content thumbnail. Fallback to branded card.
- Generate server-side using an OG image service for fast, dynamic previews.
6. Invitee Onboarding (Invited User Experience)
6.1 Key Differences from Organic Onboarding
| Aspect | Organic User | Invited User |
|---|---|---|
| Welcome screen | Generic | "Welcome! [Sender name] invited you" with sender's avatar |
| Onboarding steps | Full (5-7 screens) | Condensed (2-3 screens), skip optional steps |
| Sign-up requirement | Before first value | After first value (delayed sign-up wall) |
| First screen after onboarding | Default home | Context-specific destination (shared content, sender's profile, collaborative feature) |
| Social connection | Must find friends manually | Auto-suggested connection with sender |
6.2 Delayed Sign-Up Wall
- Let invited users experience first value before requiring account creation.
- Show a "Sign up to save your progress and connect with [Sender]" prompt after the first meaningful interaction.
- This maximizes the chance they experience the "aha moment" before dropping off at registration.
7. Technical Architecture
7.1 Backend Components
Invite Service:
POST /invites— Create invite, generate deep link, return shareable URLGET /invites/{code}— Resolve invite for incoming usersPOST /invites/{code}/accept— Mark invite as accepted, trigger sender notificationGET /users/{id}/invites— List sent invites and their statuses
Data Model:
Invite {
id: UUID
sender_id: UUID
invite_code: String (unique, short, URL-safe)
context_type: Enum (generic, achievement, content, collaborative)
context_id: String? (content ID, achievement ID, etc.)
channel: Enum (imessage, whatsapp, copy_link, airdrop, other)
status: Enum (created, sent, opened, accepted, expired)
invitee_id: UUID? (populated on acceptance)
created_at: Timestamp
accepted_at: Timestamp?
expires_at: Timestamp (default: 30 days)
}
Analytics Events:
invite_flow_started— User tapped an invite entry pointinvite_share_sheet_opened— Share sheet presentedinvite_sent— Invite shared via a channelinvite_link_opened— Invitee tapped the linkinvite_app_installed— Invitee installed the app (deferred deep link callback)invite_onboarding_started— Invitee began invited-user onboardinginvite_onboarding_completed— Invitee completed onboardinginvite_first_value— Invitee reached first value momentinvite_accepted— Invitee and sender connectedinvite_prompt_shown— Contextual trigger displayedinvite_prompt_dismissed— Contextual trigger dismissed
7.2 iOS Client Components
| Component | Description |
|---|---|
InviteManager | Singleton. Handles invite creation, deep link generation, share sheet presentation. |
InviteDeepLinkHandler | Parses incoming universal links, routes to appropriate flow. |
InvitedUserOnboardingVC | Condensed onboarding flow for invited users. |
InvitePromptManager | Controls when/where contextual invite prompts appear. Enforces frequency rules. |
InviteStatusTracker | Polls/subscribes for invite acceptance events, triggers sender notifications. |
7.3 Infrastructure
- Deep linking: Branch.io SDK or Firebase Dynamic Links (evaluate setup time vs. flexibility)
- Push notifications: Existing push infra; new notification type for invite acceptance
- OG image generation: Serverless function (e.g., Cloudflare Worker or AWS Lambda) that renders dynamic link preview images
- Rate limiting: Max 50 invites per user per day to prevent abuse
8. Edge Cases & Error Handling
| Scenario | Handling |
|---|---|
| Invitee already has the app installed | Deep link opens app directly, shows "[Sender] wants to connect" screen. Skip onboarding. |
| Invitee already has an account and is connected to sender | Toast: "You're already connected with [Sender]!" |
| Invite link expired (>30 days) | Landing page: "This invite has expired. Download [App] to get started." Still route to App Store. |
| Sender's account deleted/suspended | Invite link still works but without personalization. Generic onboarding. |
| Share sheet dismissed without sending | Log invite_share_sheet_dismissed. No toast. Invite record stays in created status. |
| User spams invites | Rate limit at 50/day. After limit: "You've sent a lot of invites today. Try again tomorrow." |
| Deep link attribution fails | Fall back to generic onboarding. Log for debugging. |
| No internet when tapping invite entry point | Show inline error: "Check your connection and try again." Queue invite creation for retry. |
| Invitee on Android | Link opens a mobile web page: "Thanks for your interest! [App] is currently available on iOS. We'll notify you when Android launches." Capture email. |
9. Privacy & Compliance
- No contacts upload without explicit consent. The invite flow uses the native iOS share sheet, which does not require contacts permission.
- If a "suggested contacts" feature is added later, it must use the Contacts framework with explicit permission and clear explanation of why.
- Invite links contain no PII — only opaque user IDs and content IDs.
- HMAC signature on links prevents enumeration/tampering.
- Comply with App Store Review Guidelines Section 5.1.1 (Data Collection and Storage) and 5.1.2 (Data Use and Sharing).
- Include invite-related data in GDPR/CCPA data export and deletion flows.
10. 4-Week Delivery Plan
Week 1: Foundation
- Backend: Invite service API (create, resolve, accept)
- Backend: Deep link generation and resolution
- iOS:
InviteManagerand share sheet integration - iOS: Universal link handling in
AppDelegate/SceneDelegate - Design: Finalize share message templates and link preview cards
- Set up Branch.io / Firebase Dynamic Links SDK
Week 2: Core Flows
- iOS: Sender flow end-to-end (entry point → share sheet → toast)
- iOS: Invitee deep link routing (existing users)
- iOS: Invited user onboarding flow (condensed)
- Backend: Invite status tracking and acceptance webhook
- Backend: OG image generation for link previews
- QA: Sender flow testing across iMessage, WhatsApp, copy link
Week 3: Polish & Contextual Triggers
- iOS: 2-3 highest-value contextual invite triggers
- iOS:
InvitePromptManagerwith frequency capping - iOS: Sender notification on invite acceptance (push + in-app)
- iOS: Deferred deep linking for new installs
- Backend: Analytics event pipeline for all invite events
- QA: Full end-to-end testing (new install → onboarding → first value)
Week 4: Testing, Optimization & Launch
- QA: Edge case testing (expired links, existing users, no internet, rate limits)
- QA: Performance testing (link resolution latency < 200ms)
- A/B test setup: Contextual triggers on/off, message variants
- Instrument all analytics events and verify in dashboard
- App Store submission
- Staged rollout: 10% → 50% → 100% over 5 days
- Monitor: Crash rates, invite funnel metrics, support tickets
11. A/B Testing Plan
Experiment 1: Share Message Personalization
- Control: Generic message ("Check out [App]!")
- Variant: Context-rich message ("[Sender] just [did X] on [App]!")
- Primary metric: Invite acceptance rate
- Sample size: 5,000 invites per variant
Experiment 2: Invitee Onboarding Length
- Control: Standard onboarding (5-7 screens)
- Variant: Condensed onboarding (2-3 screens) with delayed sign-up
- Primary metric: Onboarding completion rate, 7-day retention
- Sample size: 1,000 invited users per variant
Experiment 3: Contextual Trigger Placement
- Control: No contextual triggers (profile entry point only)
- Variant: Post-achievement + empty state triggers
- Primary metric: Invite send rate
- Sample size: 10,000 MAU per variant
12. Post-Launch Monitoring & Iteration
Key Dashboards
- Invite Funnel: Entry point tap → Share sheet open → Invite sent → Link opened → App installed → Onboarding completed → First value reached
- Channel Performance: Conversion rates by share channel (iMessage vs. WhatsApp vs. copy link vs. other)
- Trigger Performance: Invite send rate by entry point / contextual trigger
- Invitee Quality: 7-day / 30-day retention of invited users vs. organic users
Phase 2 Candidates (Post-Launch)
- Referral incentive program (both sender and invitee rewards)
- "Invite your contacts" feature with contacts permission
- In-app invite status page ("3 friends joined, 2 pending")
- Smart suggestions: "You and [contact] both like [activity]. Invite them?"
- Android support
- Leaderboard / social proof ("You've brought 5 friends to [App]!")
13. Summary of Tap Optimization
| User | Action | Taps |
|---|---|---|
| Sender | Trigger to invite sent | 2 (tap entry point + select contact in share sheet) |
| Invitee (new) | Link tap to first value | 2 (tap link + tap Install); first value on app open |
| Invitee (existing) | Link tap to first value | 1 (tap link; app opens to destination) |
| Sender | Notification to reconnection | 1 (tap push notification) |
The entire invite loop — from sender's intent to invitee experiencing value — is designed to complete in 4 total taps (2 sender + 2 invitee), with the goal of making sharing feel as natural and effortless as sending a text message.