Changelog
Notable changes to the SDK, server, and admin panel. Newest first.
iOS core 1.1.4 + Unity 2.4.4 — first-session delivery fix (2026-08-24)
On iOS, first-session events (app_install, app_first_open, session_start) could arrive only when the app was opened a second time — or, for users who declined App Tracking Transparency, never. Root causes, all fixed in ReflectCore 1.1.4: the install-reported latch was persisted before the install was durably queued (a first-launch drop lost it forever — it now latches at the moment of durable persistence, and a dropped install re-fires on the next launch, deduplicated server-side per install_uuid); legacy-uuid migration silently assumed the old install had been reported (adopted devices now fire app_install; the server flags genuine duplicates); a drain wakeup that lost the single-flight race was dropped (now remembered and replayed); backgrounding the app froze every retry until the next cold launch (a bounded beginBackgroundTask flush window now delivers the queue on the way out); and a fast 0/5/15/30 s install retry ladder plus a flush on every app activation replace the lone 30 s timer.
Behavioral default change: the Unity build post-processor no longer adds the ingest host to NSPrivacyTrackingDomains. The declaration made iOS 17+ refuse all SDK traffic until ATT was authorized, silencing undecided and denying users entirely; iOS already returns an all-zero IDFA without authorization, so nothing tracking-related escapes the ATT gate. Opt back in with ReflectBuildPostProcessor.DeclareTrackingDomain = true or REFLECT_DECLARE_TRACKING_DOMAIN=1 if your compliance posture requires the stricter declaration. Measured end to end against production: first-launch install ingested in ~3 seconds with the ATT prompt unanswered, and in under a second with ATT denied. Server side, installs re-fired by the migration path are excluded from install counts and ad-platform (CAPI) install forwarding.
Released
- Core —
ReflectCoretag1.1.4. - Unity —
v2.4.4: pins core1.1.4; tracking-domain injection now opt-in. Wire brandunity-2.4.4. Update recommended for every iOS title. - iOS (native) — facade
1.0.1; its~> 1.1dependency resolves1.1.4on the nextpod update. - Flutter / React Native — no wrapper release needed; the
~> 1.1pin resolves core1.1.4on the nextpod update. - Unreal Engine — re-vendors the
1.1.4iOS core in the next plugin tag. - Android — unaffected in production (97.6% of installs deliver in under 30 s); the same latch-ordering hardening lands in the next
reflect-androidrelease.
iOS core 1.1.3 — jailbreak-detection fix (2026-08-20)
ReflectCore 1.1.2 and older flagged every real iPhone as jailbroken: the detector counted ambiguous system paths (/bin/bash, /etc/apt, a readable preferences file) as evidence, and on recent stock iOS those checks fire universally. Every iOS event therefore carried is_rooted: true, and every iOS install attribution was stamped with the device_rooted fraud flag — reporting-level noise that also risked postback suppression if fraud filtering was ever enabled for that flag. 1.1.3 counts only jailbreak-specific artifacts (package-manager apps, MobileSubstrate, the /var/jb rootless bootstrap) or a successful sandbox-escape write, evaluated once per launch. No API change; every wrapper's ~> 1.1 pin resolves it on the next pod update. Rebuild and ship to stop sending the false flag — pin :tag => '1.1.3' where your Podfile names the core explicitly.
Shared core 1.1.2 — batch clamps, plus wrapper point releases (2026-08)
Both shared native cores now enforce the server's batch contract on the client. Previously a host-configured batch size above the server's per-batch event limit, or a batch whose compressed body exceeded the body-size limit, earned a terminal 4xx on every flush — the batch was dropped, rebuilt identically, and rejected again, so an app could silently lose all events. The cores now clamp the configured batch size, measure the gzipped body before sending, and split over-size batches; the server side additionally records per-app telemetry for any remaining ingest 4xx.
Released
- Cores —
reflect-android1.1.2(JitPack) andReflectCoretag1.1.2. Both version numbers are aligned from this release on. - Unity —
v2.4.3: clampsEventBatchSizeinValidate()and pins the 1.1.2 cores. Wire brandunity-2.4.3. - Flutter —
v1.7.3: pins the 1.1.2 cores; removes the unusedAdAttributionKitweak-framework declaration. Wire brandflutter-1.7.3. - React Native —
v2.0.4: pins the 1.1.2 cores; same podspec cleanup. Wire brandreact-native-2.0.4. - Android (native) —
com.github.bablu147:reflect-sdk-android:1.0.1: pins core1.1.2. Wire brandandroid-1.0.1. - iOS (native) — facade stays at tag
1.0.0(its~> 1.1dependency resolves1.1.2); pin the core pod at tag1.1.2in your Podfile. - Unreal Engine —
1.0.1: re-vendors the 1.1.2 iOS core and clampsEventBatchSizein config. Wire brandunreal-1.0.1. - Web —
v1.3.0: first published tag with the consent-gated fingerprinting, durable outbox, and deletion-journal work (the web SDK was never affected by the batch issue — its batch size is fixed).
Unreal Engine SDK 1.0.0 (2026-08)
First release of the Unreal Engine SDK — a C++ plugin for UE 5.8+, callable from C++ and Blueprint, over the same shared ReflectCore engine every other Reflect SDK uses. Verified end to end against production on both mobile platforms.
Added
- Unreal Engine — plugin source at github.com/bablu147/reflect-sdk-unreal, tag
1.0.0. Brands the wireunreal-1.0.0. - No Gradle or CocoaPods step. The plugin injects its own Android Gradle dependencies, manifest permissions and ProGuard keep-rules at package time, and compiles the iOS core from source shipped inside the plugin. Copy
ReflectSDK/intoPlugins/and build. - Full parity on the wire with the other SDKs — sessions, the durable offline queue, HMAC-signed ingest, attribution, deep links and the fail-closed privacy gate all behave identically.
Known limits
- Mobile only. Android and iOS collect normally. Editor, Windows, Mac, Linux and console load the plugin and answer every call immediately without collecting anything — a Reflect app registration is either Android or iOS, so a desktop build has nothing valid to report as. Calls fail fast rather than hanging, so Play In Editor is unaffected.
- Unreal cannot build any game for the iOS Simulator. UE 5.8's launcher build makes Apple's crash reporter a hard iOS dependency but ships no Simulator build of it, so linking fails before your code is involved. This affects every plugin equally — build for a real device.
Native SDKs — Android 1.0.0, iOS 1.0.0 (2026-08)
First release of the two native SDKs. Each is a thin typed facade over the shared ReflectCore engine — the same core Unity, Flutter and React Native run on — adding the host-side privacy gate, the public API surface, standard events, and the on-device debug inspector.
Added
- Android —
com.github.bablu147:reflect-sdk-android:1.0.0(JitPack), packagecom.reflect.android, minSdk 21. Brands the wireandroid-1.0.0. - iOS —
ReflectSDKtag1.0.0, moduleReflectSDK, iOS 13+. Brands the wireios-1.0.0. - One artifact, two host languages per platform. The Android SDK is Kotlin and serves Java (
@JvmStatic, builders,fun interfacelisteners, callbacks rather thansuspend); the iOS SDK is Swift and serves Objective-C (an@objcRFL*facade with completion-handler twins of the async methods). There is deliberately no separate Java SDK and no separate Objective-C SDK. - Both implement the same shared behaviour contract, so a given call behaves identically on either platform.
Install
Android needs the JitPack repository added by hand — a library cannot inject one. Use dependencyResolutionManagement in the app's settings.gradle; without it the build fails with Could not find com.github.bablu147:reflect-android:1.1.0.
Neither ReflectSDK nor ReflectCore is on CocoaPods trunk, and CocoaPods does not follow a git-sourced pod's dependency to another git source — so both pods must be declared with explicit git sources:
pod 'ReflectSDK', :git => 'https://github.com/bablu147/reflect-sdk-ios.git', :tag => '1.0.0'
pod 'ReflectCore', :git => 'https://github.com/bablu147/reflect-ios.git', :tag => '1.1.1'Shared native core — reflect-android 1.1.0, ReflectCore 1.1.1 (2026-08)
Two fixes to the published cores that every SDK inherits. Both are floors, not preferences — do not pin below them.
Fixed
- Privacy engine. The published Android core used by Flutter, React Native and Unity previously contained no privacy engine at all.
reflect-android:1.1.0is the first published core that carries it. - Platform branding.
X-Reflect-Platformwas hard-coded toflutterin both cores, so every host — Unity, React Native and the native SDKs — reported itself as Flutter on the wire. Each core now sends a constant matching its own runtime (android/ios), and it is not host-overridable.ReflectCoretag1.1.1is the first iOS core with the fix.
Events ingested before this release carry the wrong X-Reflect-Platform value; the per-SDK X-Reflect-Sdk brand (unity-2.4.2, flutter-1.7.2, …) was always correct and is the reliable field for historical data.
Unity 2.4.2, Flutter 1.7.2, React Native 2.0.3 (2026-08)
Changed
- All three now resolve the fixed cores —
reflect-android 1.1.0andReflectCore 1.1.1— so they pick up the privacy engine and correct platform branding above. Upgrading is a version bump; no API changes. - Unity — UPM Git URL
https://github.com/bablu147/reflect-sdk.git#v2.4.2. Wire brandunity-2.4.2. - Flutter — git dependency
ref: v1.7.2(not published to pub.dev). Wire brandflutter-1.7.2. - React Native —
npm install github:bablu147/reflect-sdk-react-native#v2.0.3(not published to npm). Wire brandreact-native-2.0.3. - Where the JitPack repository must go differs by toolchain and cannot be injected by a plugin — see each SDK's install section.
SDK — shared native core (2026-07)
React Native 2.0.0 and Flutter 1.7.0 were rebuilt as thin wrappers over the shared ReflectCore engine — the same Kotlin (reflect-android) and Swift (reflect-ios) core the Unity SDK shares.
Changed
- HMAC-signed ingest. Both SDKs now sign event batches (when a
signingSecretis set) and post to the authenticated/eventendpoint — previously they posted unsigned to/event/batch. - Shared, versioned native core — Android pulls
com.github.bablu147:reflect-androidfrom JitPack; iOS pulls theReflectCorepod. One core now backs Unity, Flutter, and React Native. install_uuidis preserved across the upgrade — an existing install is not counted as a reinstall.
Added
- Expanded API on both SDKs — server-side receipt verification (
verifyPurchase), mediated ad revenue (trackAdRevenue), partner parameters & sharing, attestation tokens (setIntegrityToken), link resolution (resolveDeepLink/handleDeepLink), and offline-mode / enable toggles.
SDK v2.1.0 — current
Added
- Standard event vocabulary — 25 constants + 14 typed helpers in
ReflectStandardEvents(sign_up, level_up, add_to_cart, ad_impression, etc.) matching AppsFlyer / Firebase taxonomy. - Global properties —
SetGlobalProperty / UnsetGlobalProperty / ClearGlobalProperties, merged into every event automatically. - Audience tagging —
SetAudience(...)applies cohort tags; server upsertsinstall_audiences. - Anonymous → known stitching —
SetUserIdauto-fires_user_aliason first non-null transition; server populatesuser_aliases. - GDPR / CCPA right-to-be-forgotten —
DeleteUserData(callback)wipes local state + queues server cascade-delete. - Deep linking —
OnDeepLinkevent +HandleDeepLink(url, isCold). Deferred deep links auto-fire from install referrer / AdServices payload. - Auto crash capture —
_crashevents on unhandled exceptions, throttled to 1/min. - app_first_open event distinct from
app_open(Firebase parity). - Receipt validation —
TrackPurchase / TrackSubscriptionaccept optionalreceiptData; server validates against Apple/Google (cache-first to avoid repeat calls). - Event validator — bounds-checks event names + properties client-side.
- UserId getter —
ReflectSDK.UserIdread-only property.
Changed
- Gzip compression on event batches ≥10. Typically 80% bandwidth reduction. Ingestion gateway decompresses after HMAC verify.
X-Reflect-Sdkheader bumped2.0.0→2.1.0.
Server
- Migration
008_sdk_v21.sqlapplied — addsdeletion_requests,user_aliases,install_audiences,retention_cohorts,receipt_validations, plusattributions.is_revenue_validatedandtracking_links.deep_link_path. - New endpoints:
POST /privacy/delete(queue + cron drain),POST /skan-postback(immutable audit lake). - New crons: nightly privacy deletion cascade, daily retention cohort rollup.
Build
consumer-rules.proshipped with the Android plugin — keeps native bridge alive when R8 is enabled.- License field cleaned up; package version bumped.
SDK v2.0.0
Breaking
ReflectConfig.CompanyKeyis now required whenBaseUrlis set. Format:co_live_<hex>.ReflectConfig.AppKeyis also required whenBaseUrlis set (was optional in v1).- New header on every
POST /event:X-Reflect-Company-Key. - Server rejects requests where
app_keyandcompany_keydon’t match:401 app_company_mismatch. - Server rejects suspended companies:
401 company_suspended.
Compatibility window
For 90 days following v2.0 release, the server accepts v1 SDK traffic (missing company key) and logs sdk_v1_deprecated warnings. After that window the server returns 400 missing_auth_headers.
SDK v1.0.0
Initial public release. Single-tenant; per-app HMAC-signed event ingestion; Play Install Referrer + AdServices attribution; offline queue; debug overlay; ATT integration.
Server / admin (rolling)
- 2026-04 — Onboarding paywall step inserted (
/onboard/plan). Indian Rupee pricing for IN visitors based on geo-detection. Landing page pulls live plans from data store. - 2026-04 — Resource usage dashboard (
/admin/super/usage) — cross-tenant load + cost + margin with upgrade-candidate / over-cap callouts. - 2026-04 — Plans & pricing super-admin UI (
/admin/super/plans); PayPal Subscriptions integration;/billingtenant page; per-app usage breakdown + activity feed on company detail. - 2026-04 — Migration 007: pricing tiers, subscriptions, usage counters, invoices, payments. Server-side cap enforcement + monthly invoice close cron.
- 2026-03 — Multi-tenant migration (003). Per-tenant data isolation; super-admin view of all companies.