@virex-tech/paywallo-sdk 2.3.0 → 2.4.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/dist/index.js +220 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +220 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -412,11 +412,28 @@ function parseProperties(json) {
|
|
|
412
412
|
return {};
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
|
-
|
|
415
|
+
async function persistAnonIdDurably(storage, anonId) {
|
|
416
|
+
let stored = await storage.set(ANON_ID_KEY, anonId);
|
|
417
|
+
for (let i = 0; i < ANON_ID_SET_RETRIES && !stored; i++) {
|
|
418
|
+
await new Promise((r) => setTimeout(r, ANON_ID_RETRY_DELAY_MS));
|
|
419
|
+
stored = await storage.set(ANON_ID_KEY, anonId);
|
|
420
|
+
}
|
|
421
|
+
if (!stored) {
|
|
422
|
+
await nativeStorage.set(ANON_ID_FALLBACK_KEY, anonId).catch(() => void 0);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async function readAnonIdDurably(storage) {
|
|
426
|
+
const secure = await readWithMigration(storage, ANON_ID_KEY, LEGACY_ANON_ID_KEY);
|
|
427
|
+
if (secure) return secure;
|
|
428
|
+
return nativeStorage.get(ANON_ID_FALLBACK_KEY);
|
|
429
|
+
}
|
|
430
|
+
var DEVICE_ID_KEY, ANON_ID_FALLBACK_KEY, ANON_ID_KEY, USER_EMAIL_KEY, USER_PROPERTIES_KEY, USER_DISTINCT_ID_KEY, USER_NAME_KEY, USER_COUNTRY_KEY, USER_LOCALE_KEY, USER_PHONE_KEY, USER_FIRST_NAME_KEY, USER_LAST_NAME_KEY, USER_DOB_KEY, USER_GENDER_KEY, LEGACY_USER_PHONE_KEY, LEGACY_USER_FIRST_NAME_KEY, LEGACY_USER_LAST_NAME_KEY, LEGACY_USER_DOB_KEY, LEGACY_USER_GENDER_KEY, LEGACY_DEVICE_ID_KEY, LEGACY_ANON_ID_KEY, LEGACY_EMAIL_KEY, LEGACY_PROPERTIES_KEY, LEGACY_DISTINCT_ID_KEY, LEGACY_NAME_KEY, LEGACY_COUNTRY_KEY, LEGACY_LOCALE_KEY, ANON_ID_SET_RETRIES, ANON_ID_RETRY_DELAY_MS;
|
|
416
431
|
var init_IdentityStorage = __esm({
|
|
417
432
|
"src/domains/identity/IdentityStorage.ts"() {
|
|
418
433
|
"use strict";
|
|
434
|
+
init_NativeStorage();
|
|
419
435
|
DEVICE_ID_KEY = "@paywallo:device_id";
|
|
436
|
+
ANON_ID_FALLBACK_KEY = "@paywallo:anon_id_fallback";
|
|
420
437
|
ANON_ID_KEY = "@paywallo:anon_id";
|
|
421
438
|
USER_EMAIL_KEY = "@paywallo:user_email";
|
|
422
439
|
USER_PROPERTIES_KEY = "@paywallo:user_properties";
|
|
@@ -442,6 +459,8 @@ var init_IdentityStorage = __esm({
|
|
|
442
459
|
LEGACY_NAME_KEY = "user_name";
|
|
443
460
|
LEGACY_COUNTRY_KEY = "user_country";
|
|
444
461
|
LEGACY_LOCALE_KEY = "user_locale";
|
|
462
|
+
ANON_ID_SET_RETRIES = 2;
|
|
463
|
+
ANON_ID_RETRY_DELAY_MS = 50;
|
|
445
464
|
}
|
|
446
465
|
});
|
|
447
466
|
|
|
@@ -521,8 +540,7 @@ var init_IdentityManager = __esm({
|
|
|
521
540
|
}
|
|
522
541
|
if (!this.anonId) {
|
|
523
542
|
this.anonId = generateUUID();
|
|
524
|
-
await this.secureStorage
|
|
525
|
-
});
|
|
543
|
+
await persistAnonIdDurably(this.secureStorage, this.anonId);
|
|
526
544
|
}
|
|
527
545
|
this.initialized = true;
|
|
528
546
|
return this.deviceId ?? "";
|
|
@@ -582,7 +600,8 @@ var init_IdentityManager = __esm({
|
|
|
582
600
|
dateOfBirth: this.dateOfBirth ?? void 0,
|
|
583
601
|
gender: this.gender ?? void 0
|
|
584
602
|
});
|
|
585
|
-
} catch {
|
|
603
|
+
} catch (err) {
|
|
604
|
+
if (this.debug) console.log("[Paywallo] identify dispatch error", err);
|
|
586
605
|
}
|
|
587
606
|
}
|
|
588
607
|
}
|
|
@@ -606,7 +625,8 @@ var init_IdentityManager = __esm({
|
|
|
606
625
|
if (this.apiClient && this.anonId) {
|
|
607
626
|
try {
|
|
608
627
|
await this.apiClient.identify(this.anonId, this.properties, this.email ?? void 0, this.deviceId ?? void 0);
|
|
609
|
-
} catch {
|
|
628
|
+
} catch (err) {
|
|
629
|
+
if (this.debug) console.log("[Paywallo] identify dispatch error", err);
|
|
610
630
|
}
|
|
611
631
|
}
|
|
612
632
|
}
|
|
@@ -649,18 +669,20 @@ var init_IdentityManager = __esm({
|
|
|
649
669
|
}
|
|
650
670
|
async loadPersistedState() {
|
|
651
671
|
if (!this.secureStorage) return;
|
|
652
|
-
const state = await
|
|
672
|
+
const [state, rawAnonId] = await Promise.all([
|
|
673
|
+
loadPersistedIdentity(this.secureStorage),
|
|
674
|
+
readAnonIdDurably(this.secureStorage)
|
|
675
|
+
]);
|
|
653
676
|
const deviceId = state.deviceId ?? await readDeviceIdWithFallback(this.secureStorage);
|
|
654
677
|
if (deviceId) this.deviceId = deviceId;
|
|
655
|
-
if (
|
|
678
|
+
if (rawAnonId) {
|
|
656
679
|
const legacyPrefix = "$paywallo_anon:";
|
|
657
|
-
if (
|
|
658
|
-
const stripped =
|
|
680
|
+
if (rawAnonId.startsWith(legacyPrefix)) {
|
|
681
|
+
const stripped = rawAnonId.slice(legacyPrefix.length);
|
|
659
682
|
this.anonId = stripped;
|
|
660
|
-
await this.secureStorage.set(ANON_ID_KEY, stripped).catch(() =>
|
|
661
|
-
});
|
|
683
|
+
await this.secureStorage.set(ANON_ID_KEY, stripped).catch(() => void 0);
|
|
662
684
|
} else {
|
|
663
|
-
this.anonId =
|
|
685
|
+
this.anonId = rawAnonId;
|
|
664
686
|
}
|
|
665
687
|
}
|
|
666
688
|
if (state.email) this.email = state.email;
|
|
@@ -885,21 +907,23 @@ var init_AdvertisingIdManager = __esm({
|
|
|
885
907
|
if (Platform.OS === "ios") {
|
|
886
908
|
if (!tracking.isAvailable()) {
|
|
887
909
|
const idfv2 = await this.collectIdfv();
|
|
888
|
-
|
|
889
|
-
|
|
910
|
+
const result2 = { ...fallback, idfv: idfv2 };
|
|
911
|
+
if (idfv2 !== null) this.cached = result2;
|
|
912
|
+
return result2;
|
|
890
913
|
}
|
|
891
914
|
const current = await tracking.getTrackingPermissionsAsync();
|
|
892
915
|
let status = current.status;
|
|
893
916
|
let granted = current.granted;
|
|
894
917
|
if (status === "undetermined" && requestATT) {
|
|
895
|
-
const
|
|
896
|
-
status =
|
|
897
|
-
granted =
|
|
918
|
+
const result2 = await tracking.requestTrackingPermissionsAsync();
|
|
919
|
+
status = result2.status;
|
|
920
|
+
granted = result2.granted;
|
|
898
921
|
}
|
|
899
922
|
const idfv = await this.collectIdfv();
|
|
900
923
|
const idfa = granted ? this.sanitizeId(tracking.getAdvertisingId()) : null;
|
|
901
|
-
|
|
902
|
-
|
|
924
|
+
const result = { idfv, idfa, gaid: null, attStatus: status };
|
|
925
|
+
if (idfv !== null) this.cached = result;
|
|
926
|
+
return result;
|
|
903
927
|
}
|
|
904
928
|
if (Platform.OS === "android") {
|
|
905
929
|
const rawGaid = tracking.getAdvertisingId();
|
|
@@ -915,12 +939,20 @@ var init_AdvertisingIdManager = __esm({
|
|
|
915
939
|
}
|
|
916
940
|
}
|
|
917
941
|
async collectIdfv() {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
942
|
+
const RETRY_DELAY_MS = 80;
|
|
943
|
+
const MAX_ATTEMPTS = 3;
|
|
944
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
945
|
+
try {
|
|
946
|
+
const info = await nativeDeviceInfo.getDeviceInfo();
|
|
947
|
+
const idfv = this.sanitizeId(info.idfv);
|
|
948
|
+
if (idfv !== null) return idfv;
|
|
949
|
+
} catch {
|
|
950
|
+
}
|
|
951
|
+
if (attempt < MAX_ATTEMPTS - 1) {
|
|
952
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
|
|
953
|
+
}
|
|
923
954
|
}
|
|
955
|
+
return null;
|
|
924
956
|
}
|
|
925
957
|
sanitizeId(id) {
|
|
926
958
|
if (!id || id === ZERO_IDFA) return null;
|
|
@@ -1358,6 +1390,8 @@ var init_AttributionTracker = __esm({
|
|
|
1358
1390
|
|
|
1359
1391
|
// src/domains/identity/InstallIdempotency.ts
|
|
1360
1392
|
async function checkAndArmInstallGuard(storage) {
|
|
1393
|
+
if (armedThisLaunch) return true;
|
|
1394
|
+
armedThisLaunch = true;
|
|
1361
1395
|
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
1362
1396
|
if (alreadyTracked) return true;
|
|
1363
1397
|
let fallbackTracked = null;
|
|
@@ -1391,7 +1425,7 @@ async function getOrCreateInstallEventId() {
|
|
|
1391
1425
|
});
|
|
1392
1426
|
return id;
|
|
1393
1427
|
}
|
|
1394
|
-
var INSTALL_KEYS;
|
|
1428
|
+
var INSTALL_KEYS, armedThisLaunch;
|
|
1395
1429
|
var init_InstallIdempotency = __esm({
|
|
1396
1430
|
"src/domains/identity/InstallIdempotency.ts"() {
|
|
1397
1431
|
"use strict";
|
|
@@ -1416,6 +1450,7 @@ var init_InstallIdempotency = __esm({
|
|
|
1416
1450
|
/** Legacy anon ID key written by SDK versions that used @panel: prefix. */
|
|
1417
1451
|
LEGACY_ANON_ID: "@panel:anon_id"
|
|
1418
1452
|
};
|
|
1453
|
+
armedThisLaunch = false;
|
|
1419
1454
|
}
|
|
1420
1455
|
});
|
|
1421
1456
|
|
|
@@ -2370,8 +2405,8 @@ var init_NotificationHandlerSetup = __esm({
|
|
|
2370
2405
|
// src/core/version.ts
|
|
2371
2406
|
function resolveVersion() {
|
|
2372
2407
|
try {
|
|
2373
|
-
if ("2.
|
|
2374
|
-
return "2.
|
|
2408
|
+
if ("2.4.1") {
|
|
2409
|
+
return "2.4.1";
|
|
2375
2410
|
}
|
|
2376
2411
|
} catch {
|
|
2377
2412
|
}
|
|
@@ -4244,10 +4279,10 @@ var init_OfflineQueueStorage = __esm({
|
|
|
4244
4279
|
init_NativeStorage();
|
|
4245
4280
|
init_QueueJournal();
|
|
4246
4281
|
OfflineQueueStorage = class {
|
|
4247
|
-
constructor(config, emit,
|
|
4282
|
+
constructor(config, emit, log3) {
|
|
4248
4283
|
this.config = config;
|
|
4249
4284
|
this.emit = emit;
|
|
4250
|
-
this.log =
|
|
4285
|
+
this.log = log3;
|
|
4251
4286
|
}
|
|
4252
4287
|
async loadFromStorage(queue) {
|
|
4253
4288
|
const { merged, recovered, hadJournal } = await mergeJournalIntoMain(
|
|
@@ -4496,11 +4531,11 @@ var init_OfflineQueue = __esm({
|
|
|
4496
4531
|
});
|
|
4497
4532
|
return true;
|
|
4498
4533
|
}
|
|
4499
|
-
const
|
|
4534
|
+
const delay2 = Math.min(
|
|
4500
4535
|
this.config.baseRetryDelayMs * Math.pow(2, item.attempts - 1),
|
|
4501
4536
|
this.config.maxRetryDelayMs
|
|
4502
4537
|
);
|
|
4503
|
-
item.nextRetryAt = Date.now() +
|
|
4538
|
+
item.nextRetryAt = Date.now() + delay2;
|
|
4504
4539
|
await this.storage.saveToStorage(this.queue);
|
|
4505
4540
|
return false;
|
|
4506
4541
|
}
|
|
@@ -7778,8 +7813,8 @@ var init_HttpClient = __esm({
|
|
|
7778
7813
|
if (this.shouldRetry(response.status, retryConfig)) {
|
|
7779
7814
|
if (state.attempt < retryConfig.maxRetries) {
|
|
7780
7815
|
state.attempt++;
|
|
7781
|
-
const
|
|
7782
|
-
await this.sleep(
|
|
7816
|
+
const delay2 = this.calculateDelayForResponse(state.attempt, response.headers, retryConfig);
|
|
7817
|
+
await this.sleep(delay2);
|
|
7783
7818
|
continue;
|
|
7784
7819
|
}
|
|
7785
7820
|
}
|
|
@@ -7788,8 +7823,8 @@ var init_HttpClient = __esm({
|
|
|
7788
7823
|
state.lastError = error instanceof Error ? error : new ClientError(CLIENT_ERROR_CODES.UNKNOWN, String(error));
|
|
7789
7824
|
if (this.isNetworkError(state.lastError) && state.attempt < retryConfig.maxRetries) {
|
|
7790
7825
|
state.attempt++;
|
|
7791
|
-
const
|
|
7792
|
-
await this.sleep(
|
|
7826
|
+
const delay2 = this.calculateDelay(state.attempt, retryConfig);
|
|
7827
|
+
await this.sleep(delay2);
|
|
7793
7828
|
continue;
|
|
7794
7829
|
}
|
|
7795
7830
|
throw state.lastError;
|
|
@@ -7938,7 +7973,36 @@ var init_http = __esm({
|
|
|
7938
7973
|
|
|
7939
7974
|
// src/core/ApiClient.ts
|
|
7940
7975
|
import { Platform as Platform15 } from "react-native";
|
|
7941
|
-
|
|
7976
|
+
function normalizeDateOfBirth(raw) {
|
|
7977
|
+
if (!raw) return void 0;
|
|
7978
|
+
if (DATE_OF_BIRTH_RE.test(raw)) return raw;
|
|
7979
|
+
const d = new Date(raw);
|
|
7980
|
+
if (isNaN(d.getTime())) return void 0;
|
|
7981
|
+
const hasTimeComponent = raw.includes("T") || raw.includes("Z");
|
|
7982
|
+
const yyyy = hasTimeComponent ? d.getUTCFullYear() : d.getFullYear();
|
|
7983
|
+
const mm = String((hasTimeComponent ? d.getUTCMonth() : d.getMonth()) + 1).padStart(2, "0");
|
|
7984
|
+
const dd = String(hasTimeComponent ? d.getUTCDate() : d.getDate()).padStart(2, "0");
|
|
7985
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
7986
|
+
}
|
|
7987
|
+
function buildPiiPayload(pii) {
|
|
7988
|
+
const result = {};
|
|
7989
|
+
if (pii.phone) result.phone = pii.phone;
|
|
7990
|
+
if (pii.firstName) result.firstName = pii.firstName;
|
|
7991
|
+
if (pii.lastName) result.lastName = pii.lastName;
|
|
7992
|
+
const dob = normalizeDateOfBirth(pii.dateOfBirth);
|
|
7993
|
+
if (dob) result.dateOfBirth = dob;
|
|
7994
|
+
const g = normalizeGender(pii.gender);
|
|
7995
|
+
if (g) result.gender = g;
|
|
7996
|
+
return result;
|
|
7997
|
+
}
|
|
7998
|
+
function normalizeGender(raw) {
|
|
7999
|
+
if (!raw) return void 0;
|
|
8000
|
+
const lower = raw.toLowerCase();
|
|
8001
|
+
if (lower === "m" || lower === "male") return "m";
|
|
8002
|
+
if (lower === "f" || lower === "female") return "f";
|
|
8003
|
+
return void 0;
|
|
8004
|
+
}
|
|
8005
|
+
var DATE_OF_BIRTH_RE, ApiClient;
|
|
7942
8006
|
var init_ApiClient = __esm({
|
|
7943
8007
|
"src/core/ApiClient.ts"() {
|
|
7944
8008
|
"use strict";
|
|
@@ -7951,6 +8015,7 @@ var init_ApiClient = __esm({
|
|
|
7951
8015
|
init_http();
|
|
7952
8016
|
init_queue();
|
|
7953
8017
|
init_version();
|
|
8018
|
+
DATE_OF_BIRTH_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
7954
8019
|
ApiClient = class {
|
|
7955
8020
|
constructor(appKey, apiUrl, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
|
|
7956
8021
|
this.cache = new ApiCache();
|
|
@@ -8125,11 +8190,7 @@ var init_ApiClient = __esm({
|
|
|
8125
8190
|
traits,
|
|
8126
8191
|
...attribution && { attribution },
|
|
8127
8192
|
...deviceId && { deviceId },
|
|
8128
|
-
...pii
|
|
8129
|
-
...pii?.firstName && { firstName: pii.firstName },
|
|
8130
|
-
...pii?.lastName && { lastName: pii.lastName },
|
|
8131
|
-
...pii?.dateOfBirth && { dateOfBirth: pii.dateOfBirth },
|
|
8132
|
-
...pii?.gender && { gender: pii.gender }
|
|
8193
|
+
...pii ? buildPiiPayload(pii) : {}
|
|
8133
8194
|
},
|
|
8134
8195
|
"identify"
|
|
8135
8196
|
);
|
|
@@ -8415,8 +8476,8 @@ async function initWithRetry(state, config) {
|
|
|
8415
8476
|
} catch (error) {
|
|
8416
8477
|
state.initAttempts++;
|
|
8417
8478
|
if (state.initAttempts > MAX_INIT_RETRIES) throw error;
|
|
8418
|
-
const
|
|
8419
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
8479
|
+
const delay2 = RETRY_DELAYS[state.initAttempts - 1] ?? 1e4;
|
|
8480
|
+
await new Promise((resolve) => setTimeout(resolve, delay2));
|
|
8420
8481
|
}
|
|
8421
8482
|
}
|
|
8422
8483
|
}
|
|
@@ -9691,6 +9752,108 @@ init_paywall();
|
|
|
9691
9752
|
init_paywall();
|
|
9692
9753
|
init_paywall();
|
|
9693
9754
|
|
|
9755
|
+
// src/domains/paywall/SuperwallAttributeBridge.ts
|
|
9756
|
+
init_identity();
|
|
9757
|
+
var CONFIG_POLL_INTERVAL_MS = 250;
|
|
9758
|
+
var CONFIG_POLL_MAX_ATTEMPTS = 40;
|
|
9759
|
+
var lastSignature = null;
|
|
9760
|
+
function log(debug, msg, data) {
|
|
9761
|
+
if (!debug) return;
|
|
9762
|
+
if (data !== void 0) console.log(`[Paywallo:SuperwallAttr] ${msg}`, data);
|
|
9763
|
+
else console.log(`[Paywallo:SuperwallAttr] ${msg}`);
|
|
9764
|
+
}
|
|
9765
|
+
function delay(ms) {
|
|
9766
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
9767
|
+
}
|
|
9768
|
+
var PAID_MEDIUM = /cpc|ppc|cpm|cpa|paid|display/i;
|
|
9769
|
+
function deriveIsPaid(a) {
|
|
9770
|
+
if (a.fbclid || a.gclid || a.ttclid || a.tiktokCampaignId) return true;
|
|
9771
|
+
return Boolean(a.utmMedium && PAID_MEDIUM.test(a.utmMedium));
|
|
9772
|
+
}
|
|
9773
|
+
function deriveAdNetwork(a) {
|
|
9774
|
+
if (a.fbclid) return "meta";
|
|
9775
|
+
if (a.ttclid || a.tiktokCampaignId) return "tiktok";
|
|
9776
|
+
if (a.gclid) return "google";
|
|
9777
|
+
return a.utmSource;
|
|
9778
|
+
}
|
|
9779
|
+
function buildSuperwallAttributes(a) {
|
|
9780
|
+
const out = {};
|
|
9781
|
+
if (!a) {
|
|
9782
|
+
out.pw_is_paid = false;
|
|
9783
|
+
return out;
|
|
9784
|
+
}
|
|
9785
|
+
const set2 = (key, value) => {
|
|
9786
|
+
if (value) out[key] = value;
|
|
9787
|
+
};
|
|
9788
|
+
set2("pw_utm_source", a.utmSource);
|
|
9789
|
+
set2("pw_utm_medium", a.utmMedium);
|
|
9790
|
+
set2("pw_utm_campaign", a.utmCampaign);
|
|
9791
|
+
set2("pw_utm_content", a.utmContent);
|
|
9792
|
+
set2("pw_utm_term", a.utmTerm);
|
|
9793
|
+
set2("pw_fbclid", a.fbclid);
|
|
9794
|
+
set2("pw_gclid", a.gclid);
|
|
9795
|
+
set2("pw_ttclid", a.ttclid);
|
|
9796
|
+
set2("pw_tiktok_campaign_id", a.tiktokCampaignId);
|
|
9797
|
+
set2("pw_tiktok_adgroup_id", a.tiktokAdgroupId);
|
|
9798
|
+
set2("pw_tiktok_ad_id", a.tiktokAdId);
|
|
9799
|
+
set2("pw_referrer", a.referrer);
|
|
9800
|
+
set2("pw_install_referrer_source", a.installReferrerSource);
|
|
9801
|
+
set2("pw_ad_network", deriveAdNetwork(a));
|
|
9802
|
+
out.pw_is_paid = deriveIsPaid(a);
|
|
9803
|
+
out.pw_attributed_at = a.capturedAt;
|
|
9804
|
+
return out;
|
|
9805
|
+
}
|
|
9806
|
+
function pickNative(mod) {
|
|
9807
|
+
const native = mod?.SuperwallExpoModule ?? mod?.default?.SuperwallExpoModule;
|
|
9808
|
+
return native && typeof native.setUserAttributes === "function" && typeof native.getConfigurationStatus === "function" ? native : null;
|
|
9809
|
+
}
|
|
9810
|
+
async function resolveSuperwallNativeModule(debug) {
|
|
9811
|
+
try {
|
|
9812
|
+
const native = pickNative(await import("expo-superwall"));
|
|
9813
|
+
if (native) return native;
|
|
9814
|
+
} catch {
|
|
9815
|
+
}
|
|
9816
|
+
log(debug, "expo-superwall native module not available \u2014 attribute push skipped");
|
|
9817
|
+
return null;
|
|
9818
|
+
}
|
|
9819
|
+
async function waitForConfigured(mod, debug) {
|
|
9820
|
+
for (let attempt = 0; attempt < CONFIG_POLL_MAX_ATTEMPTS; attempt++) {
|
|
9821
|
+
let status;
|
|
9822
|
+
try {
|
|
9823
|
+
status = String(await mod.getConfigurationStatus());
|
|
9824
|
+
} catch (err) {
|
|
9825
|
+
log(debug, "getConfigurationStatus error", { err: String(err) });
|
|
9826
|
+
return false;
|
|
9827
|
+
}
|
|
9828
|
+
if (status === "CONFIGURED") return true;
|
|
9829
|
+
if (status === "FAILED") {
|
|
9830
|
+
log(debug, "Superwall configuration FAILED \u2014 skipping attribute push");
|
|
9831
|
+
return false;
|
|
9832
|
+
}
|
|
9833
|
+
await delay(CONFIG_POLL_INTERVAL_MS);
|
|
9834
|
+
}
|
|
9835
|
+
log(debug, "Superwall not configured within timeout \u2014 skipping attribute push");
|
|
9836
|
+
return false;
|
|
9837
|
+
}
|
|
9838
|
+
async function pushAttributionToSuperwall(debug = false) {
|
|
9839
|
+
const attrs = buildSuperwallAttributes(attributionTracker.get());
|
|
9840
|
+
const signature = JSON.stringify(attrs);
|
|
9841
|
+
if (signature === lastSignature) {
|
|
9842
|
+
log(debug, "attributes unchanged \u2014 skipping push");
|
|
9843
|
+
return;
|
|
9844
|
+
}
|
|
9845
|
+
const native = await resolveSuperwallNativeModule(debug);
|
|
9846
|
+
if (!native) return;
|
|
9847
|
+
if (!await waitForConfigured(native, debug)) return;
|
|
9848
|
+
try {
|
|
9849
|
+
await native.setUserAttributes(attrs);
|
|
9850
|
+
lastSignature = signature;
|
|
9851
|
+
log(debug, "attributes pushed to Superwall", attrs);
|
|
9852
|
+
} catch (err) {
|
|
9853
|
+
log(debug, "setUserAttributes error", { err: String(err) });
|
|
9854
|
+
}
|
|
9855
|
+
}
|
|
9856
|
+
|
|
9694
9857
|
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9695
9858
|
init_PaywalloClient();
|
|
9696
9859
|
|
|
@@ -9724,7 +9887,7 @@ function buildDeterministicEventId(parts) {
|
|
|
9724
9887
|
var bridgeStarted = false;
|
|
9725
9888
|
var unsubscribe = null;
|
|
9726
9889
|
var debugEnabled = false;
|
|
9727
|
-
function
|
|
9890
|
+
function log2(msg, data) {
|
|
9728
9891
|
if (!debugEnabled) return;
|
|
9729
9892
|
if (data !== void 0) {
|
|
9730
9893
|
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
@@ -9754,7 +9917,7 @@ async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
|
9754
9917
|
}
|
|
9755
9918
|
});
|
|
9756
9919
|
} catch (err) {
|
|
9757
|
-
|
|
9920
|
+
log2("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
9758
9921
|
}
|
|
9759
9922
|
}
|
|
9760
9923
|
function mapDismissToCloseReason(resultType) {
|
|
@@ -9774,7 +9937,7 @@ function buildCallbacks() {
|
|
|
9774
9937
|
return {
|
|
9775
9938
|
onPaywallPresent: (info) => {
|
|
9776
9939
|
const ts = Date.now();
|
|
9777
|
-
|
|
9940
|
+
log2("onPaywallPresent", { identifier: info.identifier });
|
|
9778
9941
|
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
9779
9942
|
placement: info.presentedByEventWithName,
|
|
9780
9943
|
variant_id: info.experiment?.variant?.id,
|
|
@@ -9783,7 +9946,7 @@ function buildCallbacks() {
|
|
|
9783
9946
|
},
|
|
9784
9947
|
onPaywallDismiss: (info, result) => {
|
|
9785
9948
|
const ts = Date.now();
|
|
9786
|
-
|
|
9949
|
+
log2("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
9787
9950
|
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
9788
9951
|
placement: info.presentedByEventWithName,
|
|
9789
9952
|
variant_id: info.experiment?.variant?.id,
|
|
@@ -9797,7 +9960,7 @@ function buildCallbacks() {
|
|
|
9797
9960
|
const safe = params !== null && typeof params === "object" ? params : {};
|
|
9798
9961
|
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
9799
9962
|
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
9800
|
-
|
|
9963
|
+
log2("onPurchase", { productId, identifier });
|
|
9801
9964
|
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
9802
9965
|
},
|
|
9803
9966
|
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
@@ -9812,7 +9975,7 @@ function buildCallbacks() {
|
|
|
9812
9975
|
const product = ev.product;
|
|
9813
9976
|
const transaction = ev.transaction;
|
|
9814
9977
|
if (!product) {
|
|
9815
|
-
|
|
9978
|
+
log2("transactionComplete missing product \u2014 skipping transaction track");
|
|
9816
9979
|
return;
|
|
9817
9980
|
}
|
|
9818
9981
|
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
@@ -9821,7 +9984,7 @@ function buildCallbacks() {
|
|
|
9821
9984
|
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
9822
9985
|
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
9823
9986
|
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
9824
|
-
|
|
9987
|
+
log2("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
9825
9988
|
void (async () => {
|
|
9826
9989
|
try {
|
|
9827
9990
|
await PaywalloClient.track("transaction", {
|
|
@@ -9839,7 +10002,7 @@ function buildCallbacks() {
|
|
|
9839
10002
|
}
|
|
9840
10003
|
});
|
|
9841
10004
|
} catch (err) {
|
|
9842
|
-
|
|
10005
|
+
log2("transactionComplete track error", { err: String(err) });
|
|
9843
10006
|
}
|
|
9844
10007
|
})();
|
|
9845
10008
|
}
|
|
@@ -9848,7 +10011,7 @@ function buildCallbacks() {
|
|
|
9848
10011
|
function startSuperwallAutoBridge(debug = false) {
|
|
9849
10012
|
debugEnabled = debug;
|
|
9850
10013
|
if (bridgeStarted) {
|
|
9851
|
-
|
|
10014
|
+
log2("already started, skipping");
|
|
9852
10015
|
return;
|
|
9853
10016
|
}
|
|
9854
10017
|
void detectAndStart();
|
|
@@ -9860,7 +10023,7 @@ async function detectAndStart() {
|
|
|
9860
10023
|
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
9861
10024
|
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
9862
10025
|
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
9863
|
-
|
|
10026
|
+
log2("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
9864
10027
|
return;
|
|
9865
10028
|
}
|
|
9866
10029
|
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
@@ -9868,16 +10031,16 @@ async function detectAndStart() {
|
|
|
9868
10031
|
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
9869
10032
|
}
|
|
9870
10033
|
} catch {
|
|
9871
|
-
|
|
10034
|
+
log2("expo-superwall not installed \u2014 bridge inactive");
|
|
9872
10035
|
return;
|
|
9873
10036
|
}
|
|
9874
10037
|
try {
|
|
9875
10038
|
const callbacks = buildCallbacks();
|
|
9876
10039
|
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
9877
10040
|
bridgeStarted = true;
|
|
9878
|
-
|
|
10041
|
+
log2("bridge started");
|
|
9879
10042
|
} catch (err) {
|
|
9880
|
-
|
|
10043
|
+
log2("subscribe failed", { err: String(err) });
|
|
9881
10044
|
}
|
|
9882
10045
|
}
|
|
9883
10046
|
|
|
@@ -10450,6 +10613,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10450
10613
|
if (!mounted) return;
|
|
10451
10614
|
setDistinctId(PaywalloClient.getDistinctId());
|
|
10452
10615
|
startSuperwallAutoBridge(configRef.current.debug);
|
|
10616
|
+
void pushAttributionToSuperwall(configRef.current.debug);
|
|
10453
10617
|
setIsInitialized(true);
|
|
10454
10618
|
if (!autoPreloadTriggeredRef.current) {
|
|
10455
10619
|
autoPreloadTriggeredRef.current = true;
|