Migrate Firebase Dynamic Links in React Native
Firebase Dynamic Links has shut down. The @ulinkly/react-native SDK bridges the native Android/iOS Ulinkly SDKs behind a single TypeScript API, so you can replace @react-native-firebase/dynamic-links while keeping your app logic in JavaScript. This guide swaps the dependency and updates your code.
1. Install the package
Expo:
npx expo install @ulinkly/react-native
Bare React Native:
npm install @ulinkly/react-native
npx install-expo-modules@latest
cd ios && pod install
Then apply native configuration (custom scheme + Associated Domains / App Links) — either via the Expo config plugin or manual native setup. This replaces the deep-link configuration you previously had for Firebase.
@ulinkly/react-native is a native module — use a development build or expo prebuild, not Expo Go.
2. Configure your Ulinkly project
Follow the prerequisites from the migration overview:
- Configuration → Android/iOS: package name, bundle ID, Team ID, URL schemes, SHA-256 fingerprints, store fallbacks.
- Domains: verify your
.shared.lysubdomain or a custom host. - Links: recreate Firebase short links with the right type (
dynamicvsunified), or create them programmatically (step 5).
3. Initialize the SDK
Replace your Firebase initialization and dynamicLinks().onLink(...) setup with Ulinkly initialization at app startup:
import ULink from '@ulinkly/react-native';
async function initULink() {
await ULink.initialize({
apiKey: 'ULINK_API_KEY_FROM_DASHBOARD',
debug: __DEV__,
});
}
initULink().catch(console.error);
Always await initialize() before calling other methods. On Android, pre-init calls reject; on iOS they queue.
4. Handle incoming links
Firebase exposed dynamicLinks().getInitialLink() (cold start) and dynamicLinks().onLink() (foreground). Ulinkly unifies both into event listeners that also cover cold start automatically:
import { useEffect } from 'react';
import ULink, { ULinkResolvedData } from '@ulinkly/react-native';
export function useDeepLinks() {
useEffect(() => {
const dynSub = ULink.onDynamicLink(handleLink); // replaces onLink + getInitialLink
const uniSub = ULink.onUnifiedLink((data) => {
// platform-redirect links — open externally if appropriate
});
return () => {
dynSub.remove();
uniSub.remove();
};
}, []);
}
function handleLink(data: ULinkResolvedData) {
// Firebase: link.url + query params → Ulinkly: structured data.parameters
const screen = data.parameters?.screen as string | undefined;
// navigate based on screen / parameters
}
Mapping from Firebase concepts:
| Firebase Dynamic Links | Ulinkly (@ulinkly/react-native) |
|---|---|
dynamicLinks().getInitialLink() | cold-start link delivered via onDynamicLink (or ULink.getInitialDeepLink()) |
dynamicLinks().onLink(cb) | ULink.onDynamicLink(cb) → returns a subscription; call .remove() to unsubscribe |
Parsing link.url query string | structured data.parameters (typed map) |
| Social meta tags on the link | data.socialMediaTags |
To resolve a URL yourself (e.g. one captured by your own Linking handler), call await ULink.resolveLink(url) or await ULink.processULink(url).
5. Replace Firebase link creation
Where you built links with the Firebase Builder API or the REST shortener, switch to createLink:
const response = await ULink.createLink({
domain: 'myapp.shared.ly',
type: 'dynamic',
slug: 'rn-launch',
externalId: 'rn-launch-campaign', // idempotency key — dedupes repeat calls
iosFallbackUrl: 'https://apps.apple.com/app/id123456789',
androidFallbackUrl: 'https://play.google.com/store/apps/details?id=com.example.app',
fallbackUrl: 'https://example.com/launch',
parameters: { utm_source: 'rn-app', screen: 'offer' },
});
if (response.success) {
console.log('Created link:', response.url);
}
Unified (platform-redirect) links use type: 'unified' with iosUrl / androidUrl / fallbackUrl instead of parameters. See Create Dynamic Links → React Native.
6. Validate end-to-end
- Trigger your new links with the
adb/xcrun simctl openurlcommands from Troubleshoot → Testing Deep Links. - Run with
debug: __DEV__and inspect SDK logs viaULink.onLog(...)— native iOS/Android logs bubble up to JS. - Watch Dashboard → Links → Analytics for clicks and per-device stats.
- Optionally run
ulink verify -vto confirm native configuration.
Once verified, remove @react-native-firebase/dynamic-links from your package.json (and the Firebase deep-link entries from Info.plist / AndroidManifest.xml if they're no longer used). Your app is now fully backed by Ulinkly.