Fire the call when the paywall surface is actually visible to the user — not on push, not on configure. SwiftUI/Compose/RN/Flutter visibility callbacks are the right hook. Don't pass the variant ID, the placement, or the offer config as metadata.
▸Install the Kotlin (Android) SDK
// build.gradle.kts (app module)
dependencies {
implementation("com.respectlytics:respectlytics-kotlin:3.0.0")
}
Pure Kotlin coroutines implementation. No Java dependencies, no Google Play Services dependencies. ~300KB DEX overhead — compare to roughly 3.8MB for Firebase Analytics (a measurable cold-start improvement on lower-end devices).
▸Initialize Respectlytics in Kotlin (Android)
import com.respectlytics.android.Respectlytics
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Respectlytics.configure(this, appKey = "<YOUR_APP_KEY>")
}
}
Initialize once in Application.onCreate. No additional permissions in the manifest — INTERNET is sufficient. The SDK does not request AD_ID, does not query AdvertisingIdClient, and does not declare ACCESS_NETWORK_STATE.
▸Track the event in Kotlin (Android)
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import com.respectlytics.android.Respectlytics
@Composable
fun PaywallScreen() {
LaunchedEffect(Unit) {
// Fires once when the composable enters the composition.
Respectlytics.track("paywall_view")
}
// ... paywall composable content ...
}
For Activity/Fragment-based UIs, fire in onResume() instead of onCreate() — create fires before the user can see anything.
✦Privacy & implementation notes
Fire the event on actual visibility, not on data fetch. SwiftUI's .onAppear, Compose's LaunchedEffect(Unit), RN's useFocusEffect, and Flutter's AfterFirstLayout mixin are the canonical hooks. Tracking on configure inflates the rate with paywalls the user never saw.
Experiment IDs are tempting because they look harmless — they're really not. A stable experiment ID across thousands of sessions becomes a per-user fingerprint via the variant assignment pattern. Encode the variant in the event name; discard the assignment ID.
Many teams discover the com.google.android.gms.permission.AD_ID permission in their merged manifest only after Google Play flags them — usually because a transitive dependency dragged it in. Respectlytics's Kotlin SDK has no Google Play Services dependency at all, so it cannot contribute to that merge.
The SDK is implemented as pure Kotlin coroutines with no Java sources, no RxJava, and no platform channels. Events are queued in a Channel<Event> buffered to a small ring (RAM-only), drained by a coroutine that flushes every 30 seconds or on backgrounding. There is no SharedPreferences usage.
⇋How this compares to other analytics SDKs
| Paywall view event | Firebase Analytics | Mixpanel | Respectlytics |
|---|---|---|---|
| Per-user identity | app_instance_id | distinct_id | Never |
| Variant / experiment ID as parameter | Recommended | Recommended | Use distinct event_name |
| Placement (home, settings, …) as parameter | Recommended | Recommended | Use distinct event_name |
| Computed metric: paywall_view → paywall_purchase rate | Per-user | Per-user | Session-grouped |
| Bot / accidental view filtering | Heuristic per user | Heuristic per user | Country + session aggregate |
❓Frequently asked questions
How do we measure paywall conversion rate without joining view → purchase per user?
Per-session. A session that emits both paywall_view and paywall_purchase is a converting session. The ratio across all sessions is your conversion rate. The noise from sessions where the user views the paywall on day 1 and converts on day 3 is small at scale — and your billing system already has the longitudinal truth.
Can we A/B-test paywall variants?
Yes. Emit paywall_view_a, paywall_view_b, etc., and pair with paywall_purchase_a, paywall_purchase_b. Per-variant conversion rate falls out of session-grouped event counts.
What about tracking which placement the paywall was shown from?
Distinct event names per placement: paywall_view_home, paywall_view_settings, paywall_view_post_onboarding. Keep the taxonomy short — under 8 placements is comfortable; past that, bucket the long tail.
Should we track the offered price or product set?
No. Pricing changes belong in your release notes and your billing system, not in your analytics pipeline. Mixing them in produces stale data the moment you change a price.