smartlinks_flutter 2.0.3
smartlinks_flutter: ^2.0.3 copied to clipboard
Unified SmartLinks Flutter SDK for analytics, feedback, apps, ads, community, and blogs.
SmartLinks Flutter SDK #
Unified Flutter SDK for analytics, deep links, in-app ads, feedback, our apps, community forums, blogs, promo codes, in-app purchase verification, and AI Gateway — with one dependency and one import.
Homepage: smartlinks.live
Repository: gitlab.com/elmansoryanas/smartlinks_flutter
Table of contents #
- Why SmartLinks
- Requirements
- Installation
- Quick start
- Platform setup
- Initialization options
- API reference
- Host app customization
- Example app
- Package map
- Umbrella vs modular packages
- Migration from Linklytics
- Troubleshooting
- Publishing
- License
Why SmartLinks #
| Capability | What you get |
|---|---|
| Analytics | Custom events, anonymous app_user_id, attribution from deep links |
| Deep linking | Deferred links, universal links, route + parameter parsing |
| Monetization | Banner / interstitial / native ads, optional FCM push ads |
| Engagement | In-app feedback, promo redemption, community & blogs UI |
| Revenue | Server-side Apple / Google purchase verification with attribution |
| AI | Native-bridge AI orchestrator + optional test chat UI |
| Branding | Global + per-screen theme and string overrides |
Production API traffic on iOS and Android goes through the native bridge hosted by smartlinks_core:
- Android: Maven
live.smartlinks:smartlinks-sdk-core - iOS: CocoaPods
SmartLinksSDK/Core(~> 2.0.1)
Requirements #
| Dart SDK | ^3.9.2 |
| Flutter | >= 3.3.0 |
| Android | API 21+ |
| iOS | 11.0+ |
| SmartLinks account | API key from smartlinks.live dashboard |
Community sign-in requires Firebase configured in your host app (Google / Apple). Ads and analytics work without Firebase.
Installation #
Recommended — umbrella package #
Add a single dependency:
dependencies:
smartlinks_flutter: ^2.0.3
flutter pub get
import 'package:smartlinks_flutter/smartlinks_flutter.dart';
Modular install (advanced) #
Use individual packages under packages/ if you only need a subset (e.g. smartlinks_core + smartlinks_analytics). Most production apps should use the umbrella.
Quick start #
import 'package:flutter/material.dart';
import 'package:smartlinks_flutter/smartlinks_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final ok = await SmartLinks.initialize(
apiKey: 'YOUR_API_KEY',
isDebug: true,
);
if (ok) {
await SmartLinks.analytics.getLink((route) {
debugPrint('Deep link: ${route.route}');
debugPrint('Params: ${route.parameters}');
});
}
runApp(const MyApp());
}
Open built-in screens from anywhere with a BuildContext:
await SmartLinks.openFeedback(
customNavigation: (page) => Navigator.push(context, MaterialPageRoute(builder: (_) => page)),
);
await SmartLinks.openApps(
customNavigation: (page) => Navigator.push(context, MaterialPageRoute(builder: (_) => page)),
);
SmartLinks.community.open();
SmartLinks.blogs.open();
await SmartLinks.showPromoDialog(context);
await SmartLinks.openAiTest(context);
Platform setup #
Android #
- Minimum SDK — ensure
minSdk≥ 21 inandroid/app/build.gradle. - Core library desugaring — required if you use
flutter_local_notifications(push ads):
// android/app/build.gradle.kts
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
- Deep links (App Links) — add intent filters to your main activity:
<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="smartlinks.live"
android:pathPrefix="/" />
</intent-filter>
Replace smartlinks.live with your configured link domain if different.
iOS #
- After adding the plugin, run:
cd ios && pod install && cd ..
- Associated Domains — in Xcode → Signing & Capabilities, add Associated Domains:
applinks:smartlinks.live
- Community (optional) — add
GoogleService-Info.plistand callFirebase.initializeApp()in your app before opening community if you use Google/Apple sign-in.
Initialization options #
await SmartLinks.initialize(
apiKey: 'YOUR_API_KEY', // required
isDebug: true, // native + Dart logs
language: 'en', // ad targeting language
initializeAds: true, // set false to skip ad module prep
enablePushAds: false, // FCM push ads (needs Firebase)
pushAppId: null, // optional push app id
firebaseProject: 'your-project', // community OAuth + core config
appearance: myAppearance, // global branding — see Customization
);
| Parameter | Default | Description |
|---|---|---|
apiKey |
— | SmartLinks dashboard API key |
isDebug |
false |
Verbose logging |
language |
device locale | Passed to ads module |
initializeAds |
true |
Calls SmartLinks.ads.prepare() |
enablePushAds |
false |
Enables SmartLinksPushHandler |
pushAppId |
null |
Push notification app identifier |
firebaseProject |
null |
Firebase project slug for community social auth |
appearance |
null |
Global SmartLinksAppearance overrides |
Returns true when core + analytics native bridge are ready.
API reference #
All methods below require SmartLinks.initialize() unless noted.
Analytics & deep links #
// Custom events
await SmartLinks.analytics.sendEvent('purchase_completed', {
'sku': 'premium_monthly',
'value': 9.99,
});
// Anonymous persisted user id (also used for ads / attribution)
final userId = await SmartLinks.analytics.getAppUserId();
// Listen for deep links (call once at startup)
await SmartLinks.analytics.getLink((DeepLinkRoute route) {
// route.route — path string
// route.parameters — query params map
// route.link — full URL
if (route.parameters.containsKey('_attribution_id')) {
// Automatically saved by SDK for purchase verification
}
});
Dynamic links #
final url = await SmartLinks.analytics.generateLink(
route: 'product/123',
params: {'referrer': 'share_button'},
shortLink: true,
);
Promo codes #
// Check local premium state (after successful redeem)
final active = await SmartLinks.isPromoActive();
final expires = await SmartLinks.getPromoExpiration();
final status = await SmartLinks.getPromoStatus(); // PromoStatus
// UI — bottom sheet or full page
final redeemed = await SmartLinks.showPromoDialog(context);
await SmartLinks.openPromoEntry(context);
// Low-level API
final validation = await SmartLinks.analytics.validatePromoCode('CODE');
final redeem = await SmartLinks.analytics.redeemPromoCode('CODE');
SmartLinks.openFeedback() uses isPromoActive() automatically when you do not pass isPremium.
In-app purchase verification #
Verify store purchases server-side (credentials configured in SmartLinks dashboard). Attribution (app_user_id, deep-link attribution_id) is attached automatically.
Apple (after a sandbox or production purchase):
final valid = await SmartLinks.analytics.verifyApplePurchase(
receipt: purchase.verificationData.serverVerificationData,
);
Google (both fields required):
final valid = await SmartLinks.analytics.verifyGooglePurchase(
productId: purchase.productID,
purchaseToken: purchase.verificationData.serverVerificationData,
);
Use real purchase data from in_app_purchase or your billing SDK. Test on physical devices with sandbox / license testers.
Debug raw response:
import 'package:smartlinks_core/smartlinks_core.dart';
final result = await SmartLinksNativeApi.verifyGooglePurchase(
productId: 'your_sku',
token: 'purchase_token',
);
debugPrint('$result'); // e.g. {valid: true}
Feedback #
await SmartLinks.openFeedback(
isPremium: false, // optional; defaults to promo status
feedbackStrings: FeedbackStrings(pageTitle: 'Contact us'),
theme: SmartLinksTheme(accentColor: Colors.teal),
customNavigation: (page) => Navigator.push(
context,
MaterialPageRoute(builder: (_) => page),
),
);
Supports 30+ languages via FeedbackStrings.auto() when strings are not overridden.
Our Apps #
await SmartLinks.openApps(
appsStrings: AppListStrings(pageTitle: 'More from us'),
customNavigation: (page) => Navigator.push(
context,
MaterialPageRoute(builder: (_) => page),
),
);
Community #
Pre-built forums UI with optional Google / Apple sign-in.
SmartLinks.community.open(
bannerAd: () => SmartLinkBannerAd(adService: SmartLinks.ads),
theme: SmartLinksTheme(accentColor: Colors.indigo),
communityStrings: CommunityStrings(pageTitle: 'Community'),
);
Firebase: configure Firebase in your host app. Pass firebaseProject to SmartLinks.initialize() so social auth matches your dashboard.
Community list is visible without login; sign-in is prompted for posting, liking, and commenting.
Blogs #
SmartLinks.blogs.open(
theme: SmartLinksTheme(accentColor: Colors.indigo),
blogsStrings: BlogsStrings(pageTitle: 'News'),
);
Ads #
Initialized by default via SmartLinks.initialize(). Display a banner:
SmartLinkBannerAd(adService: SmartLinks.ads)
Interstitial and native ads:
await SmartLinks.ads.showInterstitial();
// See packages/smartlinks_ad/README.md for native ad builders
Skip ads at init: SmartLinks.initialize(..., initializeAds: false).
Push ads (optional) #
await SmartLinks.initialize(
apiKey: 'YOUR_KEY',
enablePushAds: true,
pushAppId: 123,
);
Requires Firebase (Firebase.initializeApp() before init). See smartlinks_ad_push for FCM setup.
AI Gateway #
Headless orchestrator (production) or test UI (integrators):
// Test harness screen
await SmartLinks.openAiTest(context);
// Programmatic — multi-step pipelines
final response = await SmartLinks.ai.chat(
AiChatOptions(
messages: [AiChatMessage(role: 'user', content: 'Hello')],
),
);
if (response.success) {
debugPrint('${response.results}');
}
AI calls require the native bridge (not available on web/desktop).
Host app customization #
Pass branding once at init, override per screen when opening modules.
Global appearance #
const appearance = SmartLinksAppearance(
theme: SmartLinksTheme(
accentColor: Color(0xFF6A1B9A),
cardColorDark: Color(0xFF1A1A2E),
borderRadius: 14,
gradientStart: Color(0xFF6A1B9A),
gradientEnd: Color(0xFFAB47BC),
),
feedbackStrings: FeedbackStrings(pageTitle: 'Send Feedback'),
appsStrings: AppListStrings(pageTitle: 'Our Apps'),
communityStrings: CommunityStrings(pageTitle: 'Communities'),
blogsStrings: BlogsStrings(pageTitle: 'Blog'),
promoStrings: PromoStrings(dialogTitle: 'Enter promo code'),
aiStrings: AiStrings(pageTitle: 'AI Assistant'),
);
await SmartLinks.initialize(apiKey: 'YOUR_KEY', appearance: appearance);
Per-screen override #
SmartLinks.community.open(
theme: SmartLinksTheme(accentColor: Colors.teal),
communityStrings: CommunityStrings(pageTitle: 'Support Forum'),
);
await SmartLinks.openFeedback(
theme: SmartLinksTheme(accentColor: Colors.orange),
);
Theme tokens #
SmartLinksTheme field |
Used for |
|---|---|
accentColor |
App bars, buttons, links, FABs |
cardColorLight / cardColorDark |
Cards, sheets, post backgrounds |
borderRadius |
Inputs, cards, chips |
gradientStart / gradientEnd |
Community avatars |
Unset colors fall back to the host app ThemeData.
String bundles #
| Class | Overrides |
|---|---|
FeedbackStrings |
Feedback form labels |
AppListStrings |
Apps list titles, empty states |
CommunityStrings |
Page title, join CTA, snackbar messages |
BlogsStrings |
Blog list, search, share labels |
PromoStrings |
Promo dialog / entry screen |
AiStrings |
AI test page labels |
Community and blogs still use generated l10n for strings you do not override.
Example app #
git clone https://gitlab.com/elmansoryanas/smartlinks_flutter.git
cd smartlinks_flutter
dart pub get
cd example
flutter run
iOS: cd ios && pod install && cd .. && flutter run
The example demonstrates init with custom appearance, analytics, deep links, promo, AI test, feedback, apps, community, blogs, and banner ads. See example/README.md.
Package map #
| Pub package | Role |
|---|---|
smartlinks_flutter |
Umbrella — use this in apps |
smartlinks_core |
Init, identity, native bridge, SmartLinksTheme |
smartlinks_analytics |
Events, deep links, promo APIs, purchase verify |
smartlinks_feedback |
Feedback UI |
smartlinks_apps |
Our Apps UI |
smartlinks_community |
Community forums UI |
smartlinks_blogs |
Blogs UI |
smartlinks_navigation |
Navigator helpers for community/blogs |
smartlinks_ad |
Banner, interstitial, native ads |
smartlinks_ad_push |
FCM push ads |
smartlinks_ai |
AI Gateway client + test UI |
Umbrella vs modular packages #
| Use case | Dependency |
|---|---|
| Full SmartLinks integration | smartlinks_flutter |
| Analytics + deep links only | smartlinks_core + smartlinks_analytics |
| Custom UI, own networking | smartlinks_core (native bridge only) |
| Single module (e.g. feedback) | smartlinks_feedback + smartlinks_core |
When using the umbrella, do not call SmartLinksAnalytics().initialize() separately — SmartLinks.initialize() handles it.
Migration from Linklytics #
| Before (1.x) | After (2.x) |
|---|---|
import 'package:linklytics/...' |
import 'package:smartlinks_flutter/smartlinks_flutter.dart' |
Linklytics.initialize() |
SmartLinks.initialize() |
LinklyticsAnalytics() |
SmartLinks.analytics |
| Per-package git URLs | smartlinks_flutter: ^2.0.3 on pub.dev |
Troubleshooting #
| Symptom | Likely cause | Fix |
|---|---|---|
SmartLinks modules are not ready |
initialize() returned false or not awaited |
Check API key; call before other APIs |
| Community crash on open | Firebase not configured | Add google-services / GoogleService-Info.plist |
| Deep links not received | Missing intent filter / associated domains | See Platform setup |
type 'double' is not a subtype of type 'int' |
Native JSON numeric fields | Upgrade to latest 2.0.1+ |
| AI test fails on desktop | No native bridge | Test on iOS/Android device |
| Ads empty | No inventory / wrong API key | Verify dashboard ad configuration |
Purchase verify always false |
Sandbox token or dashboard credentials | Use real test purchase; check Play/App Store setup in dashboard |
Enable debug logging: SmartLinks.initialize(isDebug: true).
Publishing #
Maintainers: see PUBLISHING.md for version sync, dry-run, and pub.dev publish order.
License #
MIT — see LICENSE.