Back to Blog
Migration Guide
15 min read
December 18, 2024

Migrate from Firebase Dynamic Links to Redirectly in React Native

Complete step-by-step guide to migrate your React Native app from Firebase Dynamic Links to Redirectly. Includes TypeScript code examples and troubleshooting tips.

Migration Timeline: 15-30 Minutes

This guide covers a basic migration. Complex setups with custom logic may require additional time for testing and verification.

Prerequisites

You need:

  • React Native 0.60 or higher
  • Node.js and npm/yarn
  • Existing Firebase Dynamic Links setup
  • Redirectly account (sign up free at redirectly.app)

Time estimate:

15-30 minutes for basic migration, plus testing time

Step 1: Remove Firebase Dynamic Links

Uninstall Firebase Package

Remove the firebase/dynamic-links package from your project:

bash
npm uninstall @react-native-firebase/dynamic-links firebase
# or if using yarn
yarn remove @react-native-firebase/dynamic-links firebase

Remove Firebase Configuration

Find and remove any Firebase initialization code from your app. Look for files like:

  • • src/services/firebaseService.ts
  • • src/utils/deepLinking.ts
  • • Any imports of dynamicLinks from Firebase

You can safely delete files that were only used for Firebase Dynamic Links initialization.

Step 2: Install Redirectly SDK

Install from npm

Add Redirectly SDK to your project:

bash
npm install @redirectly/react-native
# or if using yarn
yarn add @redirectly/react-native

Native Linking (if needed)

For React Native 0.60+, autolinking handles most of the setup. If you need manual linking:

bash
cd ios && pod install && cd ..
# or for android
cd android && ./gradlew clean

Step 3: Initialize Redirectly

Create Redirectly Service

Create a new file to manage Redirectly initialization:

typescript
import { Redirectly, DeepLinkData } from '@redirectly/react-native';

export class DeepLinkingService {
  private static initialized = false;

  static async initialize(apiKey: string): Promise<void> {
    if (this.initialized) return;

    await Redirectly.init({
      apiKey: apiKey,
      // Optional: set user for attribution tracking
      userId: null,
    });

    this.initialized = true;
  }

  static async createLink(
    path: string,
    campaign?: string,
    data?: Record<string, string>
  ): Promise<string> {
    const link = await Redirectly.createLink({
      path,
      campaign,
      data: data || {},
    });
    return link.url;
  }

  static onDeepLink(
    callback: (deepLink: DeepLinkData) => void
  ): () => void {
    return Redirectly.onDeepLink(callback);
  }

  static async getInitialLink(): Promise<DeepLinkData | null> {
    return Redirectly.getInitialLink();
  }
}

Initialize in App.tsx

Call the initialization in your main app component:

typescript
import React, { useEffect } from 'react';
import { SafeAreaView } from 'react-native';
import { DeepLinkingService } from './services/DeepLinkingService';

export default function App() {
  useEffect(() => {
    // Initialize Redirectly with your API key
    DeepLinkingService.initialize('your-api-key-here');
  }, []);

  return (
    <SafeAreaView style={{ flex: 1 }}>
      {/* Your app content */}
    </SafeAreaView>
  );
}

Step 4: Migrate Deep Link Listener

Old Firebase Code

Your existing Firebase implementation:

typescript
import { useEffect } from 'react';
import dynamicLinks from '@react-native-firebase/dynamic-links';
import { useNavigation } from '@react-navigation/native';

export const useFirebaseDeepLinks = () => {
  const navigation = useNavigation();

  useEffect(() => {
    let unsubscribe: (() => void) | undefined;

    dynamicLinks()
      .getInitialLink()
      .then((link) => {
        if (link?.url != null) {
          handleDeepLink(link.url);
        }
      });

    unsubscribe = dynamicLinks().onLink((link) => {
      const { url } = link;
      handleDeepLink(url);
    });

    return () => unsubscribe?.();
  }, [navigation]);

  const handleDeepLink = (url: string) => {
    const parsedUrl = new URL(url);
    const path = parsedUrl.pathname;

    if (path.startsWith('/product/')) {
      const productId = path.split('/')[2];
      navigation.navigate('ProductScreen', { productId });
    }
  };
};

New Redirectly Code

Migrated to use Redirectly:

typescript
import { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';
import { DeepLinkingService } from '../services/DeepLinkingService';
import { DeepLinkData } from '@redirectly/react-native';

export const useRedirectlyDeepLinks = () => {
  const navigation = useNavigation();

  useEffect(() => {
    // Handle initial deep link when app is launched from terminated state
    DeepLinkingService.getInitialLink().then((deepLink) => {
      if (deepLink) {
        handleDeepLink(deepLink);
      }
    });

    // Listen for deep links when app is already running
    const unsubscribe = DeepLinkingService.onDeepLink((deepLink) => {
      handleDeepLink(deepLink);
    });

    return unsubscribe;
  }, [navigation]);

  const handleDeepLink = (deepLink: DeepLinkData) => {
    const { path, campaign, data } = deepLink;

    // Log attribution data
    if (campaign) {
      console.log('User came from campaign:', campaign);
      console.log('Additional data:', data);
    }

    // Route based on path
    if (path.startsWith('/product/')) {
      const productId = path.split('/')[2];
      navigation.navigate('ProductScreen', { productId });
    } else if (path.startsWith('/user/')) {
      const userId = path.split('/')[2];
      navigation.navigate('UserProfile', { userId });
    } else {
      navigation.navigate('Home');
    }
  };
};

Step 5: Migrate Link Creation

Old Firebase Pattern

Creating links with Firebase:

typescript
const shareProduct = async (productId: string, productName: string) => {
  const link = await dynamicLinks().buildLink({
    link: `https://yourdomain.com/product/${productId}`,
    domainUriPrefix: 'https://yourdomain.page.link',
    android: {
      packageName: 'com.example.myapp',
      fallbackUrl: 'https://yourdomain.com/fallback',
    },
    ios: {
      bundleId: 'com.example.MyApp',
      fallbackUrl: 'https://yourdomain.com/fallback',
      appStoreId: '123456789',
    },
  });

  return link;
};

New Redirectly Pattern

Creating links with Redirectly:

typescript
const shareProduct = async (productId: string, productName: string) => {
  const linkUrl = await DeepLinkingService.createLink(
    `/product/${productId}`,
    'social_share', // campaign identifier
    {
      productName,
      timestamp: new Date().toISOString(),
    }
  );

  return linkUrl;
};

Step 6: Testing & Deployment

Test Deep Linking

1. Build and run your app on a test device:

bash
npm run android
# or for iOS
npm run ios

2. Test initial deep link:

bash
adb shell am start -W -a android.intent.action.VIEW -d "redirectly://product/123" com.example.myapp

3. Test deep link while app is running:

Create a link via Redirectly dashboard, share it, and tap to verify navigation works.

Checklist Before Deploying

  • All Firebase Dynamic Links imports removed
  • Redirectly SDK installed and initialized
  • Deep link listener migrated and tested
  • Link creation replaced with Redirectly.createLink
  • Tested on physical device (not just simulator)
  • Verified attribution tracking works

Migration Complete!

Your React Native app is now using Redirectly instead of Firebase Dynamic Links. Check out our advanced guides for more features.

Related Articles