advenue_sdk 1.4.1
advenue_sdk: ^1.4.1 copied to clipboard
Advenue MMP SDK for Flutter — attribution, install tracking, deep links, and consent, over the native iOS and Android SDKs.
advenue_sdk #
Flutter SDK for Advenue — the open-source, self-hostable mobile attribution platform (MMP), an AGPLv3 alternative to AppsFlyer, Adjust and Branch.
Attribution, the event queue, sessions, consent, deep links, SKAdNetwork and the durable device identity all live in the native Advenue iOS (Swift) and Android (Kotlin) SDKs. This package is the Dart API over them and nothing else — there is no second implementation in Dart to disagree with them.
import 'package:advenue_sdk/advenue_sdk.dart';
await Advenue.initialize(AdvenueConfig(
apiKey: 'apk_live_…',
onError: (context, cause) => debugPrint('[Advenue] $context: $cause'),
));
Advenue.track('purchase', {'sku': 'pro', 'revenue': 9.99});
Full documentation: https://advenue.io/docs/sdks/flutter.
What you get without wiring anything #
- Durable device identity (the Advenue ID), Keychain-backed on iOS.
- Automatic sessions. Both native SDKs observe foreground/background
themselves. There is no
WidgetsBindingObserverto implement, and adding one would open a second session on every launch. - Deep-link capture for attribution. Direct links are not delivered to
Dart — Flutter already routes those, and a competing callback would be a
footgun. The plugin observes them natively on every path the OS actually
uses:
scene:willConnectToSession:options:,scene:openURLContexts:andscene:continueUserActivity:on scene-based iOS hosts (Flutter's own template is one), the legacyUIApplicationDelegatecallbacks on pre-scene hosts, and the launch intent plusonNewIntenton Android. Deferred links are the SDK's to deliver, and come back fromresolveDeferredDeepLink(). - Offline buffering and retry, consent gating, GDPR/CCPA erasure
(
forgetMe), SKAdNetwork conversion values, and a privacy manifest so your App Store submission is not rejected for ours.
ATT wait (iOS) #
If your app prompts for ATT soon after launch — within at most 120 s — pass
attConsentWaitingInterval (seconds) so the install waits for the answer
instead of shipping IDFA-less. A prompt behind a longer onboarding outlasts
the cap; the install then ships IDFA-less anyway:
await Advenue.initialize(AdvenueConfig(
apiKey: 'apk_live_…',
attConsentWaitingInterval: 60,
));
Only enable it if the app actually prompts — otherwise every install waits out the full interval. Capped at 120 s; Android ignores the field.
API #
initialize, track, setUserId, setTrackingConsent /
getTrackingConsent, setConsentData / getConsentData, setAppInstanceId,
setPushToken, recordSkanRevenue (iOS), resolveDeferredDeepLink,
forgetMe, flush, getDeviceId / getAdvenueId, getResolvedAppId,
shutdown.
Every one is fail-open: a bridge failure becomes an onError diagnostic, never
an exception into your app, and a call before initialize() is a reported
no-op. See the docs for the full table.
Native floors #
- iOS 15.1 (
Package.swiftand the podspec both declare it) - Android
minSdk21,compileSdk36 environment.flutter: ">=3.44.0"— the release where Swift Package Manager became Flutter's default iOS build path and where the "support both SPM and CocoaPods" requirement takes effect. This package ships both, so 3.44 is the first version that requirement even applies to. Verified against Flutter 3.47.2 / Dart 3.13.2.
Working on this package #
The native sources are vendored into the published tarball rather than
pulled from a Maven coordinate or an SPM tag — both natives are tagged
(sdk-swift-v1.1.0, advenue-android-v1.1.0) but neither is on a registry
yet.
tool/vendor.mjs copies packages/sdk-swift/Sources and
packages/sdk-android/**/src/main/kotlin into the layout Flutter's Swift
Package Manager structure requires (ios/advenue_sdk/Sources/advenue_sdk);
the podspec reads that same directory, so one vendor target feeds both iOS
packaging systems. It reuses @advenue/react-native's vendor() rather than
duplicating it — one answer to what a complete SDK is, not two. The plugin
sources and PrivacyInfo.xcprivacy are tracked outside that tree (it is
gitignored build output, cleared on every run) and copied in.
tool/check.mjs runs four guards, in the order a failure is cheapest to read:
- the Dart version constant matches
pubspec.yaml; - vendoring produced a non-empty tree;
- the vendored Swift compiles as one module (the shape CocoaPods builds);
dart pub publish --dry-runwould include the native sources and the privacy manifest at their real vendored paths, despite those being gitignored in this repo.
node --test tool/vendor.test.mjs tool/check_version.test.mjs covers the
guards themselves. The bridge contract shared with the React Native SDK lives
in packages/conformance/bridge-manifest.json and is checked against all four
implementations by scripts/check-bridge-manifest.mjs; the Dart facade is
checked against the same file at runtime in test/facade_test.dart.
The example app in examples/flutter is also the
host app for the integration tests — the only artifact that proves "compiles"
and "joined" are different things.