Use Case: Referral Programs

Referral Program Deep Links

Build referral programs that survive app installs. Use deferred deep links to attribute new users to their referrers, even when they don't have the app installed yet.

The Challenge

The referral attribution challenge

Referral programs drive user growth, but attribution breaks when referral links are tapped before the app is installed. Here's the problem:

What breaks without deferred deep links:

  1. 1.User A refers User B via a referral link: https://myapp.com/ref/alice123
  2. 2.User B doesn't have the app installed. They tap the link, land on a web page.
  3. 3.They're prompted to install. They go to App Store. Referrer context is lost.
  4. 4.App launches. Your SDK doesn't know who referred User B. Attribution is broken.
  5. 5.User A never gets credit for the referral. No reward. Referral loop collapses.

Without deferred deep links

  • Referrer ID lost when user taps link before install
  • No way to track who invited new user
  • Rewards can't be distributed correctly
  • Referral program incentive broken

With deferred deep links

  • Referrer ID preserved across app install
  • First install attributed to correct referrer
  • Rewards automatically credited to referrer
  • Viral growth loop stays intact
How It Works

How deferred deep links enable attribution

Step 1: Generate referral link

When User A wants to refer friends, you generate a Redirectly deep link with their referrer ID: https://myapp.redirectly.app/ref?referrer_id=alice123

Step 2: User shares link

User A shares the link via SMS, email, or social. User B receives it on mobile and taps it.

Step 3: Redirectly captures referrer ID

If User B has the app: deep link opens directly, referrer ID is passed to your app immediately.

If User B doesn't have the app: Redirectly captures the full URL (including referrer_id) and stores it.

Step 4: App store redirect

User B is sent to App Store. Referrer ID is preserved in Redirectly's servers—not lost.

Step 5: SDK queries deferred link on first launch

When your app launches for the first time on User B's device, the Redirectly SDK asks: "What deep link was intended for this device?" Redirectly responds with the referral link including referrer_id.

Step 6: Credit referrer and award points

Your app receives the referrer_id, posts it to your backend: "User B was referred by alice123." Your backend credits User A with the referral reward instantly.

Implementation

Implementation with Redirectly

Backend: Generate referral links

When a user requests their referral link, create a Redirectly deep link with their ID:

# Backend code (Node.js) app.get('/api/get-referral-link', (req, res) => { const userId = req.user.id; const referralLink = ( 'https://myapp.redirectly.app/ref' + '?referrer_id=' + userId + '&campaign=user_referral' ); // Store the referral link in DB for tracking saveReferralLink(userId, referralLink); res.json({ referral_link: referralLink }); });

Mobile: Initialize and listen

Setup Redirectly and handle referral deep links on first launch:

import 'package:redirectly/redirectly.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Redirectly.initialize( apiKey: 'your_api_key_here', ); // Get deferred link (called on first launch) final deepLink = await Redirectly.getInitialLink(); if (deepLink != null && deepLink.path == 'ref') { final referrerId = deepLink.queryParameters['referrer_id']; print('Referred by: $referrerId'); // Send to backend to credit referrer creditReferral(referrerId); } runApp(const MyApp()); }

Backend: Credit the referrer

When a new user is attributed to a referrer, award points or credits:

app.post('/api/credit-referral', async (req, res) => { const { referrer_id } = req.body; // Check if referrer exists const referrer = await User.findById(referrer_id); if (!referrer) { return res.status(400).json({ error: 'Invalid referrer' }); } // Award points to referrer referrer.referral_points += 50; // or 5, depending on your rewards referrer.total_referrals += 1; await referrer.save(); // Log the referral for analytics await ReferralEvent.create({ referrer_id, referred_user_id: req.user.id, timestamp: new Date(), reward_amount: 50, }); res.json({ success: true, points_awarded: 50 }); });
Code Example

Complete referral program example

// Flutter app - Handle referral on first launch import 'package:redirectly/redirectly.dart'; import 'package:http/http.dart' as http; class ReferralManager { static Future<void> handleReferralOnFirstLaunch() async { // Get the deferred deep link final deepLink = await Redirectly.getInitialLink(); if (deepLink != null && deepLink.path == 'ref') { final referrerId = deepLink.queryParameters['referrer_id']; if (referrerId != null && referrerId.isNotEmpty) { await _creditReferrer(referrerId); } } } static Future<void> _creditReferrer(String referrerId) async { try { final response = await http.post( Uri.parse('https://api.example.com/api/credit-referral'), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ${authToken}', }, body: json.encode({ 'referrer_id': referrerId, }), ); if (response.statusCode == 200) { final data = json.decode(response.body); final pointsAwarded = data['points_awarded']; print('Referrer credited with $pointsAwarded points'); // Show celebration UI to new user showReferralBonus(referrerId, pointsAwarded); } } catch (e) { print('Error crediting referrer: $e'); } } } // User profile - Show referral link class ReferralLinkWidget extends StatefulWidget { final User user; const ReferralLinkWidget({required this.user}); @override State<ReferralLinkWidget> createState() => _ReferralLinkWidgetState(); } class _ReferralLinkWidgetState extends State<ReferralLinkWidget> { String? referralLink; bool isLoading = true; @override void initState() { super.initState(); _fetchReferralLink(); } Future<void> _fetchReferralLink() async { try { final response = await http.get( Uri.parse('https://api.example.com/api/get-referral-link'), headers: { 'Authorization': 'Bearer ${authToken}', }, ); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { referralLink = data['referral_link']; isLoading = false; }); } } catch (e) { setState(() => isLoading = false); } } Future<void> _copyToClipboard() async { if (referralLink != null) { await Clipboard.setData(ClipboardData(text: referralLink!)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Referral link copied!')), ); } } Future<void> _shareLink() async { if (referralLink != null) { await Share.share( 'Join me on the app! $referralLink', subject: 'Join my community', ); } } @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Your Referral Link', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), if (isLoading) const CircularProgressIndicator() else if (referralLink != null) ...[ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(8), ), child: SelectableText( referralLink!, style: const TextStyle(fontSize: 12), ), ), const SizedBox(height: 12), Row( children: [ Expanded( child: ElevatedButton.icon( onPressed: _copyToClipboard, icon: const Icon(Icons.copy), label: const Text('Copy'), ), ), const SizedBox(width: 8), Expanded( child: ElevatedButton.icon( onPressed: _shareLink, icon: const Icon(Icons.share), label: const Text('Share'), ), ), ], ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.blue[50], borderRadius: BorderRadius.circular(8), ), child: Row( children: [ const Icon(Icons.info, size: 16), const SizedBox(width: 8), Expanded( child: Text( 'Earn 50 points for each friend who joins!', style: TextStyle(fontSize: 12, color: Colors.blue[900]), ), ), ], ), ), ] else const Text('Failed to load referral link'), ], ), ), ); } }

This example includes:

  • Deferred link detection on first launch
  • API call to backend to credit the referrer
  • Referral link generator in user profile
  • Share and copy buttons for easy distribution
FAQ

Frequently asked questions

What if the referrer ID is invalid?

On your backend, validate the referrer ID against your users table before awarding points. If invalid, simply don't credit anything. The new user still gets onboarded normally.

Can I track multiple referrals per user?

Yes. Each time a deferred link is detected with a referrer_id, you can log a new ReferralEvent. Track all historical referrals in your database.

What rewards should I offer?

Common approaches: 50-500 points per referral, premium features unlocked, or cash/credit rewards. The amount depends on your unit economics and user value.

How do I prevent referral fraud?

Validate that the new user is not already in your system. Check their IP/device ID for obvious duplicates. Consider requiring email verification before awarding points.

Do I need to handle this differently for Android vs iOS?

No. The Redirectly SDK handles the platform differences. Your code is the same for both.

Try Redirectly Free

Get a free API key, subdomain, and 10k monthly links.