unitrack 1.3.1
unitrack: ^1.3.1 copied to clipboard
UniTrack — universal mobile analytics SDK for Flutter. Auto-captures screens, taps, network calls, crashes, OOM warnings, and JSON parse errors with a persistent offline queue, session journey, and W3 [...]
Changelog #
1.3.1 — 2026-06-30 #
Fixed: iOS build trên Flutter add-to-app #
Classes/include/unitrack.h(umbrella header CocoaPods xuất ra Swift module) outdated, thiếuut_layerenum + 6 cross-layer C symbol (ut_register_layer,ut_active_layers,ut_claim_subtree,ut_release_subtree,ut_subtree_claimed_by,ut_set_screen_dedup_window_ms,ut_set_screen_for_layer). Bây giờ là copy đầy đủ củaNative/core/include/unitrack/unitrack.h.Native/swift/Arbitration/ManualTrackSignal.swiftkhông có trong package 1.3.0 → Swift compile failcannot find type 'ManualTrackKind'. Đã thêm.unitrack.podspecs.versionsync với pubspec (1.3.0 podspec vẫn còn ghi 1.2.1).
Ai chưa publish app: bump trực tiếp ^1.3.1. Ai đã build với ^1.3.0: build sẽ fail iOS — bắt buộc bump 1.3.1.
1.3.0 — 2026-06-30 #
Added: UniTrack.customTrack(...) Dart API #
Parity với native iOS UniTrack.customTrack + Android Kotlin
UniTrack.customTrack. Native side stamp session_id, event_action (=
[action] ?? [eventName]), và user_id (nếu includeUser: true, lấy từ
cache identify() đã set).
// Pattern 1 — 1 schema = 1 action
UniTrack.instance.customTrack('banner_clicked', data: {
'banner_id': 'home_top',
'position': 1,
});
// Pattern 2 — 1 schema = nhiều action
UniTrack.instance.customTrack('payment_event',
action: 'payment_completed',
data: {'amount': 199_000, 'currency': 'VND'},
includeUser: true);
HostProxy co-resident (Flutter add-to-app embed vào native iOS đã có
UniTrack SPM) cũng route customTrack qua singleton native — zero
duplicate session/SQLite.
Removed: unitrack_firebase package #
Firebase Analytics mirror is now provided exclusively by the built-in
FirebaseAdapter (reflection-based, lives in the core unitrack plugin).
Host apps need to keep firebase_core + firebase_analytics declared, then
call UniTrack.instance.attachFirebaseAdapter() once at bootstrap. The
separate unitrack_firebase plugin has been removed from the SDK monorepo
and will be unpublished from pub.flutter-io.cn.
1.2.1 — 2026-06-23 #
FirebaseAdapter — stamp session_id qua setDefaultEventParameters #
Trước đây UniTrack chỉ stamp session_id vào params khi event đi qua
UniTrack.track() — app gọi FirebaseAnalytics.logEvent() thẳng (bypass
UniTrack, vd Firebase Performance, Crashlytics auto-events) thì event đó
KHÔNG có session_id ở params.
Fix: adapter giờ gọi setDefaultEventParameters({session_id, session_index})
ở 3 hook:
initialize()— khi attachsetUser()— khi identity đổitrack()— khi session_id đổi (detect qualastStampedSessionId)
Firebase tự merge default params vào MỌI event (kể cả app gọi
logEvent() thẳng) → 100% event Firebase có session_id UniTrack để
analyst join cross-provider.
Yêu cầu Firebase SDK:
- iOS: 8.4+ (responds-to check — older SDK no-op an toàn).
- Android: 21.0.0+ (NoSuchMethodException swallow — older SDK no-op).
1.2.0 — 2026-06-23 #
Audit-based release. Sau khi anh user feedback "code kỹ 1 lần không được hả", em audit toàn diện 15 findings — gộp vào 1 release thay vì 4 patch lẻ (1.1.1 → 1.1.4).
Added #
UniTrackConfig.screenStartEvent+screenEndEvent+logLevel— parity với Portalsdk_configblock. Trước đây Portal có 3 field này nhưng SDK Flutter bỏ qua.logLevelmặc định'warn', acceptdebug/info/warn/error/off.UniTrackConfig.fromMap()numeric coercion — chấp nhậnint → doublekhi Portal serializesamplingRate: 1thay vì1.0.
Fixed #
UniTrackRemoteConfig.snowplowOptionschỉ accept bool — giờ accept1/0,"true"/"false"string. Operator edit raw JSON typo không bị silently drop nữa.UniTrackRemoteConfig._builtinDefault()không còn hard-codehttps://mobix.asia/.... Endpoint default empty → SDK no-op cho đến lần fetch thành công kế. Apps multi-tenant nên LUÔN passfallback:với endpoint của mình.
Cleanup #
UniTrackRemoteConfig.snowplowEntities(deprecated từ 1.1.3) giữ@Deprecatedđể không vỡ camera demo cũ. App mới dùngsnowplowEntityURIs.
1.1.4 — 2026-06-23 #
Added #
UniTrackConfig.fromMap() factory — build config từ remoteCfg.sdkConfig Map
(Portal sdk_config block). App không phải lặp lại default hard-code khi cấu
hình autoCapture/trackScreens/trackTaps/trackNetwork ở Portal.
final remoteCfg = await UniTrackRemoteConfig.fetch(...);
await UniTrack.instance.initialize(
apiKey,
config: UniTrackConfig.fromMap(remoteCfg.sdkConfig),
);
Chấp nhận cả snake_case (Portal default) lẫn camelCase cho mỗi field. Field
thiếu/sai type tự fallback default constructor.
1.1.3 — 2026-06-23 #
Fix #
UniTrackRemoteConfig.snowplowEntities luôn trả map rỗng dù Portal đã set
entities. Lý do: getter yêu cầu value is Map nhưng Portal serialize entities
thành Map<String, String> (entity short-name → iglu URI). Hậu quả:
SnowplowProvider không build entity nào → log contexts: [].
- Thêm getter mới
snowplowEntityURIs: Map<String, String>đúng shape Portal. App pass thẳng vàoSnowplowProvider(entities:). snowplowEntitiescũ marked@Deprecated— giữ để không vỡ consumer cũ (camera demo) — nhưng tất cả call site nên migrate sangsnowplowEntityURIs.
1.1.2 — 2026-06-22 #
Breaking (Dart-only, minor — chỉ ảnh hưởng code gọi defaultIgluSchema) #
UniTrackRemoteConfig.defaultIgluSchema không còn hard-code FTel vendor.
Trước:
static String defaultIgluSchema(String eventName, {String version = '1-0-0'}) {
return 'iglu:vn.fpt.ftel.snowplow/$eventName/jsonschema/$version';
}
Sau (instance method, vendor đọc từ portal hoặc tham số):
String defaultIgluSchema(String eventName,
{String version = '1-0-0', String? vendor}) { ... }
Vendor lookup precedence:
- tham số
vendor:(explicit) snowplow.iglu_vendortừ Portal- throw ArgumentError (không có fallback FTel)
Lý do #
SDK không nên biết tenant. Vendor là khái niệm của app/portal, không phải SDK. Apps đa tenant lấy vendor từ Portal; single-tenant pass inline.
Migration cho app FPT (vd MobiX, FPT Life) #
Đến khi Portal expose snowplow.iglu_vendor, app pass fallback:
final igluVendor = remoteCfg.snowplowIgluVendor.isNotEmpty
? remoteCfg.snowplowIgluVendor
: 'vn.fpt.ftel.snowplow';
remoteCfg.defaultIgluSchema(eventName, vendor: igluVendor);
1.1.1 — 2026-06-22 #
Hotfix release. 1.1.0 archive thiếu native source vì flutter pub publish
lọc file qua git ls-files — folder ios/Native/ + Android SDK source untracked
nên không lên pub.flutter-io.cn, gây lỗi "Cannot find 'UniTrack' in scope" ở Xcode.
Fix #
ios/Native/(Swift SDK + C++ core) giờ tracked trong git đểpub publishthấy.- Android SDK source vendored vào
android/unitrack_sdk/src/— pod tự build Kotlin + JNI/C++ thay vì trỏ ra../../android/unitrack(path đó không tồn tại trong pub-cache consumer app). - Thêm
platforms/flutter/sync_native.sh— chạy script này trước mỗipub publishđể đồng bộ Native/ + unitrack_sdk/ với monorepo source.
1.1.0 — 2026-06-22 #
Catch-up release đưa Flutter SDK lên ngang iOS 0.3.36 + Android 0.3.11.
Mới #
- Built-in
HttpProvider— gửi event lên Kibana / ELK / backend FPT nội bộ quaaddHttpProvider()API. Portal Config tab là source of truth, app không phải code tay. 4 PayloadFormat (JSON_SINGLE / JSON_LINES / JSON_ARRAY / ELASTIC_BULK). Retry exponential backoff 1s → 5min, max 10 lần, TTL 7 ngày. - Per-provider ack queue — Mô hình B: event chỉ xoá khỏi queue khi tất cả provider ack SUCCESS. Provider nào trả RETRY thì giữ lại, exponential backoff per id. Snowplow / Firebase / Custom HTTP đều được retry chuẩn ngành.
FirebaseAdapterqua reflection —attachFirebaseAdapter()stampsession_idvào mọi event Firebase Analytics quaNSClassFromString/Class.forName. UniTrack 0 import Firebase: app chưa cài → no-op, cài sau → bridge tự kích hoạt.- W3C Trace Context auto-inject — header
traceparentchèn vào HTTP request đi tới host trong allowlist Portal (fail-closed). - Kill detection —
clean_shutdownflag persist vào session.json. Cold start kế tiếp firesession_endedvới reasonkilled_recoveredngay, không đợi 30 phút timeout.
Bỏ #
tracking_id/currentTrackingIdAPI —session_idlà khóa join duy nhất giữa Portal / Snowplow / Firebase / custom backend. Apps gọicurrentTrackingIdphải đổi sangcurrentSessionId.
Fix #
UniTrackConfigStream.ingest()String index out-of-bounds crash khi SSE chunk có unicode multi-byte. Đổi sangcomponents(separatedBy:).
Native sync #
10 file Swift + 3 file C++ trong ios/Native/ đã sync với iOS 0.3.36 source.
1.0.0 — 2026-06-09 #
Initial public release.
Features #
- Auto-capture: screen, tap, network, crash, OOM, JSON-parse error.
- Persistent SQLite offline queue with exponential backoff retries.
- Session journey tracking —
session_id+session_indexpersist across cold starts viasession.json. - W3C trace-context (
traceparentheader) opt-in injection with host allowlist. - Provider fan-out: bring your own analytics destination by implementing
AnalyticsProvider. Two first-party providers shipped separately: - Public APIs include:
initialize / track / identify / reset / setScreen / flush / setEnabledcurrentSessionId / sessionIndex / previousSessionId / rotateSessionpendingEventCounts / onFlushCompleted(offline-test introspection)applicationContext / getRemoteValue<T>trackNotification / captureNotification / trackDeeplink / trackUrlLaunchUniTrackNavigatorObserverfor route auto-capturesetTracing+UniTrackTraceContextfor W3C distributed tracing