Skip to main content

adsparkle_flutter 0.1.9 copy "adsparkle_flutter: ^0.1.9" to clipboard
adsparkle_flutter: ^0.1.9 copied to clipboard

PlatformAndroid

Flutter client SDK for the AdSparkle affiliate attribution tracking platform. Deterministic Android install attribution via the Play Install Referrer; pure Dart on every other platform.

adsparkle_flutter #

Flutter client SDK for the AdSparkle affiliate attribution tracking platform. Deterministic Android install attribution via the Play Install Referrer; pure Dart on every other platform.

Mobile apps use this SDK to capture an attribution click_id from a deep link and send affiliate attribution events (install, sign up, purchase, …) to the tracking API.

Installation #

flutter pub add adsparkle_flutter

Or add to your app's pubspec.yaml manually:

dependencies:
  adsparkle_flutter: ^0.1.8

Then:

flutter pub get

Quick start #

import 'package:adsparkle_flutter/adsparkle_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await AdSparkle.instance.configure(
    companyKey: 'co_xxxxxxxxxxxxxxxx', // publishable key (see note below)
    // baseUrl: the domain your tracking links are served from. Use the link
    // domain on the panel's Integration page (<subdomain>.go.adsparkle.co), or
    // your custom tracking domain if you set one up. On iOS, deferred
    // attribution can fail when links and SDK requests use different hosts.
    baseUrl: 'https://YOUR_TRACKING_DOMAIN',
    debug: true,                       // verbose logs in debug builds
    // Optional — only needed when your tracking links use a custom domain:
    // linkDomainSuffix: '.go.adsparkle.co', // default
    // extraLinkHosts: ['click.merchant.com'],
  );

  runApp(const MyApp());
}

A universal-link / App Links URL is recognised as a tracking link when its host ends with linkDomainSuffix, equals the baseUrl host, or equals / is a subdomain of an entry in extraLinkHosts. For such links opened while the app is already installed, the SDK registers the click with the backend using the last non-empty path segment as the link key (works for both /<key> and multi-app /<appSlug>/<key> links).

Identifying the user #

Set the end-user identifier once you know it (e.g. after login). It is persisted across launches.

await AdSparkle.instance.setUserId('user-123');

The attribution click_id arrives as a deep link query parameter:

https://app.example.com/open?click_id=2f1c9b7e-...

Pass any incoming Uri to handleDeepLink; the SDK extracts, persists, and chains the click_id (most-recent-last, de-duplicated, capped at 50).

import 'package:app_links/app_links.dart';

final appLinks = AppLinks();

// Cold start
final initial = await appLinks.getInitialLink();
if (initial != null) {
  await AdSparkle.instance.handleDeepLink(initial);
}

// While running
appLinks.uriLinkStream.listen((uri) {
  AdSparkle.instance.handleDeepLink(uri);
});

With go_router #

GoRouter(
  redirect: (context, state) {
    AdSparkle.instance.handleDeepLink(state.uri);
    return null; // don't redirect; just harvest the click_id
  },
  routes: [...],
);

You can also set it manually if you obtain it another way:

await AdSparkle.instance.setClickId('2f1c9b7e-...');

Tracking events #

Use the typed helpers, or the generic track(eventType, …):

await AdSparkle.instance.trackInstall();
await AdSparkle.instance.trackSignUp();
await AdSparkle.instance.trackLogin();
await AdSparkle.instance.trackDownload();

await AdSparkle.instance.trackPurchase(
  transactionId: 'txn_001',
  amount: 9.99,
  currency: 'USD',
  productIds: ['premium_monthly'],
  customParams: {'campaign': 'summer'},
);

await AdSparkle.instance.trackSubscription(
  transactionId: 'sub_001',
  amount: 49.99,
  currency: 'USD',
);

await AdSparkle.instance.trackRefund(transactionId: 'txn_001');

// Generic form:
await AdSparkle.instance.track(
  'purchase',
  transactionId: 'txn_002',
  amount: 4.50,
  currency: 'EUR',
);

If there is no click_id yet, the event is saved to a persisted deferred queue and sent automatically once a click_id arrives (deep link, Install Referrer, /match, or register-click). If no user_id was set, a persistent anonymous identifier is generated. track never throws.

Event types #

Event Wire value Helper Required extra fields
Install install trackInstall —
Sign up sign_up trackSignUp —
Login login trackLogin —
Download download trackDownload —
Purchase purchase trackPurchase transactionId, amount
Subscription subscription trackSubscription transactionId, amount
Refund refund trackRefund transactionId

Besides the built-ins above, a company custom-event shortId (e.g. YE2YFSQ) can be passed directly as the event_type:

await AdSparkle.instance.track(
  'YE2YFSQ',
  productIds: ['premium_monthly'],
  customParams: {'campaign': 'summer'},
);

The value is validated against ^[A-Za-z0-9_]{1,64}$ (mixed case — shortIds are uppercase, built-in keys lowercase) and sent as-is on the wire; values that fail this format check are ignored. product_ids and custom_params are already supported by track (and the typed helpers) for every event type.

Reliability #

  • Postbacks go to POST {baseUrl}/api/tracking/postback.
  • On 5xx/408/429 responses or network errors the SDK retries up to 3 times with exponential backoff.
  • If all attempts fail, the event is saved to a persisted pending queue (shared_preferences) and re-sent on the next track() / configure().
  • Other 4xx responses are treated as permanent and the event is dropped.

Debug diagnostics — see the chain on the device #

debugPrint is useless when you are testing a release-ish build on a real phone and are not attached to flutter run / Xcode / logcat. Turn on debug: true and wrap your app with AdSparkleDebugOverlay to get the SDK's diagnostics on screen:

await AdSparkle.instance.configure(companyKey: 'co_xxx', debug: true);

MaterialApp(
  builder: (context, child) =>
      AdSparkleDebugOverlay(child: child ?? const SizedBox.shrink()),
  home: const HomePage(),
);

You will see one short line per step, newest on top:

AdSparkle 0.1.9 hazir | baseUrl=acme.go.adsparkle.co | suffix=.go.adsparkle.co
Link geldi: https://acme.go.adsparkle.co/abc123
Tiklama kaydediliyor: key=abc123
click_id alindi: 7f3a9c21
purchase gonderildi ✓
  • Tap the bar to expand/collapse the list, long-press it (or use the copy button) to copy the whole buffer to the clipboard and send it to support. Buttons on the bar clear the list or dismiss the panel.
  • The message list is IgnorePointer, so it never blocks the UI underneath.
  • The exact same messages are produced by the iOS, Android and React Native SDKs, so support can read any platform's log the same way.

Using your own toast instead #

If your app already has a toast/snackbar, take the messages directly — the overlay is then unnecessary (a handler takes priority; a message is shown exactly once):

setDebugHandler((String message) => showMySnackBar(message));

setDebugHandler(null) removes the hook. subscribeDebug(listener) is the low-level alternative and returns an unsubscribe function; on subscribe it replays the buffered history so a late listener does not miss the first steps.

What is not shown #

companyKey, any postback secret, device_id and the full click_id are never printed. click_id appears as its first 8 characters only, and URLs / keys are truncated to 60. With debug: false (the default) not a single diagnostic string is built and the overlay renders only its child — zero production impact.

Security note — the company key is publishable #

companyKey is a publishable co_ key. It is safe to ship inside your app binary. It is not a secret. This SDK never uses an HMAC secret and never signs requests — secret-based signing happens server-side only.

Reading the current click id #

final id = AdSparkle.instance.clickId; // String?

Attribution callback #

Register a callback to be notified the moment a click_id becomes active — no polling needed. It fires for every source (deep-link ?click_id, register-click, Play Install Referrer, iOS /match):

AdSparkle.instance.onClickId = (String clickId) {
  debugPrint('attributed: $clickId');
};
  • If a click_id is already available when you set the handler, it is invoked immediately (once, asynchronously) with the current value — so a late-registered handler never misses the attribution moment.
  • The same value never fires twice in a row; a different new click_id fires again.
  • Set to null to remove the handler. The callback is optional — polling AdSparkle.instance.clickId remains a valid alternative.
0
likes
130
points
346
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter client SDK for the AdSparkle affiliate attribution tracking platform. Deterministic Android install attribution via the Play Install Referrer; pure Dart on every other platform.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, http, shared_preferences

More

Packages that depend on adsparkle_flutter

Packages that implement adsparkle_flutter