@apex-inc/capacitor-plugin 2.5.1 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ApexIncCapacitorPlugin.podspec +1 -0
- package/README.md +52 -1
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/java/inc/apex/capacitor/ApexCapacitorPlugin.kt +200 -18
- package/android/src/main/java/inc/apex/capacitor/FirstLaunchInstall.kt +28 -0
- package/android/src/main/java/inc/apex/capacitor/MetaInstallReferrer.kt +75 -0
- package/android/src/main/java/inc/apex/capacitor/MobileContext.kt +43 -0
- package/dist/definitions.d.ts +31 -5
- package/dist/definitions.d.ts.map +1 -1
- package/dist/esm/definitions.d.ts +31 -5
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +10 -9
- package/dist/esm/web.js.map +1 -1
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +10 -9
- package/dist/web.js.map +1 -1
- package/ios/Sources/ApexCapacitorPlugin/FirstLaunchInstall.swift +50 -0
- package/ios/Sources/ApexCapacitorPlugin/MobileContext.swift +49 -0
- package/ios/Sources/ApexCapacitorPluginBridge/ApexCapacitorPlugin.swift +86 -8
- package/ios/Sources/PrivacyInfo.xcprivacy +72 -0
- package/ios/Tests/ApexCapacitorPluginTests/FirstLaunchInstallTests.swift +66 -0
- package/ios/Tests/ApexCapacitorPluginTests/MobileContextTests.swift +56 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
13
|
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.resource_bundles = { 'ApexIncCapacitorPluginPrivacy' => ['ios/Sources/PrivacyInfo.xcprivacy'] }
|
|
14
15
|
s.ios.deployment_target = '13.0'
|
|
15
16
|
s.dependency 'Capacitor'
|
|
16
17
|
s.swift_version = '5.9'
|
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ await Apex.initialize({
|
|
|
29
29
|
// apiUrl: "https://app.apex.inc",
|
|
30
30
|
// autoTrackScreenViews: true, // default — screen_view auto-fires from SPA navigation
|
|
31
31
|
// autoConversionValues: true, // default — Apex drives SKAdNetwork values from Set up Apex (iOS)
|
|
32
|
+
// autoTrackInstall: true, // default — app_install once, on the first launch of a fresh install
|
|
33
|
+
// metaAppId: "1234567890", // Android: credits installs from Meta ads (see "Meta install referrer")
|
|
32
34
|
// sessionTimeoutMinutes: 30,
|
|
33
35
|
// offlineQueueMaxSize: 1000,
|
|
34
36
|
// testMode: false,
|
|
@@ -36,7 +38,17 @@ await Apex.initialize({
|
|
|
36
38
|
});
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
On iOS and Android the plugin sends `app_install` itself, once, on the
|
|
42
|
+
first launch of a fresh install, carrying what Apex needs to credit the
|
|
43
|
+
ad behind it. Someone who had your app before you added Apex is not sent
|
|
44
|
+
as an install. If your app already tracks `app_install`, keep it or
|
|
45
|
+
remove it: only the first one per install is sent.
|
|
46
|
+
|
|
47
|
+
Track `app_open` yourself on launch and when the app returns to the
|
|
48
|
+
foreground; on iOS and Android the plugin does not send it for you. (In a
|
|
49
|
+
browser preview, the web version sends one `app_open` per page load.)
|
|
50
|
+
|
|
51
|
+
`screen_view` auto-fires from
|
|
40
52
|
the webview's History API (pushState / replaceState / back-forward /
|
|
41
53
|
hashchange — covers Ionic, React Router, Vue Router, and plain SPA
|
|
42
54
|
routing, on device and in browser preview). Screen names default to the
|
|
@@ -169,6 +181,27 @@ const { status: current } = await Apex.getTrackingStatus();
|
|
|
169
181
|
|
|
170
182
|
## Advertising identifiers
|
|
171
183
|
|
|
184
|
+
Every event carries the phone's details under `mobile` (app id, app
|
|
185
|
+
version, OS version, model, language, time zone, and on iOS the tracking
|
|
186
|
+
answer). Apex passes them to the ad networks you connect, so they can
|
|
187
|
+
credit installs and purchases to their ads. The advertising id rides
|
|
188
|
+
along only with permission:
|
|
189
|
+
|
|
190
|
+
- **iOS**: the IDFA, only after the person allowed tracking in the ATT
|
|
191
|
+
prompt. Read on every event, so a change in Settings applies at once.
|
|
192
|
+
- **Android**: the GAID, only when the person has not limited ad tracking
|
|
193
|
+
or deleted the id. Looked up at `initialize()` and again when the app
|
|
194
|
+
opens.
|
|
195
|
+
|
|
196
|
+
The plugin ships an Apple privacy manifest that declares the advertising
|
|
197
|
+
id, app activity and purchases as used for tracking, since Apex sends
|
|
198
|
+
installs and purchases to the ad networks you connect. Xcode merges it into your app's privacy report;
|
|
199
|
+
your App Store privacy label should say the same.
|
|
200
|
+
|
|
201
|
+
The IDFV and Android ID fallbacks below are never put on events. If your
|
|
202
|
+
app asks for consent with `requireConsent`, nothing is sent at all until
|
|
203
|
+
`setConsent({ granted: true })`.
|
|
204
|
+
|
|
172
205
|
```ts
|
|
173
206
|
// Returns IDFA (iOS, ATT authorized), GAID (Android), or fallback.
|
|
174
207
|
const { id, fallback } = await Apex.getAdvertisingId();
|
|
@@ -177,6 +210,24 @@ if (!id && fallback === "idfv") {
|
|
|
177
210
|
}
|
|
178
211
|
```
|
|
179
212
|
|
|
213
|
+
## Meta install referrer (Android)
|
|
214
|
+
|
|
215
|
+
The Facebook, Instagram and Facebook Lite apps remember the Meta ad a
|
|
216
|
+
person tapped or saw before installing yours. Pass your Meta app id and
|
|
217
|
+
the install carries that ad to Apex:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
await Apex.initialize({ workspaceKey: "prj_your_key", metaAppId: "1234567890" });
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Skip `metaAppId` if your app already has the Facebook SDK's
|
|
224
|
+
`com.facebook.sdk.ApplicationId` manifest entry; the plugin reads it.
|
|
225
|
+
The ad stays encrypted on the phone. Apex opens it with your install
|
|
226
|
+
referrer key: in Meta for Developers, open your app's Basic settings,
|
|
227
|
+
find "Install Referrer Decryption Key" under Android, and paste it in
|
|
228
|
+
Apex under the Meta connection. Needs Facebook 428, Instagram 296 or
|
|
229
|
+
Facebook Lite 411 or newer on the phone.
|
|
230
|
+
|
|
180
231
|
## SKAdNetwork conversion values (iOS 4.0+)
|
|
181
232
|
|
|
182
233
|
You do not have to write this code. In the Apex dashboard, **Set up Apex →
|
|
@@ -36,5 +36,10 @@
|
|
|
36
36
|
<package android:name="com.google.android.feedback" />
|
|
37
37
|
<package android:name="com.amazon.venezia" />
|
|
38
38
|
<package android:name="com.sec.android.app.samsungapps" />
|
|
39
|
+
<!-- Meta Install Referrer: Android 11+ hides these apps' content
|
|
40
|
+
providers unless the app declares it looks for them. -->
|
|
41
|
+
<package android:name="com.facebook.katana" />
|
|
42
|
+
<package android:name="com.instagram.android" />
|
|
43
|
+
<package android:name="com.facebook.lite" />
|
|
39
44
|
</queries>
|
|
40
45
|
</manifest>
|
|
@@ -67,9 +67,19 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
67
67
|
// rather than returning null because the Play service hasn't
|
|
68
68
|
// connected yet. Calls that arrive before the fetch completes are
|
|
69
69
|
// parked and flushed by the listener.
|
|
70
|
-
private var installReferrerResolved: Boolean = false
|
|
70
|
+
@Volatile private var installReferrerResolved: Boolean = false
|
|
71
71
|
private var installReferrerClickSeconds: Long = 0
|
|
72
72
|
private val pendingReferrerCalls = mutableListOf<PluginCall>()
|
|
73
|
+
private val referrerLatch = java.util.concurrent.CountDownLatch(1)
|
|
74
|
+
|
|
75
|
+
// The install is sent once per install, by the plugin or the app, never both.
|
|
76
|
+
private var autoTrackInstall: Boolean = true
|
|
77
|
+
private val installLock = Any()
|
|
78
|
+
|
|
79
|
+
// Meta Install Referrer. Read once per launch, on the install event.
|
|
80
|
+
private var metaAppId: String? = null
|
|
81
|
+
@Volatile private var metaReferrerRead: Boolean = false
|
|
82
|
+
@Volatile private var metaReferrer: MetaInstallReferrer.Found? = null
|
|
73
83
|
// Phase 2-SDK — workspace-bound SDK key forwarded as
|
|
74
84
|
// `x-apex-api-key` on every event POST + on `identify()`.
|
|
75
85
|
private var apiKey: String? = null
|
|
@@ -85,6 +95,27 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
85
95
|
// Phase 4a — consent gate. Defaults granted; set false by
|
|
86
96
|
// initialize({ requireConsent: true }) until setConsent({ granted:true }).
|
|
87
97
|
private var consentGranted: Boolean = true
|
|
98
|
+
|
|
99
|
+
// The GAID, looked up off the main thread (Play services blocks) and
|
|
100
|
+
// refreshed on `app_open`, since the person can limit ad tracking or
|
|
101
|
+
// delete the id in Settings at any time.
|
|
102
|
+
@Volatile private var gaid: String? = null
|
|
103
|
+
@Volatile private var gaidResolved: Boolean = false
|
|
104
|
+
private val device by lazy {
|
|
105
|
+
val locale = Locale.getDefault()
|
|
106
|
+
MobileContext.Device(
|
|
107
|
+
bundleId = context.packageName,
|
|
108
|
+
appVersion = try {
|
|
109
|
+
context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: "0.0.0"
|
|
110
|
+
} catch (_: Exception) {
|
|
111
|
+
"0.0.0"
|
|
112
|
+
},
|
|
113
|
+
osVersion = Build.VERSION.RELEASE,
|
|
114
|
+
deviceModel = "${Build.MANUFACTURER} ${Build.MODEL}".trim(),
|
|
115
|
+
timezone = TimeZone.getDefault().id,
|
|
116
|
+
locale = "${locale.language}-${locale.country}",
|
|
117
|
+
)
|
|
118
|
+
}
|
|
88
119
|
// Phase 3 — per-launch dedup so each (experiment, variant) exposure fires
|
|
89
120
|
// once. Concurrent set: getVariant resolves on background threads.
|
|
90
121
|
private val firedExposures = java.util.concurrent.ConcurrentHashMap.newKeySet<String>()
|
|
@@ -156,6 +187,8 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
156
187
|
apiKey = if (rawKey.isNullOrEmpty()) null else rawKey
|
|
157
188
|
// Phase 4a — consent gate.
|
|
158
189
|
consentGranted = !(call.getBoolean("requireConsent", false) ?: false)
|
|
190
|
+
metaAppId = MetaInstallReferrer.normalizeAppId(call.getString("metaAppId")) ?: manifestMetaAppId()
|
|
191
|
+
autoTrackInstall = call.getBoolean("autoTrackInstall", true) ?: true
|
|
159
192
|
val maxSize = call.getInt("offlineQueueMaxSize") ?: 1000
|
|
160
193
|
|
|
161
194
|
val queueFile = File(context.filesDir, "apex-capacitor/events.json")
|
|
@@ -210,10 +243,80 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
210
243
|
|
|
211
244
|
// Fire-and-forget install referrer retrieval on init.
|
|
212
245
|
fetchInstallReferrer()
|
|
246
|
+
Thread { resolveGaid() }.start()
|
|
247
|
+
// Off this thread: the install waits up to REFERRER_WAIT_MS for Play.
|
|
248
|
+
Thread { sendInstallIfFirstLaunch() }.start()
|
|
213
249
|
|
|
214
250
|
call.resolve()
|
|
215
251
|
}
|
|
216
252
|
|
|
253
|
+
/** First install time and this version's install time, from the package manager. */
|
|
254
|
+
private fun installTimes(): Pair<Long?, Long?> = try {
|
|
255
|
+
val info = context.packageManager.getPackageInfo(context.packageName, 0)
|
|
256
|
+
Pair(info.firstInstallTime, info.lastUpdateTime)
|
|
257
|
+
} catch (_: Exception) {
|
|
258
|
+
Pair(null, null)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Send `app_install` on the first launch of a fresh install. Marks the
|
|
263
|
+
* install as handled for someone who had the app before Apex, so the
|
|
264
|
+
* update that adds Apex reports no one as new.
|
|
265
|
+
*/
|
|
266
|
+
private fun sendInstallIfFirstLaunch() {
|
|
267
|
+
if (!autoTrackInstall || !consentGranted || offlineQueue == null) return
|
|
268
|
+
val (installed, versionInstalled) = installTimes()
|
|
269
|
+
val decision = synchronized(installLock) {
|
|
270
|
+
val sent = prefs?.getBoolean(FirstLaunchInstall.PREF_KEY, false) == true
|
|
271
|
+
val d = FirstLaunchInstall.decide(sent, installed, versionInstalled, System.currentTimeMillis())
|
|
272
|
+
if (d != FirstLaunchInstall.Decision.ALREADY_SENT) {
|
|
273
|
+
prefs?.edit()?.putBoolean(FirstLaunchInstall.PREF_KEY, true)?.apply()
|
|
274
|
+
}
|
|
275
|
+
d
|
|
276
|
+
}
|
|
277
|
+
if (debug) println("[apex-capacitor] first-launch install: $decision")
|
|
278
|
+
if (decision != FirstLaunchInstall.Decision.SEND) return
|
|
279
|
+
try {
|
|
280
|
+
enqueuePayload(
|
|
281
|
+
UUID.randomUUID().toString().lowercase(),
|
|
282
|
+
mutableMapOf<String, Any?>("type" to "app_install", "data" to JSONObject().put("source", "apex_first_launch")),
|
|
283
|
+
)
|
|
284
|
+
} catch (e: Exception) {
|
|
285
|
+
if (debug) println("[apex-capacitor] first-launch install not queued: ${e.message}")
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** True the first time an install is claimed; the app's own `app_install` after that is dropped. */
|
|
290
|
+
private fun claimInstall(): Boolean = synchronized(installLock) {
|
|
291
|
+
if (prefs?.getBoolean(FirstLaunchInstall.PREF_KEY, false) == true) {
|
|
292
|
+
false
|
|
293
|
+
} else {
|
|
294
|
+
prefs?.edit()?.putBoolean(FirstLaunchInstall.PREF_KEY, true)?.apply()
|
|
295
|
+
true
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private fun resolveGaid() {
|
|
300
|
+
if (Looper.myLooper() == Looper.getMainLooper()) return
|
|
301
|
+
gaid = try {
|
|
302
|
+
val info = AdvertisingIdClient.getAdvertisingIdInfo(context)
|
|
303
|
+
MobileContext.advertisingId(info.id, info.isLimitAdTrackingEnabled)
|
|
304
|
+
} catch (_: Exception) {
|
|
305
|
+
null
|
|
306
|
+
}
|
|
307
|
+
gaidResolved = true
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** The first event of a launch (often the install) waits for the lookup rather than going without. */
|
|
311
|
+
private fun currentGaid(): String? {
|
|
312
|
+
if (!gaidResolved) resolveGaid()
|
|
313
|
+
return gaid
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private fun stampDevice(slot: MutableMap<String, Any?>) {
|
|
317
|
+
MobileContext.fill(slot, device, currentGaid())
|
|
318
|
+
}
|
|
319
|
+
|
|
217
320
|
// ── Push notifications (FCM) ──────────────────────────────────────
|
|
218
321
|
@PluginMethod
|
|
219
322
|
fun registerForPushNotifications(call: PluginCall) {
|
|
@@ -448,12 +551,6 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
448
551
|
// kotlinx.coroutines here would bloat every consumer's APK by ~1MB.
|
|
449
552
|
@PluginMethod
|
|
450
553
|
fun identify(call: PluginCall) {
|
|
451
|
-
// Phase 4a — identify sends PII; collect nothing until consent given.
|
|
452
|
-
if (!consentGranted) {
|
|
453
|
-
if (debug) println("[apex-capacitor] consent not granted; skipping identify")
|
|
454
|
-
call.resolve()
|
|
455
|
-
return
|
|
456
|
-
}
|
|
457
554
|
val email = call.getString("email")?.trim()
|
|
458
555
|
if (email.isNullOrEmpty()) {
|
|
459
556
|
call.reject("email is required")
|
|
@@ -463,10 +560,18 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
463
560
|
val traits = call.getObject("traits")
|
|
464
561
|
|
|
465
562
|
val payload = JSObject()
|
|
466
|
-
.put("visitorId", visitorId)
|
|
467
563
|
.put("email", email)
|
|
468
564
|
.put("workspaceKey", workspaceKey)
|
|
469
565
|
.put("timestamp", java.time.Instant.now().toString())
|
|
566
|
+
// Signing up is its own reason to know the person. Without consent
|
|
567
|
+
// only the identify goes: no device id, and Apex records advertising
|
|
568
|
+
// as denied so no ad platform is sent them.
|
|
569
|
+
if (consentGranted) {
|
|
570
|
+
payload.put("visitorId", visitorId)
|
|
571
|
+
} else {
|
|
572
|
+
if (debug) println("[apex-capacitor] consent not granted; identifying without a device id")
|
|
573
|
+
payload.put("noBrowserConsent", true)
|
|
574
|
+
}
|
|
470
575
|
if (!userId.isNullOrEmpty()) {
|
|
471
576
|
payload.put("userId", userId)
|
|
472
577
|
}
|
|
@@ -812,7 +917,7 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
812
917
|
payload["mobile"] = mutableMapOf<String, Any?>(
|
|
813
918
|
"releaseChannel" to releaseChannel,
|
|
814
919
|
"releaseChannelSource" to releaseChannelSource,
|
|
815
|
-
)
|
|
920
|
+
).also { stampDevice(it) }
|
|
816
921
|
val event = NativeQueuedEvent(
|
|
817
922
|
id = UUID.randomUUID().toString().lowercase(),
|
|
818
923
|
payload = payload,
|
|
@@ -902,8 +1007,7 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
902
1007
|
// ── Events / Queue ────────────────────────────────────────────────
|
|
903
1008
|
@PluginMethod
|
|
904
1009
|
fun track(call: PluginCall) {
|
|
905
|
-
|
|
906
|
-
if (queue == null) {
|
|
1010
|
+
if (offlineQueue == null) {
|
|
907
1011
|
call.reject("Plugin not initialized — call initialize() first")
|
|
908
1012
|
return
|
|
909
1013
|
}
|
|
@@ -916,6 +1020,22 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
916
1020
|
val id = call.getString("id") ?: UUID.randomUUID().toString().lowercase()
|
|
917
1021
|
val payload = mutableMapOf<String, Any?>()
|
|
918
1022
|
call.data.keys().forEach { key -> payload[key] = call.data.opt(key) }
|
|
1023
|
+
if (payload["type"] == "app_install" && !claimInstall()) {
|
|
1024
|
+
if (debug) println("[apex-capacitor] app_install already sent for this install; dropping")
|
|
1025
|
+
call.resolve()
|
|
1026
|
+
return
|
|
1027
|
+
}
|
|
1028
|
+
try {
|
|
1029
|
+
enqueuePayload(id, payload)
|
|
1030
|
+
call.resolve()
|
|
1031
|
+
} catch (e: Exception) {
|
|
1032
|
+
call.reject("Failed to enqueue event: ${e.message}")
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/** Stamp and queue an event. Shared by `track()` and the plugin's own install. */
|
|
1037
|
+
private fun enqueuePayload(id: String, payload: MutableMap<String, Any?>) {
|
|
1038
|
+
val queue = offlineQueue ?: throw IllegalStateException("Plugin not initialized")
|
|
919
1039
|
TrackStamps.apply(payload, visitorId, testMode, java.time.Instant.now().toString())
|
|
920
1040
|
|
|
921
1041
|
// MMP-061 — stamp release channel under event.mobile so the
|
|
@@ -934,7 +1054,10 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
934
1054
|
}
|
|
935
1055
|
mobileSlot["releaseChannel"] = releaseChannel
|
|
936
1056
|
mobileSlot["releaseChannelSource"] = releaseChannelSource
|
|
1057
|
+
stampDevice(mobileSlot)
|
|
1058
|
+
if (payload["type"] == "app_install") stampInstallReferrers(mobileSlot)
|
|
937
1059
|
payload["mobile"] = mobileSlot
|
|
1060
|
+
if (payload["type"] == "app_open") Thread { resolveGaid() }.start()
|
|
938
1061
|
|
|
939
1062
|
// MMP-081 — runtime context. Native Android plugin always
|
|
940
1063
|
// stamps `native-android`; we don't overwrite a value the
|
|
@@ -951,13 +1074,8 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
951
1074
|
attempts = 0,
|
|
952
1075
|
enqueuedAtMs = System.currentTimeMillis(),
|
|
953
1076
|
)
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
kickFlush("track")
|
|
957
|
-
call.resolve()
|
|
958
|
-
} catch (e: Exception) {
|
|
959
|
-
call.reject("Failed to enqueue event: ${e.message}")
|
|
960
|
-
}
|
|
1077
|
+
queue.enqueue(event)
|
|
1078
|
+
kickFlush("track")
|
|
961
1079
|
}
|
|
962
1080
|
|
|
963
1081
|
@PluginMethod
|
|
@@ -1010,6 +1128,7 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
1010
1128
|
if (granted) {
|
|
1011
1129
|
// Resume: flush anything captured before this point.
|
|
1012
1130
|
kickFlush("consent")
|
|
1131
|
+
Thread { sendInstallIfFirstLaunch() }.start()
|
|
1013
1132
|
} else {
|
|
1014
1133
|
// Revoke: drop anything queued but not yet sent.
|
|
1015
1134
|
try {
|
|
@@ -1108,8 +1227,71 @@ class ApexCapacitorPlugin : Plugin() {
|
|
|
1108
1227
|
})
|
|
1109
1228
|
}
|
|
1110
1229
|
|
|
1230
|
+
/**
|
|
1231
|
+
* The install event carries Play's referrer and Meta's, so Apex can
|
|
1232
|
+
* credit the ad. Waits briefly for Play when it hasn't answered yet,
|
|
1233
|
+
* off the main thread only.
|
|
1234
|
+
*/
|
|
1235
|
+
private fun stampInstallReferrers(slot: MutableMap<String, Any?>) {
|
|
1236
|
+
if (!installReferrerResolved && Looper.myLooper() != Looper.getMainLooper()) {
|
|
1237
|
+
try {
|
|
1238
|
+
referrerLatch.await(REFERRER_WAIT_MS, java.util.concurrent.TimeUnit.MILLISECONDS)
|
|
1239
|
+
} catch (_: InterruptedException) { }
|
|
1240
|
+
}
|
|
1241
|
+
MetaInstallReferrer.stampInstall(slot, lastInstallReferrer, installReferrerClickSeconds, readMetaReferrer())
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/** The Meta app id from the Facebook SDK's manifest entry, when the app has one. */
|
|
1245
|
+
@Suppress("DEPRECATION")
|
|
1246
|
+
private fun manifestMetaAppId(): String? = try {
|
|
1247
|
+
val info = context.packageManager.getApplicationInfo(
|
|
1248
|
+
context.packageName,
|
|
1249
|
+
android.content.pm.PackageManager.GET_META_DATA,
|
|
1250
|
+
)
|
|
1251
|
+
MetaInstallReferrer.normalizeAppId(info.metaData?.get("com.facebook.sdk.ApplicationId")?.toString())
|
|
1252
|
+
} catch (_: Exception) {
|
|
1253
|
+
null
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
/** Ask the Facebook, Instagram and Facebook Lite apps for the Meta ad behind this install. */
|
|
1257
|
+
private fun readMetaReferrer(): MetaInstallReferrer.Found? {
|
|
1258
|
+
if (metaReferrerRead) return metaReferrer
|
|
1259
|
+
val appId = metaAppId
|
|
1260
|
+
if (appId == null) {
|
|
1261
|
+
metaReferrerRead = true
|
|
1262
|
+
return null
|
|
1263
|
+
}
|
|
1264
|
+
val found = mutableListOf<MetaInstallReferrer.Found>()
|
|
1265
|
+
for ((authority, app) in MetaInstallReferrer.PROVIDERS) {
|
|
1266
|
+
try {
|
|
1267
|
+
if (context.packageManager.resolveContentProvider(authority, 0) == null) continue
|
|
1268
|
+
val uri = Uri.parse("content://$authority/$appId")
|
|
1269
|
+
context.contentResolver.query(uri, MetaInstallReferrer.COLUMNS, null, null, null)?.use { c ->
|
|
1270
|
+
if (!c.moveToFirst()) return@use
|
|
1271
|
+
val refIdx = c.getColumnIndex("install_referrer")
|
|
1272
|
+
if (refIdx < 0 || c.isNull(refIdx)) return@use
|
|
1273
|
+
val ctIdx = c.getColumnIndex("is_ct")
|
|
1274
|
+
val tsIdx = c.getColumnIndex("actual_timestamp")
|
|
1275
|
+
found += MetaInstallReferrer.Found(
|
|
1276
|
+
referrer = c.getString(refIdx),
|
|
1277
|
+
isClickThrough = if (ctIdx >= 0 && !c.isNull(ctIdx)) c.getInt(ctIdx) == 1 else null,
|
|
1278
|
+
timestampSeconds = if (tsIdx >= 0 && !c.isNull(tsIdx)) c.getLong(tsIdx) else null,
|
|
1279
|
+
app = app,
|
|
1280
|
+
)
|
|
1281
|
+
}
|
|
1282
|
+
} catch (e: Exception) {
|
|
1283
|
+
if (debug) println("[apex-capacitor] Meta referrer from $app failed: ${e.message}")
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
metaReferrer = MetaInstallReferrer.latest(found)
|
|
1287
|
+
metaReferrerRead = true
|
|
1288
|
+
if (debug) println("[apex-capacitor] Meta install referrer ${if (metaReferrer != null) "found (${metaReferrer?.app})" else "not found"}")
|
|
1289
|
+
return metaReferrer
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1111
1292
|
private fun flushPendingReferrerCalls() {
|
|
1112
1293
|
installReferrerResolved = true
|
|
1294
|
+
referrerLatch.countDown()
|
|
1113
1295
|
val waiting = synchronized(pendingReferrerCalls) {
|
|
1114
1296
|
val copy = pendingReferrerCalls.toList()
|
|
1115
1297
|
pendingReferrerCalls.clear()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package inc.apex.capacitor
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether this launch should send `app_install`. The plugin sends it once
|
|
5
|
+
* per install so every app counts installs the same way; the app's own
|
|
6
|
+
* `app_install` is dropped once one has gone.
|
|
7
|
+
*
|
|
8
|
+
* Someone who had the app before Apex was added is not a new install: the
|
|
9
|
+
* update that brings Apex must not report every existing user to the ad
|
|
10
|
+
* networks as one. A fresh install is one made in the last 7 days, or one
|
|
11
|
+
* never updated since (the version installed is the one running).
|
|
12
|
+
*/
|
|
13
|
+
internal object FirstLaunchInstall {
|
|
14
|
+
const val PREF_KEY = "installSent"
|
|
15
|
+
const val FRESH_WINDOW_MS: Long = 7L * 24 * 3600 * 1000
|
|
16
|
+
private const val SAME_VERSION_TOLERANCE_MS: Long = 5L * 60 * 1000
|
|
17
|
+
|
|
18
|
+
enum class Decision { SEND, ALREADY_SENT, EXISTING_USER }
|
|
19
|
+
|
|
20
|
+
fun decide(alreadySent: Boolean, installedMs: Long?, versionInstalledMs: Long?, nowMs: Long): Decision {
|
|
21
|
+
if (alreadySent) return Decision.ALREADY_SENT
|
|
22
|
+
if (installedMs == null || installedMs <= 0) return Decision.SEND
|
|
23
|
+
if (versionInstalledMs != null && kotlin.math.abs(versionInstalledMs - installedMs) <= SAME_VERSION_TOLERANCE_MS) {
|
|
24
|
+
return Decision.SEND
|
|
25
|
+
}
|
|
26
|
+
return if (nowMs - installedMs <= FRESH_WINDOW_MS) Decision.SEND else Decision.EXISTING_USER
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
package inc.apex.capacitor
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Meta Install Referrer: the Facebook, Instagram and Facebook Lite apps
|
|
5
|
+
* keep the Meta ad a person tapped or saw before installing, and hand it to
|
|
6
|
+
* the app that was installed. Play's referrer only carries a tap that led
|
|
7
|
+
* straight to the install; this also carries views and earlier taps.
|
|
8
|
+
*
|
|
9
|
+
* The campaign inside is encrypted with the app owner's key. The plugin
|
|
10
|
+
* never decrypts it; it goes to Apex on the `app_install` event and Apex
|
|
11
|
+
* opens it with the key the shop saved in the Meta connection.
|
|
12
|
+
*
|
|
13
|
+
* Pure logic here (no Android imports) so it runs under plain JUnit. The
|
|
14
|
+
* ContentResolver query lives in the plugin.
|
|
15
|
+
*/
|
|
16
|
+
internal object MetaInstallReferrer {
|
|
17
|
+
|
|
18
|
+
/** Content provider authority → the app name Apex records. */
|
|
19
|
+
val PROVIDERS: List<Pair<String, String>> = listOf(
|
|
20
|
+
"com.facebook.katana.provider.InstallReferrerProvider" to "facebook",
|
|
21
|
+
"com.instagram.contentprovider.InstallReferrerProvider" to "instagram",
|
|
22
|
+
"com.facebook.lite.provider.InstallReferrerProvider" to "facebook_lite",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
val COLUMNS: Array<String> = arrayOf("install_referrer", "is_ct", "actual_timestamp")
|
|
26
|
+
|
|
27
|
+
data class Found(
|
|
28
|
+
val referrer: String,
|
|
29
|
+
/** Null when the Meta app didn't say tap or view. */
|
|
30
|
+
val isClickThrough: Boolean?,
|
|
31
|
+
/** When the tap or view happened, in seconds. */
|
|
32
|
+
val timestampSeconds: Long?,
|
|
33
|
+
val app: String,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The Meta app id as the provider path wants it: digits only. Accepts
|
|
38
|
+
* the Facebook SDK's `fb1234…` form as well as the plain id.
|
|
39
|
+
*/
|
|
40
|
+
fun normalizeAppId(raw: String?): String? {
|
|
41
|
+
val trimmed = raw?.trim()?.removePrefix("fb") ?: return null
|
|
42
|
+
return if (trimmed.isNotEmpty() && trimmed.all { it.isDigit() }) trimmed else null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The most recent touch wins when more than one Meta app answered. */
|
|
46
|
+
fun latest(found: List<Found>): Found? =
|
|
47
|
+
found.filter { it.referrer.isNotBlank() }.maxByOrNull { it.timestampSeconds ?: 0L }
|
|
48
|
+
|
|
49
|
+
/** What goes under `event.mobile.metaInstallReferrer`. */
|
|
50
|
+
fun toSlot(found: Found): Map<String, Any?> {
|
|
51
|
+
val slot = mutableMapOf<String, Any?>("referrer" to found.referrer, "app" to found.app)
|
|
52
|
+
found.isClickThrough?.let { slot["isClickThrough"] = it }
|
|
53
|
+
found.timestampSeconds?.let { if (it > 0) slot["timestamp"] = it }
|
|
54
|
+
return slot
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Stamp the install's referrers on an `app_install` event, keeping
|
|
59
|
+
* anything the app already set.
|
|
60
|
+
*/
|
|
61
|
+
fun stampInstall(
|
|
62
|
+
slot: MutableMap<String, Any?>,
|
|
63
|
+
playReferrer: String?,
|
|
64
|
+
playClickSeconds: Long,
|
|
65
|
+
meta: Found?,
|
|
66
|
+
) {
|
|
67
|
+
if (slot["installReferrer"] == null && !playReferrer.isNullOrBlank()) {
|
|
68
|
+
slot["installReferrer"] = playReferrer
|
|
69
|
+
if (playClickSeconds > 0) slot["installReferrerClickTimestamp"] = playClickSeconds
|
|
70
|
+
}
|
|
71
|
+
if (slot["metaInstallReferrer"] == null && meta != null) {
|
|
72
|
+
slot["metaInstallReferrer"] = toSlot(meta)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package inc.apex.capacitor
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The device details stamped under `event.mobile` on every event, matching
|
|
5
|
+
* iOS. Apex builds the ad networks' app-event device block from them
|
|
6
|
+
* (Meta's `app_data` + `extinfo`), so an event without them reaches Meta
|
|
7
|
+
* with a blank device.
|
|
8
|
+
*
|
|
9
|
+
* The advertising id is the GAID, and only when the person has not limited
|
|
10
|
+
* ad tracking. The Android ID fallback is never sent: it is not an
|
|
11
|
+
* advertising id and Meta must not match on it.
|
|
12
|
+
*/
|
|
13
|
+
internal object MobileContext {
|
|
14
|
+
private const val ZERO_ID = "00000000-0000-0000-0000-000000000000"
|
|
15
|
+
|
|
16
|
+
data class Device(
|
|
17
|
+
val bundleId: String,
|
|
18
|
+
val appVersion: String,
|
|
19
|
+
val osVersion: String,
|
|
20
|
+
val deviceModel: String,
|
|
21
|
+
val timezone: String,
|
|
22
|
+
val locale: String,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
/** The GAID to send, or null when tracking is limited or the person deleted the id. */
|
|
26
|
+
fun advertisingId(id: String?, limitAdTracking: Boolean): String? =
|
|
27
|
+
if (limitAdTracking || id.isNullOrBlank() || id == ZERO_ID) null else id.lowercase()
|
|
28
|
+
|
|
29
|
+
/** Fill the fields the caller didn't set on the event. */
|
|
30
|
+
fun fill(slot: MutableMap<String, Any?>, device: Device, gaid: String?) {
|
|
31
|
+
putIfMissing(slot, "bundleId", device.bundleId)
|
|
32
|
+
putIfMissing(slot, "appVersion", device.appVersion)
|
|
33
|
+
putIfMissing(slot, "osVersion", device.osVersion)
|
|
34
|
+
putIfMissing(slot, "deviceModel", device.deviceModel)
|
|
35
|
+
putIfMissing(slot, "timezone", device.timezone)
|
|
36
|
+
putIfMissing(slot, "locale", device.locale)
|
|
37
|
+
if (gaid != null) putIfMissing(slot, "gaid", gaid)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private fun putIfMissing(slot: MutableMap<String, Any?>, key: String, value: String) {
|
|
41
|
+
if (slot[key] == null) slot[key] = value
|
|
42
|
+
}
|
|
43
|
+
}
|
package/dist/definitions.d.ts
CHANGED
|
@@ -205,10 +205,15 @@ export interface InitializeOptions {
|
|
|
205
205
|
* until you call `setConsent({ granted: true })` (e.g. from your privacy
|
|
206
206
|
* prompt's accept handler). Default `false` (collect immediately).
|
|
207
207
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
208
|
+
* One exception: `identify` still tells Apex who signed up, because
|
|
209
|
+
* signing up is their own reason for you to know them. It sends no event
|
|
210
|
+
* and no device id, and Apex records advertising consent as denied.
|
|
211
|
+
*
|
|
212
|
+
* Apex counts people by a first-party visitor id. The advertising id is a
|
|
213
|
+
* separate permission: events carry the IDFA only after the person allows
|
|
214
|
+
* tracking in the ATT prompt (`requestTrackingAuthorization`), and the
|
|
215
|
+
* GAID only when they haven't limited ad tracking. The IDFV and Android
|
|
216
|
+
* ID are never put on events.
|
|
212
217
|
*/
|
|
213
218
|
requireConsent?: boolean;
|
|
214
219
|
/**
|
|
@@ -247,6 +252,26 @@ export interface InitializeOptions {
|
|
|
247
252
|
* workspace has more than one. Defaults to the workspace's first app.
|
|
248
253
|
*/
|
|
249
254
|
mobileAppId?: string;
|
|
255
|
+
/**
|
|
256
|
+
* Your Meta (Facebook) app id, from Meta for Developers. On Android the
|
|
257
|
+
* plugin uses it to ask the Facebook, Instagram and Facebook Lite apps
|
|
258
|
+
* which Meta ad the person tapped or saw before installing, and sends
|
|
259
|
+
* that with the `app_install` event. Apex opens it with the install
|
|
260
|
+
* referrer key saved in your Meta connection and credits the ad.
|
|
261
|
+
*
|
|
262
|
+
* Optional when your app already has the Facebook SDK's
|
|
263
|
+
* `com.facebook.sdk.ApplicationId` manifest entry. No-op on iOS and web.
|
|
264
|
+
*/
|
|
265
|
+
metaAppId?: string;
|
|
266
|
+
/**
|
|
267
|
+
* Send `app_install` once, on the first launch of a fresh install
|
|
268
|
+
* (default true on iOS and Android; no-op on web). It carries what Apex
|
|
269
|
+
* needs to credit the ad behind the install and to report it to the ad
|
|
270
|
+
* networks you connect. Someone who had the app before Apex was added is
|
|
271
|
+
* not sent as an install. Whether the plugin or your app sends it, only
|
|
272
|
+
* the first `app_install` per install goes.
|
|
273
|
+
*/
|
|
274
|
+
autoTrackInstall?: boolean;
|
|
250
275
|
}
|
|
251
276
|
/**
|
|
252
277
|
* Options for {@link ApexCapacitorPlugin.identify}.
|
|
@@ -400,7 +425,8 @@ export interface ApexCapacitorPlugin {
|
|
|
400
425
|
/**
|
|
401
426
|
* Returns IDFA (iOS) or GAID (Android). When unavailable (ATT denied or LAT
|
|
402
427
|
* enabled), returns a fallback with `fallback` indicating which identifier
|
|
403
|
-
* was substituted.
|
|
428
|
+
* was substituted. Events never carry the fallback: they get `idfa` /
|
|
429
|
+
* `gaid` under `mobile` only when the real advertising id is allowed.
|
|
404
430
|
*/
|
|
405
431
|
getAdvertisingId(): Promise<AdvertisingIdResult>;
|
|
406
432
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../src/definitions.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../src/definitions.ts"],"names":[],"mappings":"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"}
|