Flutter SDK
Create and manage deep links in your Flutter iOS & Android apps
Installation
Add to your pubspec.yaml:
dependencies:
baxcloud_links_sdk: ^1.0.0+1Then run:
flutter pub getDevice info (device model, OS version) is collected automatically using device_info_plus. No extra setup needed.
Quick Start
1. Initialize the SDK
1import 'package:baxcloud_links_sdk/baxcloud_links_sdk.dart';
2
3final links = BaxCloudLinksClient(
4 config: BaxCloudLinksConfig(
5 projectId: 'your-project-id',
6 apiKey: 'your-api-key',
7 debug: true, // Enable SDK debug logs (disable in production)
8 ),
9);2. Create a Deep Link
iOS/Android store URLs are configured once in the Dashboard → BaxLinks → Setup. You only pass link-specific data:
1final link = await links.createLink(
2 CreateLinkOptions(
3 fallbackUrl: 'https://yourapp.com/invite?code=ABC123',
4 deepLinkPath: '/invite/ABC123',
5 deepLinkParams: {'inviteCode': 'ABC123', 'referrer': 'john'},
6 title: 'Join us on MyApp!',
7 ),
8);
9
10// Short URL from project subdomain (e.g. https://xxxxx.baxcloud.link/abc123)
11print(link.shortUrl);3. Track Install (device info auto-collected)
1// Device ID, model, OS, OS version collected automatically
2await links.trackInstall(appVersion: '1.0.0');4. Get Deferred Deep Link
1// On first launch — device fingerprint matched automatically
2final result = await links.getDeferredLink();
3
4if (result.found && result.deepLinkPath != null) {
5 Navigator.of(context).pushNamed(
6 result.deepLinkPath!,
7 arguments: result.deepLinkParams,
8 );
9}Debug Logging
Trace SDK activity during development
Set debug: true in the config to see detailed SDK activity in the console. All messages are prefixed with [BaxCloudLinks]. Disable in production.
[BaxCloudLinks] BaxCloudLinks SDK initialized (project: abc123)
[BaxCloudLinks] handleDeepLink: https://xxx.baxcloud.link/mTX4Jw (scheme=https)
[BaxCloudLinks] resolveLink: mTX4Jw
[BaxCloudLinks] GET .../v1/sdk/links/resolve/mTX4Jw → 200
[BaxCloudLinks] handleDeepLink: resolved params={type: post, objectId: abc}Handling Incoming Deep Links
Resolve short links and URI scheme links automatically
The SDK provides handleDeepLink(Uri) which automatically detects HTTPS short links (App Links / Universal Links) and resolves them via the API, or extracts query parameters directly from URI scheme links. Returns a Map<String, dynamic>? or null.
Recommended Setup
1late BaxCloudLinksClient _linksClient;
2StreamSubscription? _linkSubscription;
3
4void initLinks() {
5 _linksClient = BaxCloudLinksClient(
6 config: BaxCloudLinksConfig(
7 projectId: 'your-project-id',
8 apiKey: 'your-api-key',
9 debug: true,
10 ),
11 );
12
13 _handleInitialLink();
14
15 _linkSubscription = _linksClient.listenForLinks(
16 (uri) => _handleDeepLink(uri),
17 );
18}
19
20Future<void> _handleInitialLink() async {
21 final uri = await _linksClient.getInitialLink();
22 if (uri == null) return;
23
24 // IMPORTANT: On cold start the Navigator may not be mounted yet.
25 await Future.delayed(const Duration(milliseconds: 500));
26
27 await _handleDeepLink(uri);
28}
29
30Future<void> _handleDeepLink(Uri uri) async {
31 final params = await _linksClient.handleDeepLink(uri);
32 if (params == null) return;
33
34 final type = params['type']?.toString();
35 final objectId = params['objectId']?.toString();
36
37 if (type == 'post' && objectId != null) {
38 // Navigate to post screen
39 } else if (type == 'profile' && objectId != null) {
40 // Navigate to profile screen
41 }
42}Cold-Start Deep Links
When the app is opened from a fully closed state via a link, getInitialLink() returns the URI before the widget tree (Navigator, Overlay) is mounted. Navigating immediately causes: '_elements.contains(element)': is not true. Always add a short delay or use WidgetsBinding.instance.addPostFrameCallback before navigating.
Recommended: Initialize the deep link listener after runApp() — e.g. inside your root widget's initState() — rather than in main().
Resolve a Short Link Manually
1final result = await links.resolveLink('mTX4Jw');
2// { found: true, deepLinkPath: '/post/abc',
3// deepLinkParams: { type: 'post', objectId: 'abc' } }Extract Slug from URI
1final slug = links.extractSlugFromUri(
2 Uri.parse('https://xxx.baxcloud.link/mTX4Jw'),
3);
4// 'mTX4Jw'Event Tracking
Device info (ID, model, OS, version) is collected automatically — no manual deviceId needed
Convenience Methods
1// First launch — attributes install to a link click
2await links.trackInstall(appVersion: '1.0.0');
3
4// Every app open
5await links.trackOpen(appVersion: '1.0.0');
6
7// After signup
8await links.trackSignup();
9
10// After a purchase
11await links.trackPurchase(29.99, eventData: {'planId': 'pro'});
12
13// Custom event
14await links.trackCustomEvent('level_complete', eventValue: 5);Low-level trackEvent
1// Use trackEvent() for full control
2await links.trackEvent(
3 TrackEventOptions(
4 eventType: BaxLinkEventType.custom,
5 eventName: 'level_complete',
6 eventValue: 5,
7 linkSlug: 'invite-john', // attribute to a specific link
8 platform: 'flutter',
9 ),
10);Event Types: installopenreinstallsignuppurchasecustom
Deferred Deep Linking
Navigate users to the right screen after install
Call getDeferredLink() on first launch. BaxCloud fingerprints the device IP and matches it to a recent link click (48-hour window).
Full Implementation
1import 'package:shared_preferences/shared_preferences.dart';
2
3Future<void> checkDeferredLink(BuildContext context) async {
4 final prefs = await SharedPreferences.getInstance();
5 if (prefs.getBool('bax_deferred_checked') ?? false) return;
6 await prefs.setBool('bax_deferred_checked', true);
7
8 // Track install (device info auto-collected)
9 await links.trackInstall(appVersion: '1.0.0');
10
11 // Check for deferred deep link
12 final result = await links.getDeferredLink();
13 if (result.found && result.deepLinkPath != null) {
14 Navigator.of(context).pushNamed(
15 result.deepLinkPath!,
16 arguments: result.deepLinkParams,
17 );
18 }
19}How it works: Device IP is matched to a recent click within 48 hours. Returns deepLinkPath + deepLinkParams.
Attribution & Install Tracking
Query attributed installs for referral rewards
When an install event is reported, BaxCloud matches it to a link click via IP fingerprinting (7-day window).
Query Attributed Installs
1final result = await links.getAttributedInstalls();
2print('Total: ${result.total}');
3
4for (final install in result.data) {
5 print('${install.linkSlug} · ${install.os} · ${install.country}');
6}
7
8// Filter by link
9final linkInstalls = await links.getAttributedInstalls(
10 linkId: 'your-link-id',
11 page: 1,
12 limit: 20,
13);Attribution Webhook
A link.install.attributed webhook fires on your server when attribution succeeds:
1{
2 "event": "link.install.attributed",
3 "linkSlug": "invite-john",
4 "deepLinkPath": "/invite/REF456",
5 "deepLinkParams": { "referralCode": "REF456" },
6 "attributedAt": "2025-01-15T10:30:00.000Z",
7 "install": { "os": "iOS", "appVersion": "1.0.0", "country": "US" }
8}API Reference
Link Management
createLink(options)Create a new deep linkgetLink(linkId)Get a link by IDlistLinks(params?)List project linksupdateLink(id, options)Update a linkdeleteLink(id)Delete a linkEvent Tracking
trackInstall({appVersion?})Track first install — auto device infotrackOpen({appVersion?})Track app open — auto device infotrackSignup({eventData?})Track signup — auto device infotrackPurchase(value, {eventData?})Track purchase — auto device infotrackCustomEvent(name, {value?, eventData?})Track custom eventtrackEvent(TrackEventOptions)Low-level event trackingDeep Linking & Attribution
handleDeepLink(uri)Resolve any incoming URI — HTTPS short links via API, URI scheme directlyresolveLink(slug)Resolve a short link slug to deep link data via the APIextractSlugFromUri(uri)Extract the slug from a short link URLgetInitialLink()Get the initial deep link URI that opened the app (cold start)listenForLinks(onLink)Listen for incoming deep links while app is runninggetDeferredLink()Retrieve deferred deep link (auto device ID)getAttributedInstalls(opts?)Query attributed installsgetAppConfig()Get project config + shortLinkBasegetShortUrl(link)Returns link.shortUrl (e.g. https://xxxxx.baxcloud.link/slug)Platform Setup
Required native configuration for deep link handling. Get your subdomain from Dashboard → BaxLinks → Setup.
Android — Disable Flutter deep linking
In AndroidManifest.xml inside your <activity>:
<meta-data
android:name="flutter_deeplinking_enabled"
android:value="false" />
<!-- URI Scheme (e.g. myapp://invite/ABC123) -->
<intent-filter>
<data android:scheme="@string/baxcloud_links_scheme" android:host="*" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<!-- App Links (HTTPS) -->
<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="@string/baxcloud_links_default_url" />
</intent-filter>Android — res/values/strings.xml
<resources>
<string name="app_name">YourApp</string>
<!-- Your URI scheme, e.g. "myapp" -->
<string name="baxcloud_links_scheme">myapp</string>
<!-- Replace xxxxx with YOUR project subdomain from Dashboard → BaxLinks → Setup -->
<string name="baxcloud_links_default_url">xxxxx.baxcloud.link</string>
</resources>iOS — Runner.entitlements
<key>com.apple.developer.associated-domains</key>
<array>
<!-- Wildcard covers all xxxxx.baxcloud.link subdomains (iOS 14+) -->
<string>applinks:*.baxcloud.link</string>
</array>iOS — URI Scheme in Info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>