Detour Flutter Plugin
Detour Flutter Plugin wraps the native Detour SDKs for Android and iOS, giving Flutter apps access to deferred deep linking. A deferred link works like a regular deep link, but survives the Play Store or App Store install — a user who clicks a link before having the app installed is redirected to the right screen on first launch. The plugin also handles Universal/App Links and custom scheme links in a single unified API.
Quick links
- Documentation: https://detour.swmansion.com/docs/
- Installation guide: https://detour.swmansion.com/docs/sdk/flutter/sdk-installation
Create an account
You need a Detour account to generate app credentials and configure your links.
Sign up here: https://godetour.dev/auth/signup
Installation
Package
Add the package to your pubspec.yaml:
dependencies:
detour_flutter_plugin: ^1.2.1
Then run flutter pub get.
Native SDK dependencies
This plugin uses native Detour SDK implementations:
- Android:
com.swmansion.detour:detour-sdk:1.1.0 - iOS:
DetourCocoaPod~> 1.1.0(pulled automatically via the plugin podspec)
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
The native iOS SDK is resolved automatically as a CocoaPods dependency. Just run:
cd ios && pod install && cd ..
Requirements
- Dart:
^3.11.1 - Flutter:
>=3.3.0 - Android: min SDK 24
- iOS: 13.0+
Usage
Recommended: DetourService
DetourService is the recommended integration layer. It extends ChangeNotifier and merges initial and runtime link handling into a single pending intent with explicit consume semantics.
DetourService example
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>',
),
);
}
void _onDetourChanged() {
final intent = detour.pendingIntent;
if (intent == null) return;
// Navigate once, then mark as consumed.
// context.go(intent.link.route);
detour.consumePendingIntent();
}
@override
void dispose() {
detour.removeListener(_onDetourChanged);
detour.dispose();
super.dispose();
}
Low-level API: DetourFlutterPlugin
For full manual control, use DetourFlutterPlugin directly:
DetourFlutterPlugin example
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');
Link processing mode
Use linkProcessingMode to control which link sources the SDK handles:
| 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 and native registration on each platform.
Native registration
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="myapp" />
</intent-filter>
iOS (Info.plist):
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Test commands:
# Android
adb shell am start -a android.intent.action.VIEW \
-d "myapp://products/42?source=scheme" \
<your.package.name>
# iOS Simulator
xcrun simctl openurl booted "myapp://products/42?source=scheme"
Analytics
Analytics example
await detour.logEvent(
DetourEventName.purchase,
data: {'value': 9.99, 'currency': 'USD'},
);
await detour.logRetention('week_1');
See the analytics docs for the full event list and retention tracking setup.
Types
DetourConfig
DetourConfig
class DetourConfig {
final String apiKey;
final String appID;
final bool shouldUseClipboard; // default: true
final LinkProcessingMode linkProcessingMode; // default: LinkProcessingMode.all
}
DetourIntent
DetourIntent
class DetourIntent {
final DetourLink link;
final DetourIntentSource source; // initial, runtime, or manual
final DateTime receivedAt;
}
enum DetourIntentSource { initial, runtime, manual }
DetourResult
DetourResult
class DetourResult {
final bool processed;
final DetourLink? link;
}
DetourLink
DetourLink
class DetourLink {
final String url;
final String route;
final String pathname;
final Map<String, String> params;
final LinkType type; // deferred, verified, or scheme
}
DetourEventName
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 (extends ChangeNotifier):
Future<void> start(DetourConfig config)bool get isStartedbool get isInitialLinkProcessedDetourIntent? get pendingIntentvoid consumePendingIntent()Future<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)
Example
A complete integration example covering deferred links, Universal/App Links, and custom scheme links is in example/. See the example setup guide for step-by-step instructions.
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
License
This library is licensed under The MIT License.
Detour Flutter Plugin 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.