Skip to content

Flutter SDK

The Ferry Flutter SDK supports Flutter 3.10 and Dart 3.0 or later. It wraps the native iOS and Android SDKs rather than reimplementing matching in Dart.

Platform requirements

PlatformMinimum
Flutter3.10
Dart3.0
iOS15.0
AndroidAPI 24

Install the package

Add ferry_link_flutter from pub.dev:

Terminal window
flutter pub add ferry_link_flutter

1. Configure before runApp

import 'package:ferry_link_flutter/ferry_link_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Ferry.configure(publicKey: 'pk_test_xxx');
runApp(const MyApp());
}
final subscription = Ferry.onLink.listen((link) {
switch (link.data['screen']) {
case 'product':
router.showProduct(link.data['product_id']);
case 'cart':
router.showCart();
default:
router.showHome();
}
});

Subscribe once in the root widget. The first subscriber starts deferred matching, and a link that resolves early is buffered until the listener is ready.

3. Configure Android

Add an autoVerify intent filter to android/app/src/main/AndroidManifest.xml:

<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="go.acme.com" />
</intent-filter>

4. Configure iOS

Add Associated Domains entries to ios/Runner/Runner.entitlements:

applinks:go.acme.com
applinks:acme.feryl.io

The Flutter plugin forwards native link opens into Ferry.onLink. No extra Dart link-forwarding code is required for normal App Links and universal links.

5. Track events

await Ferry.track(FerryEvents.login);
await Ferry.track(
FerryEvents.signup,
customerId: 'opaque_customer_42',
);
await Ferry.track(
FerryEvents.purchase(
transactionId: 'txn_1',
value: 9.99,
currency: 'USD',
productId: 'pro_monthly',
),
customerId: 'opaque_customer_42',
);

Handle a URL you already have

Use handle for a Ferry URL received through another channel, such as a push notification:

final handled = await Ferry.handle(
'https://go.acme.com/welcome?campaign=fall_sale',
);

It returns true when Ferry took ownership of the URL and delivered it through onLink.

Important behavior

  • Ferry.onLink is a broadcast stream.
  • link.isDeferred is the authoritative direct-versus-deferred field.
  • Native SDKs own installation identity, retries, batching, and matching signals.
  • configure, track, flush, and handle degrade safely when the native side is unavailable.
  • Client link creation is the deliberate exception that reports a typed failure.

Next steps