@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 CHANGED
@@ -428,11 +428,28 @@ function parseProperties(json) {
428
428
  return {};
429
429
  }
430
430
  }
431
- var DEVICE_ID_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;
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.set(ANON_ID_KEY, this.anonId).catch(() => {
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 loadPersistedIdentity(this.secureStorage);
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 (state.anonId) {
694
+ if (rawAnonId) {
672
695
  const legacyPrefix = "$paywallo_anon:";
673
- if (state.anonId.startsWith(legacyPrefix)) {
674
- const stripped = state.anonId.slice(legacyPrefix.length);
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 = state.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
- this.cached = { ...fallback, idfv: idfv2 };
905
- return this.cached;
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 result = await tracking.requestTrackingPermissionsAsync();
912
- status = result.status;
913
- granted = result.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
- this.cached = { idfv, idfa, gaid: null, attStatus: status };
918
- return this.cached;
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
- try {
935
- const info = await nativeDeviceInfo.getDeviceInfo();
936
- return this.sanitizeId(info.idfv);
937
- } catch {
938
- return null;
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.3.0") {
2390
- return "2.3.0";
2424
+ if ("2.4.1") {
2425
+ return "2.4.1";
2391
2426
  }
2392
2427
  } catch {
2393
2428
  }
@@ -4249,10 +4284,10 @@ var init_OfflineQueueStorage = __esm({
4249
4284
  init_NativeStorage();
4250
4285
  init_QueueJournal();
4251
4286
  OfflineQueueStorage = class {
4252
- constructor(config, emit, log2) {
4287
+ constructor(config, emit, log3) {
4253
4288
  this.config = config;
4254
4289
  this.emit = emit;
4255
- this.log = log2;
4290
+ this.log = log3;
4256
4291
  }
4257
4292
  async loadFromStorage(queue) {
4258
4293
  const { merged, recovered, hadJournal } = await mergeJournalIntoMain(
@@ -4501,11 +4536,11 @@ var init_OfflineQueue = __esm({
4501
4536
  });
4502
4537
  return true;
4503
4538
  }
4504
- const delay = Math.min(
4539
+ const delay2 = Math.min(
4505
4540
  this.config.baseRetryDelayMs * Math.pow(2, item.attempts - 1),
4506
4541
  this.config.maxRetryDelayMs
4507
4542
  );
4508
- item.nextRetryAt = Date.now() + delay;
4543
+ item.nextRetryAt = Date.now() + delay2;
4509
4544
  await this.storage.saveToStorage(this.queue);
4510
4545
  return false;
4511
4546
  }
@@ -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 delay = this.calculateDelayForResponse(state.attempt, response.headers, retryConfig);
7782
- await this.sleep(delay);
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 delay = this.calculateDelay(state.attempt, retryConfig);
7792
- await this.sleep(delay);
7826
+ const delay2 = this.calculateDelay(state.attempt, retryConfig);
7827
+ await this.sleep(delay2);
7793
7828
  continue;
7794
7829
  }
7795
7830
  throw state.lastError;
@@ -7937,7 +7972,36 @@ var init_http = __esm({
7937
7972
  });
7938
7973
 
7939
7974
  // src/core/ApiClient.ts
7940
- var import_react_native25, ApiClient;
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;
7941
8005
  var init_ApiClient = __esm({
7942
8006
  "src/core/ApiClient.ts"() {
7943
8007
  "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?.phone && { phone: pii.phone },
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
  );
@@ -8414,8 +8475,8 @@ async function initWithRetry(state, config) {
8414
8475
  } catch (error) {
8415
8476
  state.initAttempts++;
8416
8477
  if (state.initAttempts > MAX_INIT_RETRIES) throw error;
8417
- const delay = RETRY_DELAYS[state.initAttempts - 1] ?? 1e4;
8418
- await new Promise((resolve) => setTimeout(resolve, delay));
8478
+ const delay2 = RETRY_DELAYS[state.initAttempts - 1] ?? 1e4;
8479
+ await new Promise((resolve) => setTimeout(resolve, delay2));
8419
8480
  }
8420
8481
  }
8421
8482
  }
@@ -9769,6 +9830,108 @@ init_paywall();
9769
9830
  init_paywall();
9770
9831
  init_paywall();
9771
9832
 
9833
+ // src/domains/paywall/SuperwallAttributeBridge.ts
9834
+ init_identity();
9835
+ var CONFIG_POLL_INTERVAL_MS = 250;
9836
+ var CONFIG_POLL_MAX_ATTEMPTS = 40;
9837
+ var lastSignature = null;
9838
+ function log(debug, msg, data) {
9839
+ if (!debug) return;
9840
+ if (data !== void 0) console.log(`[Paywallo:SuperwallAttr] ${msg}`, data);
9841
+ else console.log(`[Paywallo:SuperwallAttr] ${msg}`);
9842
+ }
9843
+ function delay(ms) {
9844
+ return new Promise((resolve) => setTimeout(resolve, ms));
9845
+ }
9846
+ var PAID_MEDIUM = /cpc|ppc|cpm|cpa|paid|display/i;
9847
+ function deriveIsPaid(a) {
9848
+ if (a.fbclid || a.gclid || a.ttclid || a.tiktokCampaignId) return true;
9849
+ return Boolean(a.utmMedium && PAID_MEDIUM.test(a.utmMedium));
9850
+ }
9851
+ function deriveAdNetwork(a) {
9852
+ if (a.fbclid) return "meta";
9853
+ if (a.ttclid || a.tiktokCampaignId) return "tiktok";
9854
+ if (a.gclid) return "google";
9855
+ return a.utmSource;
9856
+ }
9857
+ function buildSuperwallAttributes(a) {
9858
+ const out = {};
9859
+ if (!a) {
9860
+ out.pw_is_paid = false;
9861
+ return out;
9862
+ }
9863
+ const set2 = (key, value) => {
9864
+ if (value) out[key] = value;
9865
+ };
9866
+ set2("pw_utm_source", a.utmSource);
9867
+ set2("pw_utm_medium", a.utmMedium);
9868
+ set2("pw_utm_campaign", a.utmCampaign);
9869
+ set2("pw_utm_content", a.utmContent);
9870
+ set2("pw_utm_term", a.utmTerm);
9871
+ set2("pw_fbclid", a.fbclid);
9872
+ set2("pw_gclid", a.gclid);
9873
+ set2("pw_ttclid", a.ttclid);
9874
+ set2("pw_tiktok_campaign_id", a.tiktokCampaignId);
9875
+ set2("pw_tiktok_adgroup_id", a.tiktokAdgroupId);
9876
+ set2("pw_tiktok_ad_id", a.tiktokAdId);
9877
+ set2("pw_referrer", a.referrer);
9878
+ set2("pw_install_referrer_source", a.installReferrerSource);
9879
+ set2("pw_ad_network", deriveAdNetwork(a));
9880
+ out.pw_is_paid = deriveIsPaid(a);
9881
+ out.pw_attributed_at = a.capturedAt;
9882
+ return out;
9883
+ }
9884
+ function pickNative(mod) {
9885
+ const native = mod?.SuperwallExpoModule ?? mod?.default?.SuperwallExpoModule;
9886
+ return native && typeof native.setUserAttributes === "function" && typeof native.getConfigurationStatus === "function" ? native : null;
9887
+ }
9888
+ async function resolveSuperwallNativeModule(debug) {
9889
+ try {
9890
+ const native = pickNative(await import("expo-superwall"));
9891
+ if (native) return native;
9892
+ } catch {
9893
+ }
9894
+ log(debug, "expo-superwall native module not available \u2014 attribute push skipped");
9895
+ return null;
9896
+ }
9897
+ async function waitForConfigured(mod, debug) {
9898
+ for (let attempt = 0; attempt < CONFIG_POLL_MAX_ATTEMPTS; attempt++) {
9899
+ let status;
9900
+ try {
9901
+ status = String(await mod.getConfigurationStatus());
9902
+ } catch (err) {
9903
+ log(debug, "getConfigurationStatus error", { err: String(err) });
9904
+ return false;
9905
+ }
9906
+ if (status === "CONFIGURED") return true;
9907
+ if (status === "FAILED") {
9908
+ log(debug, "Superwall configuration FAILED \u2014 skipping attribute push");
9909
+ return false;
9910
+ }
9911
+ await delay(CONFIG_POLL_INTERVAL_MS);
9912
+ }
9913
+ log(debug, "Superwall not configured within timeout \u2014 skipping attribute push");
9914
+ return false;
9915
+ }
9916
+ async function pushAttributionToSuperwall(debug = false) {
9917
+ const attrs = buildSuperwallAttributes(attributionTracker.get());
9918
+ const signature = JSON.stringify(attrs);
9919
+ if (signature === lastSignature) {
9920
+ log(debug, "attributes unchanged \u2014 skipping push");
9921
+ return;
9922
+ }
9923
+ const native = await resolveSuperwallNativeModule(debug);
9924
+ if (!native) return;
9925
+ if (!await waitForConfigured(native, debug)) return;
9926
+ try {
9927
+ await native.setUserAttributes(attrs);
9928
+ lastSignature = signature;
9929
+ log(debug, "attributes pushed to Superwall", attrs);
9930
+ } catch (err) {
9931
+ log(debug, "setUserAttributes error", { err: String(err) });
9932
+ }
9933
+ }
9934
+
9772
9935
  // src/domains/paywall/SuperwallAutoBridge.ts
9773
9936
  init_PaywalloClient();
9774
9937
 
@@ -9802,7 +9965,7 @@ function buildDeterministicEventId(parts) {
9802
9965
  var bridgeStarted = false;
9803
9966
  var unsubscribe = null;
9804
9967
  var debugEnabled = false;
9805
- function log(msg, data) {
9968
+ function log2(msg, data) {
9806
9969
  if (!debugEnabled) return;
9807
9970
  if (data !== void 0) {
9808
9971
  console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
@@ -9832,7 +9995,7 @@ async function trackPaywallEvent(type, identifier, ts, extra) {
9832
9995
  }
9833
9996
  });
9834
9997
  } catch (err) {
9835
- log("track error", { type, identifier, eventId: _eventId, err: String(err) });
9998
+ log2("track error", { type, identifier, eventId: _eventId, err: String(err) });
9836
9999
  }
9837
10000
  }
9838
10001
  function mapDismissToCloseReason(resultType) {
@@ -9852,7 +10015,7 @@ function buildCallbacks() {
9852
10015
  return {
9853
10016
  onPaywallPresent: (info) => {
9854
10017
  const ts = Date.now();
9855
- log("onPaywallPresent", { identifier: info.identifier });
10018
+ log2("onPaywallPresent", { identifier: info.identifier });
9856
10019
  void trackPaywallEvent("viewed", info.identifier, ts, {
9857
10020
  placement: info.presentedByEventWithName,
9858
10021
  variant_id: info.experiment?.variant?.id,
@@ -9861,7 +10024,7 @@ function buildCallbacks() {
9861
10024
  },
9862
10025
  onPaywallDismiss: (info, result) => {
9863
10026
  const ts = Date.now();
9864
- log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
10027
+ log2("onPaywallDismiss", { identifier: info.identifier, result: result.type });
9865
10028
  void trackPaywallEvent("closed", info.identifier, ts, {
9866
10029
  placement: info.presentedByEventWithName,
9867
10030
  variant_id: info.experiment?.variant?.id,
@@ -9875,7 +10038,7 @@ function buildCallbacks() {
9875
10038
  const safe = params !== null && typeof params === "object" ? params : {};
9876
10039
  const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
9877
10040
  const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
9878
- log("onPurchase", { productId, identifier });
10041
+ log2("onPurchase", { productId, identifier });
9879
10042
  void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
9880
10043
  },
9881
10044
  // Global Superwall event listener — used specifically for `transactionComplete`
@@ -9890,7 +10053,7 @@ function buildCallbacks() {
9890
10053
  const product = ev.product;
9891
10054
  const transaction = ev.transaction;
9892
10055
  if (!product) {
9893
- log("transactionComplete missing product \u2014 skipping transaction track");
10056
+ log2("transactionComplete missing product \u2014 skipping transaction track");
9894
10057
  return;
9895
10058
  }
9896
10059
  const productId = product.productIdentifier ?? product.id ?? "unknown";
@@ -9899,7 +10062,7 @@ function buildCallbacks() {
9899
10062
  const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
9900
10063
  const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
9901
10064
  const paywallIdentifier = ev.paywallInfo?.identifier;
9902
- log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
10065
+ log2("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
9903
10066
  void (async () => {
9904
10067
  try {
9905
10068
  await PaywalloClient.track("transaction", {
@@ -9917,7 +10080,7 @@ function buildCallbacks() {
9917
10080
  }
9918
10081
  });
9919
10082
  } catch (err) {
9920
- log("transactionComplete track error", { err: String(err) });
10083
+ log2("transactionComplete track error", { err: String(err) });
9921
10084
  }
9922
10085
  })();
9923
10086
  }
@@ -9926,7 +10089,7 @@ function buildCallbacks() {
9926
10089
  function startSuperwallAutoBridge(debug = false) {
9927
10090
  debugEnabled = debug;
9928
10091
  if (bridgeStarted) {
9929
- log("already started, skipping");
10092
+ log2("already started, skipping");
9930
10093
  return;
9931
10094
  }
9932
10095
  void detectAndStart();
@@ -9938,7 +10101,7 @@ async function detectAndStart() {
9938
10101
  if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
9939
10102
  const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
9940
10103
  if (typeof internal.subscribeToSuperwallEvents !== "function") {
9941
- log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
10104
+ log2("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
9942
10105
  return;
9943
10106
  }
9944
10107
  subscribeFn = internal.subscribeToSuperwallEvents;
@@ -9946,16 +10109,16 @@ async function detectAndStart() {
9946
10109
  subscribeFn = mod.subscribeToSuperwallEvents;
9947
10110
  }
9948
10111
  } catch {
9949
- log("expo-superwall not installed \u2014 bridge inactive");
10112
+ log2("expo-superwall not installed \u2014 bridge inactive");
9950
10113
  return;
9951
10114
  }
9952
10115
  try {
9953
10116
  const callbacks = buildCallbacks();
9954
10117
  unsubscribe = subscribeFn(void 0, () => callbacks);
9955
10118
  bridgeStarted = true;
9956
- log("bridge started");
10119
+ log2("bridge started");
9957
10120
  } catch (err) {
9958
- log("subscribe failed", { err: String(err) });
10121
+ log2("subscribe failed", { err: String(err) });
9959
10122
  }
9960
10123
  }
9961
10124
 
@@ -10528,6 +10691,7 @@ function PaywalloProvider({ children, config }) {
10528
10691
  if (!mounted) return;
10529
10692
  setDistinctId(PaywalloClient.getDistinctId());
10530
10693
  startSuperwallAutoBridge(configRef.current.debug);
10694
+ void pushAttributionToSuperwall(configRef.current.debug);
10531
10695
  setIsInitialized(true);
10532
10696
  if (!autoPreloadTriggeredRef.current) {
10533
10697
  autoPreloadTriggeredRef.current = true;