Link creation
Generate smart links and read link details in your Flutter app.
Create smart links from your app with generateLink, and read an existing link with linkDetails.
Generating a link
Pass metadata, tracking and redirects. It returns the URL as a String:
import 'package:flutter/foundation.dart';
import 'package:grovs_flutter_plugin/grovs.dart';
import 'package:grovs_flutter_plugin/models/grovs_link.dart';
final grovs = Grovs();
Future<String> createShareLink() async {
try {
final link = await grovs.generateLink(
GenerateLinkParams(
title: 'Check out this product',
subtitle: 'Limited time offer',
imageURL: 'https://example.com/image.jpg',
data: {
'screen': 'product',
'productId': '12345',
},
tags: ['promotion', 'share'],
tracking: TrackingParams(
utmCampaign: 'spring_sale',
utmSource: 'in_app',
utmMedium: 'share_button',
),
),
);
debugPrint('Generated: $link');
return link;
} on GrovsException catch (e) {
debugPrint('Error: ${e.message} (${e.code})');
rethrow;
}
}The SDK must be configured, enabled and authenticated. Failures throw GrovsException with code GENERATION_ERROR. The message is the native error text on Android, a generic message on iOS.
Parameters
| Parameter | Type | Description |
|---|---|---|
title | String | Link preview title (required) |
subtitle | String? | Link preview subtitle |
imageURL | String? | Link preview image URL |
data | Map<String, dynamic>? | Custom payload delivered on deep link open |
tags | List<String>? | Tags for filtering and analytics |
customRedirects | CustomRedirects? | Override the default redirect per platform. See Custom redirects |
showPreviewIos | bool? | Show the link preview page on iOS. null uses the project default |
showPreviewAndroid | bool? | Show the link preview page on Android. null uses the project default |
copyToClipboardIos | bool? | Copy the link to the clipboard from the preview page on iOS, for clipboard-assisted deferred deep linking. null inherits the project setting |
copyToClipboardAndroid | bool? | Same, for Android. null inherits the project setting |
tracking | TrackingParams? | UTM campaign, source and medium |
copyToClipboardIos and copyToClipboardAndroid apply only when that platform shows the preview page. Passing false is an explicit override, unlike omitting the parameter. Project setting and visitor experience: Copy to Clipboard.
On Android, data values that are strings, numbers, booleans or otherwise serializable pass through; anything else goes through toString(). iOS passes the map unchanged.
Custom redirects
Override where a link sends users per platform:
final link = await grovs.generateLink(
GenerateLinkParams(
title: 'Special offer',
data: {'promoId': 'summer25'},
customRedirects: CustomRedirects(
ios: CustomLinkRedirect(url: 'https://example.com/ios-promo'),
android: CustomLinkRedirect(url: 'https://example.com/android-promo'),
desktop: CustomLinkRedirect(
url: 'https://example.com/desktop-promo',
openAppIfInstalled: false,
),
),
),
);With openAppIfInstalled true (default), the app opens if installed, otherwise the redirect URL is used. With false, the redirect URL is always used.
Sharing the link
Open the share sheet once the link is ready, for example with share_plus:
import 'package:share_plus/share_plus.dart';
final link = await grovs.generateLink(
GenerateLinkParams(title: 'Share this', data: {'itemId': 'abc'}),
);
await Share.share(link);Link details
linkDetails fetches a link by its path, the last part of the link. For https://yourapp.sqd.link/abc123 the path is abc123. Pass the path only, not the full URL.
try {
final details = await grovs.linkDetails('abc123');
debugPrint('${details.title} ${details.data} ${details.tracking?.utmCampaign}');
} on GrovsException catch (e) {
debugPrint('Error ${e.code}: ${e.message}');
}GrovsException.code | Raised when |
|---|---|
INVALID_ARGUMENT | The path is empty or only whitespace. Checked in Dart. |
SDK_DISABLED | The SDK is disabled with setSDK(false). |
LINK_DETAILS_ERROR | The link wasn't found or the request failed. |
The result is a GrovsLinkDetails. A field whose value has an unexpected type is null. raw holds every field the backend sent, as received; its numbers can be doubles on Android and ints on iOS, while the typed fields are the same on both platforms.