ReflectDocs
Browse docsOverview
Flutter SDK

Flutter SDK

Reflect SDK for Flutter — a thin Dart + native bridge over the shared ReflectCore engine. Mobile attribution, event tracking, deep linking, and SKAN for iOS and Android.

v1.7.0 — thin wrapper over the shared native core
As of v1.7.0 the plugin runs on Reflect's shared ReflectCore engine — the same Kotlin (reflect-android) and Swift (reflect-ios) core the React Native and Unity SDKs use. All logic (durable on-disk queue, HMAC-signed ingest, batching, response-driven retry, device signals, deferred deep links, attribution, SKAN, ATT) lives in the core; the Dart layer only forwards each call over a method channel. 1.6.0 and earlier were a standalone re-implementation that posted unsigned events — 1.7.0 is a native rewrite, but the public Dart API stays backward-compatible and gains new methods. Yourinstall_uuid is preserved across the upgrade.

Installation

Add the dependency to your pubspec.yaml, pinned to a release tag:

dependencies:
  reflect_sdk:
    git:
      url: https://github.com/bablu147/reflect-sdk-flutter.git
      ref: v1.7.0

Then run flutter pub get. Because the plugin pulls its native core as a versioned dependency, a consumer app needs two one-time additions so the published cores resolve.

Android — add the JitPack repo in your app's android/settings.gradle:

dependencyResolutionManagement {
  repositories {
    maven { url 'https://jitpack.io' }   // com.github.bablu147:reflect-android
  }
}

The AAR brings its transitive dependencies (Play Install Referrer, App Set ID, ads-identifier) and R8 keep-rules automatically.

iOS — run cd ios && pod install. If the ReflectCore pod is not yet on CocoaPods trunk, add it to your ios/Podfile:

pod 'ReflectCore', :git => 'https://github.com/bablu147/reflect-ios.git', :tag => '1.0.0'

Requirements

  • Dart >=3.0.0, Flutter >=3.10.0
  • Android: minSdkVersion 21
  • iOS: 12+
  • Pulls the shared ReflectCore native engine (JitPack AAR on Android, the ReflectCore pod on iOS) — no other third-party dependencies

Quick start

import 'package:reflect_sdk/reflect_sdk.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Reflect.initialize(ReflectConfig(
    appKey:        "app_live_...",
    companyKey:    "co_live_...",
    baseUrl:       "https://api.reflect.cloud",
    // signingSecret: "sec_...",  // optional — HMAC-signs ingest + surfaces attribution
  ));

  runApp(MyApp());
}

With a signingSecret set, every event batch is HMAC-signed and posted to the authenticated /event endpoint; without one the SDK falls back to the unsigned /event/batch path.

API reference

MethodDescription
Reflect.initialize(config)Initialize the SDK (call once at app start)
Reflect.trackEvent(name, properties?)Track a named event with optional properties
Reflect.trackRevenue(params)Track a revenue event
Reflect.trackPurchase(params)Track a purchase event with optional receipt
Reflect.trackSubscription(params)Track a subscription event
Reflect.verifyPurchase(params)Verify a receipt server-side and return a typed result
Reflect.verifyAndTrackPurchase(params)Verify a receipt AND track the purchase
Reflect.trackAdRevenue(params)Track mediated ad revenue (fires ad_impression)
Reflect.setUserId(userId)Set user ID for cross-device attribution
Reflect.clearUserId()Clear user ID (e.g. on logout)
Reflect.setEmail(email)Attach the user's RAW email to future events (server hashes it; consent-gated) — enables email attribution
Reflect.clearEmail()Clear the stored email (e.g. on logout)
Reflect.setUserProperties(props)Set properties attached to all future events
Reflect.setGlobalProperty(key, val)Set a property merged into every event
Reflect.unsetGlobalProperty(key)Remove a global property
Reflect.clearGlobalProperties()Remove all global properties
Reflect.setPartnerParameter(key, val)Set a global partner parameter forwarded to integrations
Reflect.setPartnerSharing(map)Per-partner third-party-sharing overrides
Reflect.setThirdPartySharing(enabled)Opt in/out of partner data sharing
Reflect.setConsent(state) / getConsent()Set/read data-collection consent (attached as consent_state)
Reflect.setAdvertisingConsent(granted)Grant/revoke IDFA/GAID consent
Reflect.setExternalDeviceId(id)Attach a customer-owned device identifier
Reflect.requestIosTracking()Request iOS ATT permission (returns status)
Reflect.getInstallUuid()Get the persistent install UUID
Reflect.getAttribution()Get current attribution data
Reflect.getAttributionWithTimeout(ms)Force a fresh attribution check, resolving early or after the timeout
Reflect.onAttributionChangedStream firing when the server resolves/changes attribution
Reflect.updateConversionValue(...)Update SKAN conversion value (iOS only)
Reflect.getInitialDeepLink()Get the deep link that opened the app
Reflect.getLastDeepLink()The last deep link handled (cold/warm/deferred)
Reflect.onDeepLinkStream of deep link events while running
Reflect.resolveDeepLink(url)Unshorten/resolve a branded tracking URL via the server
Reflect.handleDeepLink(url)Feed the SDK a link the app captured itself
Reflect.registerPushToken(token, provider)Register a push token (fires _push_token)
Reflect.setPushToken(token)Sticky push token stamped on every event
Reflect.setIntegrityToken(token)Supply a Play Integrity / App Attest token (anti-fraud)
Reflect.setAudience(tags)Tag the install for audience segmentation
Reflect.deleteUserData()GDPR — delete all user data
Reflect.setEnabled(enabled) / isEnabled()Enable/disable the SDK at runtime
Reflect.setOfflineMode(offline)Pause/resume sending (keeps tracking + queuing on-device)
Reflect.flush()Force-flush buffered events
Reflect.debugSnapshot()PII-safe snapshot of SDK state (drives ReflectDebugOverlay)

Event tracking

// Simple event
await Reflect.trackEvent("level_complete", properties: {
  "level": 5,
  "score": 12340,
});

// Revenue event
await Reflect.trackRevenue(RevenueParams(
  amount: 4.99,
  currency: "USD",
  productId: "gems_500",
  transactionId: "txn_abc123",
));

// Attribute installs/revenue to an email (pass it RAW — the server hashes it;
// only sent while consent is not denied).
await Reflect.setEmail("[email protected]");
await Reflect.clearEmail();   // on logout

The SDK sends the event property bag on the wire as properties; the server maps it to its canonical props field, so props.email reaches attribution. See Privacy & consent for the consent gate and hashing details.

Deep linking

// Get the link that launched the app (incl. server-resolved deferred links)
final initial = await Reflect.getInitialDeepLink();
if (initial != null) {
  navigateTo(initial.path);
}

// Listen for links while running (isDeferred = true for deferred links)
Reflect.onDeepLink.listen((data) {
  navigateTo(data.path);
});

SKAN (iOS)

final result = await Reflect.updateConversionValue(
  42,
  coarseValue: "high",
  lockWindow: false,
);
if (!result.success) print("SKAN error: ${result.error}");

Standard events

Pre-built helpers with typed parameters:

import 'package:reflect_sdk/reflect_sdk.dart';

ReflectStandardEvents.signUpWith("google");
ReflectStandardEvents.levelCompleted(5, score: 12340);
ReflectStandardEvents.addedToCart("gems_500", 4.99, "USD");
ReflectStandardEvents.adShown("admob", "interstitial", revenue: 0.02, currencyCode: "USD");

Global properties

await Reflect.setGlobalProperty("ab_group", "variant_b");
await Reflect.unsetGlobalProperty("ab_group");
await Reflect.clearGlobalProperties();

Purchase & subscription

await Reflect.trackPurchase(PurchaseParams(
  productId: "gems_500",
  price: 4.99,
  currency: "USD",
  receiptData: "<base64-receipt>",
));

await Reflect.trackSubscription(SubscriptionParams(
  productId: "pro_monthly",
  price: 9.99,
  currency: "USD",
  isTrial: true,
));

// Verify a receipt server-side AND track it in one call
final result = await Reflect.verifyAndTrackPurchase(PurchaseParams(
  productId: "gems_500",
  transactionId: "txn_abc123",
  receiptData: "<base64-receipt>",
));

Privacy (GDPR)

final deleted = await Reflect.deleteUserData();
// Clears local state + sends deletion request to server
v1.7.0 — shared native core, signed ingest
Running on the shared ReflectCore, the SDK now HMAC-signs ingest, and gains server-side receipt verification (verifyPurchase/verifyAndTrackPurchase), mediated ad revenue (trackAdRevenue), partner parameters & sharing controls, attestation tokens (setIntegrityToken), link resolution (resolveDeepLink/handleDeepLink), offline-mode toggles, and a live debug snapshot — on top of the existing track, consent, deep-link, ATT, and SKAN API. All APIs are async (Future<T>); deep links and attribution use streams.