smartlinks_flutter 2.0.3 copy "smartlinks_flutter: ^2.0.3" to clipboard
smartlinks_flutter: ^2.0.3 copied to clipboard

Unified SmartLinks Flutter SDK for analytics, feedback, apps, ads, community, and blogs.

SmartLinks Flutter SDK #

pub package

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 #


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 #

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 #

  1. Minimum SDK — ensure minSdk ≥ 21 in android/app/build.gradle.
  2. 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")
}
  1. 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 #

  1. After adding the plugin, run:
cd ios && pod install && cd ..
  1. Associated Domains — in Xcode → Signing & Capabilities, add Associated Domains:
applinks:smartlinks.live
  1. Community (optional) — add GoogleService-Info.plist and call Firebase.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.

// 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
  }
});
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.