@virex-tech/paywallo-sdk 2.2.7 → 2.4.0
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.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +210 -52
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +210 -52
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -166,6 +166,7 @@ interface PaywallConfig {
|
|
|
166
166
|
content?: string | Record<string, unknown>;
|
|
167
167
|
primaryProductId?: string;
|
|
168
168
|
secondaryProductId?: string;
|
|
169
|
+
tertiaryProductId?: string;
|
|
169
170
|
}
|
|
170
171
|
interface PaywallBlockConfig {
|
|
171
172
|
type: string;
|
|
@@ -1601,6 +1602,7 @@ interface PaywallContextValue {
|
|
|
1601
1602
|
selectedProductId: string | null;
|
|
1602
1603
|
primaryProductId: string | null;
|
|
1603
1604
|
secondaryProductId: string | null;
|
|
1605
|
+
tertiaryProductId: string | null;
|
|
1604
1606
|
currentNavigationIndex: number;
|
|
1605
1607
|
currentTabIndex: number;
|
|
1606
1608
|
trialEnabled: boolean;
|
|
@@ -1649,6 +1651,7 @@ interface PaywallModalProps {
|
|
|
1649
1651
|
config: Record<string, unknown>;
|
|
1650
1652
|
primaryProductId?: string;
|
|
1651
1653
|
secondaryProductId?: string;
|
|
1654
|
+
tertiaryProductId?: string;
|
|
1652
1655
|
};
|
|
1653
1656
|
preloadedProducts?: Map<string, Product>;
|
|
1654
1657
|
variantKey?: string;
|
|
@@ -1859,6 +1862,7 @@ interface VariableContext {
|
|
|
1859
1862
|
selectedProductId?: string;
|
|
1860
1863
|
primaryProductId?: string;
|
|
1861
1864
|
secondaryProductId?: string;
|
|
1865
|
+
tertiaryProductId?: string;
|
|
1862
1866
|
products: Map<string, Product>;
|
|
1863
1867
|
customVariables?: Record<string, string>;
|
|
1864
1868
|
deviceInfo?: {
|
package/dist/index.d.ts
CHANGED
|
@@ -166,6 +166,7 @@ interface PaywallConfig {
|
|
|
166
166
|
content?: string | Record<string, unknown>;
|
|
167
167
|
primaryProductId?: string;
|
|
168
168
|
secondaryProductId?: string;
|
|
169
|
+
tertiaryProductId?: string;
|
|
169
170
|
}
|
|
170
171
|
interface PaywallBlockConfig {
|
|
171
172
|
type: string;
|
|
@@ -1601,6 +1602,7 @@ interface PaywallContextValue {
|
|
|
1601
1602
|
selectedProductId: string | null;
|
|
1602
1603
|
primaryProductId: string | null;
|
|
1603
1604
|
secondaryProductId: string | null;
|
|
1605
|
+
tertiaryProductId: string | null;
|
|
1604
1606
|
currentNavigationIndex: number;
|
|
1605
1607
|
currentTabIndex: number;
|
|
1606
1608
|
trialEnabled: boolean;
|
|
@@ -1649,6 +1651,7 @@ interface PaywallModalProps {
|
|
|
1649
1651
|
config: Record<string, unknown>;
|
|
1650
1652
|
primaryProductId?: string;
|
|
1651
1653
|
secondaryProductId?: string;
|
|
1654
|
+
tertiaryProductId?: string;
|
|
1652
1655
|
};
|
|
1653
1656
|
preloadedProducts?: Map<string, Product>;
|
|
1654
1657
|
variantKey?: string;
|
|
@@ -1859,6 +1862,7 @@ interface VariableContext {
|
|
|
1859
1862
|
selectedProductId?: string;
|
|
1860
1863
|
primaryProductId?: string;
|
|
1861
1864
|
secondaryProductId?: string;
|
|
1865
|
+
tertiaryProductId?: string;
|
|
1862
1866
|
products: Map<string, Product>;
|
|
1863
1867
|
customVariables?: Record<string, string>;
|
|
1864
1868
|
deviceInfo?: {
|
package/dist/index.js
CHANGED
|
@@ -428,11 +428,28 @@ function parseProperties(json) {
|
|
|
428
428
|
return {};
|
|
429
429
|
}
|
|
430
430
|
}
|
|
431
|
-
|
|
431
|
+
async function persistAnonIdDurably(storage, anonId) {
|
|
432
|
+
let stored = await storage.set(ANON_ID_KEY, anonId);
|
|
433
|
+
for (let i = 0; i < ANON_ID_SET_RETRIES && !stored; i++) {
|
|
434
|
+
await new Promise((r) => setTimeout(r, ANON_ID_RETRY_DELAY_MS));
|
|
435
|
+
stored = await storage.set(ANON_ID_KEY, anonId);
|
|
436
|
+
}
|
|
437
|
+
if (!stored) {
|
|
438
|
+
await nativeStorage.set(ANON_ID_FALLBACK_KEY, anonId).catch(() => void 0);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
async function readAnonIdDurably(storage) {
|
|
442
|
+
const secure = await readWithMigration(storage, ANON_ID_KEY, LEGACY_ANON_ID_KEY);
|
|
443
|
+
if (secure) return secure;
|
|
444
|
+
return nativeStorage.get(ANON_ID_FALLBACK_KEY);
|
|
445
|
+
}
|
|
446
|
+
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;
|
|
432
447
|
var init_IdentityStorage = __esm({
|
|
433
448
|
"src/domains/identity/IdentityStorage.ts"() {
|
|
434
449
|
"use strict";
|
|
450
|
+
init_NativeStorage();
|
|
435
451
|
DEVICE_ID_KEY = "@paywallo:device_id";
|
|
452
|
+
ANON_ID_FALLBACK_KEY = "@paywallo:anon_id_fallback";
|
|
436
453
|
ANON_ID_KEY = "@paywallo:anon_id";
|
|
437
454
|
USER_EMAIL_KEY = "@paywallo:user_email";
|
|
438
455
|
USER_PROPERTIES_KEY = "@paywallo:user_properties";
|
|
@@ -458,6 +475,8 @@ var init_IdentityStorage = __esm({
|
|
|
458
475
|
LEGACY_NAME_KEY = "user_name";
|
|
459
476
|
LEGACY_COUNTRY_KEY = "user_country";
|
|
460
477
|
LEGACY_LOCALE_KEY = "user_locale";
|
|
478
|
+
ANON_ID_SET_RETRIES = 2;
|
|
479
|
+
ANON_ID_RETRY_DELAY_MS = 50;
|
|
461
480
|
}
|
|
462
481
|
});
|
|
463
482
|
|
|
@@ -537,8 +556,7 @@ var init_IdentityManager = __esm({
|
|
|
537
556
|
}
|
|
538
557
|
if (!this.anonId) {
|
|
539
558
|
this.anonId = generateUUID();
|
|
540
|
-
await this.secureStorage
|
|
541
|
-
});
|
|
559
|
+
await persistAnonIdDurably(this.secureStorage, this.anonId);
|
|
542
560
|
}
|
|
543
561
|
this.initialized = true;
|
|
544
562
|
return this.deviceId ?? "";
|
|
@@ -598,7 +616,8 @@ var init_IdentityManager = __esm({
|
|
|
598
616
|
dateOfBirth: this.dateOfBirth ?? void 0,
|
|
599
617
|
gender: this.gender ?? void 0
|
|
600
618
|
});
|
|
601
|
-
} catch {
|
|
619
|
+
} catch (err) {
|
|
620
|
+
if (this.debug) console.log("[Paywallo] identify dispatch error", err);
|
|
602
621
|
}
|
|
603
622
|
}
|
|
604
623
|
}
|
|
@@ -622,7 +641,8 @@ var init_IdentityManager = __esm({
|
|
|
622
641
|
if (this.apiClient && this.anonId) {
|
|
623
642
|
try {
|
|
624
643
|
await this.apiClient.identify(this.anonId, this.properties, this.email ?? void 0, this.deviceId ?? void 0);
|
|
625
|
-
} catch {
|
|
644
|
+
} catch (err) {
|
|
645
|
+
if (this.debug) console.log("[Paywallo] identify dispatch error", err);
|
|
626
646
|
}
|
|
627
647
|
}
|
|
628
648
|
}
|
|
@@ -665,18 +685,20 @@ var init_IdentityManager = __esm({
|
|
|
665
685
|
}
|
|
666
686
|
async loadPersistedState() {
|
|
667
687
|
if (!this.secureStorage) return;
|
|
668
|
-
const state = await
|
|
688
|
+
const [state, rawAnonId] = await Promise.all([
|
|
689
|
+
loadPersistedIdentity(this.secureStorage),
|
|
690
|
+
readAnonIdDurably(this.secureStorage)
|
|
691
|
+
]);
|
|
669
692
|
const deviceId = state.deviceId ?? await readDeviceIdWithFallback(this.secureStorage);
|
|
670
693
|
if (deviceId) this.deviceId = deviceId;
|
|
671
|
-
if (
|
|
694
|
+
if (rawAnonId) {
|
|
672
695
|
const legacyPrefix = "$paywallo_anon:";
|
|
673
|
-
if (
|
|
674
|
-
const stripped =
|
|
696
|
+
if (rawAnonId.startsWith(legacyPrefix)) {
|
|
697
|
+
const stripped = rawAnonId.slice(legacyPrefix.length);
|
|
675
698
|
this.anonId = stripped;
|
|
676
|
-
await this.secureStorage.set(ANON_ID_KEY, stripped).catch(() =>
|
|
677
|
-
});
|
|
699
|
+
await this.secureStorage.set(ANON_ID_KEY, stripped).catch(() => void 0);
|
|
678
700
|
} else {
|
|
679
|
-
this.anonId =
|
|
701
|
+
this.anonId = rawAnonId;
|
|
680
702
|
}
|
|
681
703
|
}
|
|
682
704
|
if (state.email) this.email = state.email;
|
|
@@ -901,21 +923,23 @@ var init_AdvertisingIdManager = __esm({
|
|
|
901
923
|
if (import_react_native3.Platform.OS === "ios") {
|
|
902
924
|
if (!tracking.isAvailable()) {
|
|
903
925
|
const idfv2 = await this.collectIdfv();
|
|
904
|
-
|
|
905
|
-
|
|
926
|
+
const result2 = { ...fallback, idfv: idfv2 };
|
|
927
|
+
if (idfv2 !== null) this.cached = result2;
|
|
928
|
+
return result2;
|
|
906
929
|
}
|
|
907
930
|
const current = await tracking.getTrackingPermissionsAsync();
|
|
908
931
|
let status = current.status;
|
|
909
932
|
let granted = current.granted;
|
|
910
933
|
if (status === "undetermined" && requestATT) {
|
|
911
|
-
const
|
|
912
|
-
status =
|
|
913
|
-
granted =
|
|
934
|
+
const result2 = await tracking.requestTrackingPermissionsAsync();
|
|
935
|
+
status = result2.status;
|
|
936
|
+
granted = result2.granted;
|
|
914
937
|
}
|
|
915
938
|
const idfv = await this.collectIdfv();
|
|
916
939
|
const idfa = granted ? this.sanitizeId(tracking.getAdvertisingId()) : null;
|
|
917
|
-
|
|
918
|
-
|
|
940
|
+
const result = { idfv, idfa, gaid: null, attStatus: status };
|
|
941
|
+
if (idfv !== null) this.cached = result;
|
|
942
|
+
return result;
|
|
919
943
|
}
|
|
920
944
|
if (import_react_native3.Platform.OS === "android") {
|
|
921
945
|
const rawGaid = tracking.getAdvertisingId();
|
|
@@ -931,12 +955,20 @@ var init_AdvertisingIdManager = __esm({
|
|
|
931
955
|
}
|
|
932
956
|
}
|
|
933
957
|
async collectIdfv() {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
958
|
+
const RETRY_DELAY_MS = 80;
|
|
959
|
+
const MAX_ATTEMPTS = 3;
|
|
960
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
961
|
+
try {
|
|
962
|
+
const info = await nativeDeviceInfo.getDeviceInfo();
|
|
963
|
+
const idfv = this.sanitizeId(info.idfv);
|
|
964
|
+
if (idfv !== null) return idfv;
|
|
965
|
+
} catch {
|
|
966
|
+
}
|
|
967
|
+
if (attempt < MAX_ATTEMPTS - 1) {
|
|
968
|
+
await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));
|
|
969
|
+
}
|
|
939
970
|
}
|
|
971
|
+
return null;
|
|
940
972
|
}
|
|
941
973
|
sanitizeId(id) {
|
|
942
974
|
if (!id || id === ZERO_IDFA) return null;
|
|
@@ -1374,6 +1406,8 @@ var init_AttributionTracker = __esm({
|
|
|
1374
1406
|
|
|
1375
1407
|
// src/domains/identity/InstallIdempotency.ts
|
|
1376
1408
|
async function checkAndArmInstallGuard(storage) {
|
|
1409
|
+
if (armedThisLaunch) return true;
|
|
1410
|
+
armedThisLaunch = true;
|
|
1377
1411
|
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
1378
1412
|
if (alreadyTracked) return true;
|
|
1379
1413
|
let fallbackTracked = null;
|
|
@@ -1407,7 +1441,7 @@ async function getOrCreateInstallEventId() {
|
|
|
1407
1441
|
});
|
|
1408
1442
|
return id;
|
|
1409
1443
|
}
|
|
1410
|
-
var INSTALL_KEYS;
|
|
1444
|
+
var INSTALL_KEYS, armedThisLaunch;
|
|
1411
1445
|
var init_InstallIdempotency = __esm({
|
|
1412
1446
|
"src/domains/identity/InstallIdempotency.ts"() {
|
|
1413
1447
|
"use strict";
|
|
@@ -1432,6 +1466,7 @@ var init_InstallIdempotency = __esm({
|
|
|
1432
1466
|
/** Legacy anon ID key written by SDK versions that used @panel: prefix. */
|
|
1433
1467
|
LEGACY_ANON_ID: "@panel:anon_id"
|
|
1434
1468
|
};
|
|
1469
|
+
armedThisLaunch = false;
|
|
1435
1470
|
}
|
|
1436
1471
|
});
|
|
1437
1472
|
|
|
@@ -2386,8 +2421,8 @@ var init_NotificationHandlerSetup = __esm({
|
|
|
2386
2421
|
// src/core/version.ts
|
|
2387
2422
|
function resolveVersion() {
|
|
2388
2423
|
try {
|
|
2389
|
-
if ("2.
|
|
2390
|
-
return "2.
|
|
2424
|
+
if ("2.4.0") {
|
|
2425
|
+
return "2.4.0";
|
|
2391
2426
|
}
|
|
2392
2427
|
} catch {
|
|
2393
2428
|
}
|
|
@@ -3403,6 +3438,7 @@ function buildPaywallInjectionScript(data) {
|
|
|
3403
3438
|
products: data.products,
|
|
3404
3439
|
primaryProductId: data.primaryProductId,
|
|
3405
3440
|
secondaryProductId: data.secondaryProductId,
|
|
3441
|
+
tertiaryProductId: data.tertiaryProductId,
|
|
3406
3442
|
currentLanguage: getCurrentLanguage(),
|
|
3407
3443
|
defaultLanguage: getDefaultLanguage()
|
|
3408
3444
|
}
|
|
@@ -3487,6 +3523,7 @@ function PaywallWebView({
|
|
|
3487
3523
|
products,
|
|
3488
3524
|
primaryProductId,
|
|
3489
3525
|
secondaryProductId,
|
|
3526
|
+
tertiaryProductId,
|
|
3490
3527
|
isPurchasing,
|
|
3491
3528
|
webUrl: webUrlProp,
|
|
3492
3529
|
onPurchase,
|
|
@@ -3558,10 +3595,11 @@ function PaywallWebView({
|
|
|
3558
3595
|
craftData,
|
|
3559
3596
|
products: Array.from(products.values()),
|
|
3560
3597
|
primaryProductId,
|
|
3561
|
-
secondaryProductId
|
|
3598
|
+
secondaryProductId,
|
|
3599
|
+
tertiaryProductId
|
|
3562
3600
|
});
|
|
3563
3601
|
injectScript(script);
|
|
3564
|
-
}, [craftData, products, primaryProductId, secondaryProductId, injectScript]);
|
|
3602
|
+
}, [craftData, products, primaryProductId, secondaryProductId, tertiaryProductId, injectScript]);
|
|
3565
3603
|
const processedIdsRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
|
|
3566
3604
|
const dedupeTimersRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
|
|
3567
3605
|
(0, import_react4.useEffect)(() => {
|
|
@@ -4246,10 +4284,10 @@ var init_OfflineQueueStorage = __esm({
|
|
|
4246
4284
|
init_NativeStorage();
|
|
4247
4285
|
init_QueueJournal();
|
|
4248
4286
|
OfflineQueueStorage = class {
|
|
4249
|
-
constructor(config, emit,
|
|
4287
|
+
constructor(config, emit, log3) {
|
|
4250
4288
|
this.config = config;
|
|
4251
4289
|
this.emit = emit;
|
|
4252
|
-
this.log =
|
|
4290
|
+
this.log = log3;
|
|
4253
4291
|
}
|
|
4254
4292
|
async loadFromStorage(queue) {
|
|
4255
4293
|
const { merged, recovered, hadJournal } = await mergeJournalIntoMain(
|
|
@@ -5507,7 +5545,8 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
5507
5545
|
placement: snap.placement,
|
|
5508
5546
|
config: snap.config,
|
|
5509
5547
|
primaryProductId: snap.primaryProductId,
|
|
5510
|
-
secondaryProductId: snap.secondaryProductId
|
|
5548
|
+
secondaryProductId: snap.secondaryProductId,
|
|
5549
|
+
tertiaryProductId: snap.tertiaryProductId
|
|
5511
5550
|
};
|
|
5512
5551
|
} else {
|
|
5513
5552
|
const fetched = await apiClient.getPaywall(placement);
|
|
@@ -5519,6 +5558,7 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
5519
5558
|
const productIds = [];
|
|
5520
5559
|
if (config.primaryProductId) productIds.push(config.primaryProductId);
|
|
5521
5560
|
if (config.secondaryProductId) productIds.push(config.secondaryProductId);
|
|
5561
|
+
if (config.tertiaryProductId) productIds.push(config.tertiaryProductId);
|
|
5522
5562
|
const snapProducts = preloadedProductsRef.current;
|
|
5523
5563
|
if (snapProducts && snapProducts.size > 0) {
|
|
5524
5564
|
if (!cancelled) setProducts(snapProducts);
|
|
@@ -5702,6 +5742,7 @@ function PaywallModal({
|
|
|
5702
5742
|
products,
|
|
5703
5743
|
primaryProductId: paywallConfig.primaryProductId,
|
|
5704
5744
|
secondaryProductId: paywallConfig.secondaryProductId,
|
|
5745
|
+
tertiaryProductId: paywallConfig.tertiaryProductId,
|
|
5705
5746
|
isPurchasing,
|
|
5706
5747
|
onReady: handleWebViewReady,
|
|
5707
5748
|
onClose: handleClose,
|
|
@@ -5883,6 +5924,7 @@ var init_PaywallPreloadService = __esm({
|
|
|
5883
5924
|
const productIds = [];
|
|
5884
5925
|
if (config.primaryProductId) productIds.push(config.primaryProductId);
|
|
5885
5926
|
if (config.secondaryProductId) productIds.push(config.secondaryProductId);
|
|
5927
|
+
if (config.tertiaryProductId) productIds.push(config.tertiaryProductId);
|
|
5886
5928
|
if (productIds.length === 0) return /* @__PURE__ */ new Map();
|
|
5887
5929
|
try {
|
|
5888
5930
|
const loaded = await getIAPService().loadProducts(productIds);
|
|
@@ -7930,7 +7972,36 @@ var init_http = __esm({
|
|
|
7930
7972
|
});
|
|
7931
7973
|
|
|
7932
7974
|
// src/core/ApiClient.ts
|
|
7933
|
-
|
|
7975
|
+
function normalizeDateOfBirth(raw) {
|
|
7976
|
+
if (!raw) return void 0;
|
|
7977
|
+
if (DATE_OF_BIRTH_RE.test(raw)) return raw;
|
|
7978
|
+
const d = new Date(raw);
|
|
7979
|
+
if (isNaN(d.getTime())) return void 0;
|
|
7980
|
+
const hasTimeComponent = raw.includes("T") || raw.includes("Z");
|
|
7981
|
+
const yyyy = hasTimeComponent ? d.getUTCFullYear() : d.getFullYear();
|
|
7982
|
+
const mm = String((hasTimeComponent ? d.getUTCMonth() : d.getMonth()) + 1).padStart(2, "0");
|
|
7983
|
+
const dd = String(hasTimeComponent ? d.getUTCDate() : d.getDate()).padStart(2, "0");
|
|
7984
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
7985
|
+
}
|
|
7986
|
+
function buildPiiPayload(pii) {
|
|
7987
|
+
const result = {};
|
|
7988
|
+
if (pii.phone) result.phone = pii.phone;
|
|
7989
|
+
if (pii.firstName) result.firstName = pii.firstName;
|
|
7990
|
+
if (pii.lastName) result.lastName = pii.lastName;
|
|
7991
|
+
const dob = normalizeDateOfBirth(pii.dateOfBirth);
|
|
7992
|
+
if (dob) result.dateOfBirth = dob;
|
|
7993
|
+
const g = normalizeGender(pii.gender);
|
|
7994
|
+
if (g) result.gender = g;
|
|
7995
|
+
return result;
|
|
7996
|
+
}
|
|
7997
|
+
function normalizeGender(raw) {
|
|
7998
|
+
if (!raw) return void 0;
|
|
7999
|
+
const lower = raw.toLowerCase();
|
|
8000
|
+
if (lower === "m" || lower === "male") return "m";
|
|
8001
|
+
if (lower === "f" || lower === "female") return "f";
|
|
8002
|
+
return void 0;
|
|
8003
|
+
}
|
|
8004
|
+
var import_react_native25, DATE_OF_BIRTH_RE, ApiClient;
|
|
7934
8005
|
var init_ApiClient = __esm({
|
|
7935
8006
|
"src/core/ApiClient.ts"() {
|
|
7936
8007
|
"use strict";
|
|
@@ -7944,6 +8015,7 @@ var init_ApiClient = __esm({
|
|
|
7944
8015
|
init_http();
|
|
7945
8016
|
init_queue();
|
|
7946
8017
|
init_version();
|
|
8018
|
+
DATE_OF_BIRTH_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
7947
8019
|
ApiClient = class {
|
|
7948
8020
|
constructor(appKey, apiUrl, debug = false, environment = "Production", offlineQueueEnabled = true, timeout = 3e4) {
|
|
7949
8021
|
this.cache = new ApiCache();
|
|
@@ -8102,6 +8174,8 @@ var init_ApiClient = __esm({
|
|
|
8102
8174
|
}
|
|
8103
8175
|
}
|
|
8104
8176
|
const attribution = Object.keys(rawAttribution).length > 0 ? rawAttribution : void 0;
|
|
8177
|
+
const rawUserId = properties?.["userId"];
|
|
8178
|
+
const externalUserId = typeof rawUserId === "string" && rawUserId.length > 0 ? rawUserId : void 0;
|
|
8105
8179
|
await postWithQueue(
|
|
8106
8180
|
{
|
|
8107
8181
|
isOfflineQueueEnabled: () => this.offlineQueueEnabled,
|
|
@@ -8112,14 +8186,11 @@ var init_ApiClient = __esm({
|
|
|
8112
8186
|
"/sdk/identity/identify",
|
|
8113
8187
|
{
|
|
8114
8188
|
distinct_id: distinctId,
|
|
8189
|
+
...externalUserId && { external_user_id: externalUserId },
|
|
8115
8190
|
traits,
|
|
8116
8191
|
...attribution && { attribution },
|
|
8117
8192
|
...deviceId && { deviceId },
|
|
8118
|
-
...pii
|
|
8119
|
-
...pii?.firstName && { firstName: pii.firstName },
|
|
8120
|
-
...pii?.lastName && { lastName: pii.lastName },
|
|
8121
|
-
...pii?.dateOfBirth && { dateOfBirth: pii.dateOfBirth },
|
|
8122
|
-
...pii?.gender && { gender: pii.gender }
|
|
8193
|
+
...pii ? buildPiiPayload(pii) : {}
|
|
8123
8194
|
},
|
|
8124
8195
|
"identify"
|
|
8125
8196
|
);
|
|
@@ -9759,6 +9830,88 @@ init_paywall();
|
|
|
9759
9830
|
init_paywall();
|
|
9760
9831
|
init_paywall();
|
|
9761
9832
|
|
|
9833
|
+
// src/domains/paywall/SuperwallAttributeBridge.ts
|
|
9834
|
+
init_identity();
|
|
9835
|
+
var lastSignature = null;
|
|
9836
|
+
function log(debug, msg, data) {
|
|
9837
|
+
if (!debug) return;
|
|
9838
|
+
if (data !== void 0) console.log(`[Paywallo:SuperwallAttr] ${msg}`, data);
|
|
9839
|
+
else console.log(`[Paywallo:SuperwallAttr] ${msg}`);
|
|
9840
|
+
}
|
|
9841
|
+
var PAID_MEDIUM = /cpc|ppc|cpm|cpa|paid|display/i;
|
|
9842
|
+
function deriveIsPaid(a) {
|
|
9843
|
+
if (a.fbclid || a.gclid || a.ttclid || a.tiktokCampaignId) return true;
|
|
9844
|
+
return Boolean(a.utmMedium && PAID_MEDIUM.test(a.utmMedium));
|
|
9845
|
+
}
|
|
9846
|
+
function deriveAdNetwork(a) {
|
|
9847
|
+
if (a.fbclid) return "meta";
|
|
9848
|
+
if (a.ttclid || a.tiktokCampaignId) return "tiktok";
|
|
9849
|
+
if (a.gclid) return "google";
|
|
9850
|
+
return a.utmSource;
|
|
9851
|
+
}
|
|
9852
|
+
function buildSuperwallAttributes(a) {
|
|
9853
|
+
const out = {};
|
|
9854
|
+
if (!a) {
|
|
9855
|
+
out.pw_is_paid = false;
|
|
9856
|
+
return out;
|
|
9857
|
+
}
|
|
9858
|
+
const set2 = (key, value) => {
|
|
9859
|
+
if (value) out[key] = value;
|
|
9860
|
+
};
|
|
9861
|
+
set2("pw_utm_source", a.utmSource);
|
|
9862
|
+
set2("pw_utm_medium", a.utmMedium);
|
|
9863
|
+
set2("pw_utm_campaign", a.utmCampaign);
|
|
9864
|
+
set2("pw_utm_content", a.utmContent);
|
|
9865
|
+
set2("pw_utm_term", a.utmTerm);
|
|
9866
|
+
set2("pw_fbclid", a.fbclid);
|
|
9867
|
+
set2("pw_gclid", a.gclid);
|
|
9868
|
+
set2("pw_ttclid", a.ttclid);
|
|
9869
|
+
set2("pw_tiktok_campaign_id", a.tiktokCampaignId);
|
|
9870
|
+
set2("pw_tiktok_adgroup_id", a.tiktokAdgroupId);
|
|
9871
|
+
set2("pw_tiktok_ad_id", a.tiktokAdId);
|
|
9872
|
+
set2("pw_referrer", a.referrer);
|
|
9873
|
+
set2("pw_install_referrer_source", a.installReferrerSource);
|
|
9874
|
+
set2("pw_ad_network", deriveAdNetwork(a));
|
|
9875
|
+
out.pw_is_paid = deriveIsPaid(a);
|
|
9876
|
+
out.pw_attributed_at = a.capturedAt;
|
|
9877
|
+
return out;
|
|
9878
|
+
}
|
|
9879
|
+
function pickShared(mod) {
|
|
9880
|
+
const shared = mod?.default?.shared ?? mod?.shared;
|
|
9881
|
+
return shared && typeof shared.setUserAttributes === "function" ? shared : null;
|
|
9882
|
+
}
|
|
9883
|
+
async function resolveSuperwallShared(debug) {
|
|
9884
|
+
try {
|
|
9885
|
+
const shared = pickShared(await import("expo-superwall/compat"));
|
|
9886
|
+
if (shared) return shared;
|
|
9887
|
+
} catch {
|
|
9888
|
+
}
|
|
9889
|
+
try {
|
|
9890
|
+
const shared = pickShared(await import("expo-superwall"));
|
|
9891
|
+
if (shared) return shared;
|
|
9892
|
+
} catch {
|
|
9893
|
+
}
|
|
9894
|
+
log(debug, "expo-superwall not available \u2014 attribute push skipped");
|
|
9895
|
+
return null;
|
|
9896
|
+
}
|
|
9897
|
+
async function pushAttributionToSuperwall(debug = false) {
|
|
9898
|
+
const attrs = buildSuperwallAttributes(attributionTracker.get());
|
|
9899
|
+
const signature = JSON.stringify(attrs);
|
|
9900
|
+
if (signature === lastSignature) {
|
|
9901
|
+
log(debug, "attributes unchanged \u2014 skipping push");
|
|
9902
|
+
return;
|
|
9903
|
+
}
|
|
9904
|
+
const shared = await resolveSuperwallShared(debug);
|
|
9905
|
+
if (!shared) return;
|
|
9906
|
+
try {
|
|
9907
|
+
await shared.setUserAttributes(attrs);
|
|
9908
|
+
lastSignature = signature;
|
|
9909
|
+
log(debug, "attributes pushed to Superwall", attrs);
|
|
9910
|
+
} catch (err) {
|
|
9911
|
+
log(debug, "setUserAttributes error", { err: String(err) });
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9914
|
+
|
|
9762
9915
|
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9763
9916
|
init_PaywalloClient();
|
|
9764
9917
|
|
|
@@ -9792,7 +9945,7 @@ function buildDeterministicEventId(parts) {
|
|
|
9792
9945
|
var bridgeStarted = false;
|
|
9793
9946
|
var unsubscribe = null;
|
|
9794
9947
|
var debugEnabled = false;
|
|
9795
|
-
function
|
|
9948
|
+
function log2(msg, data) {
|
|
9796
9949
|
if (!debugEnabled) return;
|
|
9797
9950
|
if (data !== void 0) {
|
|
9798
9951
|
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
@@ -9822,7 +9975,7 @@ async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
|
9822
9975
|
}
|
|
9823
9976
|
});
|
|
9824
9977
|
} catch (err) {
|
|
9825
|
-
|
|
9978
|
+
log2("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
9826
9979
|
}
|
|
9827
9980
|
}
|
|
9828
9981
|
function mapDismissToCloseReason(resultType) {
|
|
@@ -9842,7 +9995,7 @@ function buildCallbacks() {
|
|
|
9842
9995
|
return {
|
|
9843
9996
|
onPaywallPresent: (info) => {
|
|
9844
9997
|
const ts = Date.now();
|
|
9845
|
-
|
|
9998
|
+
log2("onPaywallPresent", { identifier: info.identifier });
|
|
9846
9999
|
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
9847
10000
|
placement: info.presentedByEventWithName,
|
|
9848
10001
|
variant_id: info.experiment?.variant?.id,
|
|
@@ -9851,7 +10004,7 @@ function buildCallbacks() {
|
|
|
9851
10004
|
},
|
|
9852
10005
|
onPaywallDismiss: (info, result) => {
|
|
9853
10006
|
const ts = Date.now();
|
|
9854
|
-
|
|
10007
|
+
log2("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
9855
10008
|
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
9856
10009
|
placement: info.presentedByEventWithName,
|
|
9857
10010
|
variant_id: info.experiment?.variant?.id,
|
|
@@ -9865,7 +10018,7 @@ function buildCallbacks() {
|
|
|
9865
10018
|
const safe = params !== null && typeof params === "object" ? params : {};
|
|
9866
10019
|
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
9867
10020
|
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
9868
|
-
|
|
10021
|
+
log2("onPurchase", { productId, identifier });
|
|
9869
10022
|
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
9870
10023
|
},
|
|
9871
10024
|
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
@@ -9880,7 +10033,7 @@ function buildCallbacks() {
|
|
|
9880
10033
|
const product = ev.product;
|
|
9881
10034
|
const transaction = ev.transaction;
|
|
9882
10035
|
if (!product) {
|
|
9883
|
-
|
|
10036
|
+
log2("transactionComplete missing product \u2014 skipping transaction track");
|
|
9884
10037
|
return;
|
|
9885
10038
|
}
|
|
9886
10039
|
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
@@ -9889,7 +10042,7 @@ function buildCallbacks() {
|
|
|
9889
10042
|
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
9890
10043
|
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
9891
10044
|
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
9892
|
-
|
|
10045
|
+
log2("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
9893
10046
|
void (async () => {
|
|
9894
10047
|
try {
|
|
9895
10048
|
await PaywalloClient.track("transaction", {
|
|
@@ -9907,7 +10060,7 @@ function buildCallbacks() {
|
|
|
9907
10060
|
}
|
|
9908
10061
|
});
|
|
9909
10062
|
} catch (err) {
|
|
9910
|
-
|
|
10063
|
+
log2("transactionComplete track error", { err: String(err) });
|
|
9911
10064
|
}
|
|
9912
10065
|
})();
|
|
9913
10066
|
}
|
|
@@ -9916,7 +10069,7 @@ function buildCallbacks() {
|
|
|
9916
10069
|
function startSuperwallAutoBridge(debug = false) {
|
|
9917
10070
|
debugEnabled = debug;
|
|
9918
10071
|
if (bridgeStarted) {
|
|
9919
|
-
|
|
10072
|
+
log2("already started, skipping");
|
|
9920
10073
|
return;
|
|
9921
10074
|
}
|
|
9922
10075
|
void detectAndStart();
|
|
@@ -9928,7 +10081,7 @@ async function detectAndStart() {
|
|
|
9928
10081
|
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
9929
10082
|
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
9930
10083
|
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
9931
|
-
|
|
10084
|
+
log2("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
9932
10085
|
return;
|
|
9933
10086
|
}
|
|
9934
10087
|
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
@@ -9936,16 +10089,16 @@ async function detectAndStart() {
|
|
|
9936
10089
|
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
9937
10090
|
}
|
|
9938
10091
|
} catch {
|
|
9939
|
-
|
|
10092
|
+
log2("expo-superwall not installed \u2014 bridge inactive");
|
|
9940
10093
|
return;
|
|
9941
10094
|
}
|
|
9942
10095
|
try {
|
|
9943
10096
|
const callbacks = buildCallbacks();
|
|
9944
10097
|
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
9945
10098
|
bridgeStarted = true;
|
|
9946
|
-
|
|
10099
|
+
log2("bridge started");
|
|
9947
10100
|
} catch (err) {
|
|
9948
|
-
|
|
10101
|
+
log2("subscribe failed", { err: String(err) });
|
|
9949
10102
|
}
|
|
9950
10103
|
}
|
|
9951
10104
|
|
|
@@ -10518,6 +10671,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10518
10671
|
if (!mounted) return;
|
|
10519
10672
|
setDistinctId(PaywalloClient.getDistinctId());
|
|
10520
10673
|
startSuperwallAutoBridge(configRef.current.debug);
|
|
10674
|
+
void pushAttributionToSuperwall(configRef.current.debug);
|
|
10521
10675
|
setIsInitialized(true);
|
|
10522
10676
|
if (!autoPreloadTriggeredRef.current) {
|
|
10523
10677
|
autoPreloadTriggeredRef.current = true;
|
|
@@ -10553,7 +10707,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
10553
10707
|
placement: preloaded.config.placement,
|
|
10554
10708
|
config: preloaded.config.config,
|
|
10555
10709
|
primaryProductId: preloaded.config.primaryProductId,
|
|
10556
|
-
secondaryProductId: preloaded.config.secondaryProductId
|
|
10710
|
+
secondaryProductId: preloaded.config.secondaryProductId,
|
|
10711
|
+
tertiaryProductId: preloaded.config.tertiaryProductId
|
|
10557
10712
|
},
|
|
10558
10713
|
preloadedProducts: preloaded.products
|
|
10559
10714
|
}
|
|
@@ -10855,6 +11010,9 @@ function resolveProductsVariable(parts, context) {
|
|
|
10855
11010
|
if (parts[1] === "secondary" && context.secondaryProductId) {
|
|
10856
11011
|
return getProductVariable(context.products.get(context.secondaryProductId), parts[2]);
|
|
10857
11012
|
}
|
|
11013
|
+
if (parts[1] === "tertiary" && context.tertiaryProductId) {
|
|
11014
|
+
return getProductVariable(context.products.get(context.tertiaryProductId), parts[2]);
|
|
11015
|
+
}
|
|
10858
11016
|
if (parts[1] === "hasIntroductoryOffer") {
|
|
10859
11017
|
return Array.from(context.products.values()).some((p) => p.introductoryPrice) ? "true" : "false";
|
|
10860
11018
|
}
|