Flutter Detour
Flutter SDK for handling deferred deep links with native Detour SDKs on Android and iOS.
Documentation
Check out our documentation page for integration guides and API details:
- Docs home: https://docs.swmansion.com/detour/docs/
- Flutter installation guide: https://docs.swmansion.com/detour/docs/sdk/flutter/sdk-installation
Other Detour SDKs
Detour is also available for other app stacks:
- Android SDK: https://github.com/software-mansion-labs/android-detour
- iOS SDK: https://github.com/software-mansion-labs/ios-detour
- React Native SDK: https://github.com/software-mansion-labs/react-native-detour
Create account on platform
Create account and configure your links: https://godetour.dev/auth/signup
Installation
Package
Add the package to your pubspec.yaml:
dependencies:
detour_flutter_plugin: ^1.0.1
Install dependencies:
flutter pub get
Native SDK dependencies
This plugin uses native Detour SDK implementations:
- Android:
com.swmansion.detour:detour-sdk:1.0.0 - iOS: embedded in this plugin package (no extra pod dependency)
Android
Make sure your Android repositories can resolve com.swmansion.detour:detour-sdk (for example via google() and mavenCentral() in your project repositories block).
iOS
No additional setup is required for the native iOS SDK dependency.
Run pods:
cd ios
pod install
cd ..
Usage
Recommended integration with DetourService
DetourService is the recommended orchestration layer. It:
- configures SDK once,
- merges initial and runtime link handling into a single pending intent,
- exposes readiness via
isInitialLinkProcessed, - uses explicit consume semantics with
consumePendingIntent(), - suppresses short-window duplicate emissions.
import 'package:detour_flutter_plugin/detour_flutter_plugin.dart';
final detour = DetourService();
@override
void initState() {
super.initState();
detour.addListener(_onDetourChanged);
_startDetour();
}
Future<void> _startDetour() async {
await detour.start(
const DetourConfig(
apiKey: '<REPLACE_WITH_YOUR_API_KEY>',
appID: '<REPLACE_WITH_APP_ID_FROM_PLATFORM>',
shouldUseClipboard: true,
linkProcessingMode: LinkProcessingMode.all,
),
);
}
void _onDetourChanged() {
final intent = detour.pendingIntent;
if (intent == null) return;
// Route once, then mark as consumed.
// context.go(intent.link.route);
detour.consumePendingIntent();
}
@override
void dispose() {
detour.removeListener(_onDetourChanged);
detour.dispose();
super.dispose();
}
Link processing mode
Use linkProcessingMode to control which sources are handled by SDK:
| Value | Universal/App links | Deferred links | Custom scheme links |
|---|---|---|---|
LinkProcessingMode.all (default) |
✅ | ✅ | ✅ |
LinkProcessingMode.webOnly |
✅ | ✅ | ❌ |
LinkProcessingMode.deferredOnly |
❌ | ✅ | ❌ |
Custom scheme runtime links
Custom scheme links require:
linkProcessingMode: LinkProcessingMode.all- native registration on each platform
Android (AndroidManifest.xml):
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="detour-flutter-example" />
</intent-filter>
iOS (Info.plist):
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>detour-flutter-example</string>
</array>
</dict>
</array>
Test commands:
# Android
adb shell am start -a android.intent.action.VIEW \
-d "detour-flutter-example://products/42?source=scheme" \
<your.package.name>
# iOS Simulator
xcrun simctl openurl booted "detour-flutter-example://products/42?source=scheme"
Low-level API
If you need full manual control, use DetourFlutterPlugin directly:
final plugin = DetourFlutterPlugin();
await plugin.configure(
const DetourConfig(
apiKey: '<REPLACE_WITH_YOUR_API_KEY>',
appID: '<REPLACE_WITH_APP_ID_FROM_PLATFORM>',
),
);
final initial = await plugin.resolveInitialLink();
final stream = plugin.linkStream;
final processed = await plugin.processLink('https://example.com/path');
Analytics
Flutter API follows native SDK analytics contract:
- predefined events via
DetourEventName, - retention events as string names.
await detour.logEvent(
DetourEventName.purchase,
data: {'value': 9.99, 'currency': 'USD'},
);
await detour.logRetention('home_screen_viewed');
Types
DetourConfig
class DetourConfig {
final String apiKey;
final String appID;
final bool shouldUseClipboard;
final LinkProcessingMode linkProcessingMode;
}
DetourIntent
class DetourIntent {
final DetourLink link;
final DetourIntentSource source;
final DateTime receivedAt;
}
DetourResult
class DetourResult {
final bool processed;
final DetourLink? link;
}
DetourLink
class DetourLink {
final String url;
final String route;
final String pathname;
final Map<String, String> params;
final LinkType type;
}
DetourEventName
enum DetourEventName {
login,
search,
share,
signUp,
tutorialBegin,
tutorialComplete,
reEngage,
invite,
openedFromPushNotification,
addPaymentInfo,
addShippingInfo,
addToCart,
removeFromCart,
refund,
viewItem,
beginCheckout,
purchase,
adImpression,
}
API Reference
DetourService
High-level integration helper:
Future<void> start(DetourConfig config)DetourIntent? get pendingIntentvoid consumePendingIntent()bool get isInitialLinkProcessedFuture<DetourResult> processLink(String url, {bool emitIntent = true})Future<void> logEvent(DetourEventName eventName, {Map<String, dynamic>? data})Future<void> logRetention(String eventName)Future<void> stop()
DetourFlutterPlugin
Low-level bridge API:
Future<void> configure(DetourConfig config)Future<DetourResult> resolveInitialLink()Stream<DetourResult> get linkStreamFuture<DetourResult> processLink(String url)Future<void> logEvent(DetourEventName eventName, {Map<String, dynamic>? data})Future<void> logRetention(String eventName)
Requirements
- Dart:
^3.11.1 - Flutter:
>=3.3.0 - Android: min SDK 24
- iOS: 13.0+
Example
A complete integration example is available in this repo:
example/
License
This library is licensed under The MIT License.
Flutter Detour is created by Software Mansion
Since 2012, Software Mansion is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product - Hire us.