@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.mjs CHANGED
@@ -412,11 +412,28 @@ function parseProperties(json) {
412
412
  return {};
413
413
  }
414
414
  }
415
- 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;
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.set(ANON_ID_KEY, this.anonId).catch(() => {
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 loadPersistedIdentity(this.secureStorage);
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 (state.anonId) {
678
+ if (rawAnonId) {
656
679
  const legacyPrefix = "$paywallo_anon:";
657
- if (state.anonId.startsWith(legacyPrefix)) {
658
- const stripped = state.anonId.slice(legacyPrefix.length);
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 = state.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
- this.cached = { ...fallback, idfv: idfv2 };
889
- return this.cached;
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 result = await tracking.requestTrackingPermissionsAsync();
896
- status = result.status;
897
- granted = result.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
- this.cached = { idfv, idfa, gaid: null, attStatus: status };
902
- return this.cached;
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
- try {
919
- const info = await nativeDeviceInfo.getDeviceInfo();
920
- return this.sanitizeId(info.idfv);
921
- } catch {
922
- return null;
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.3.0") {
2374
- return "2.3.0";
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, log2) {
4282
+ constructor(config, emit, log3) {
4248
4283
  this.config = config;
4249
4284
  this.emit = emit;
4250
- this.log = log2;
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 delay = Math.min(
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() + delay;
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 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;
@@ -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
- var ApiClient;
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?.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
  );
@@ -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 delay = RETRY_DELAYS[state.initAttempts - 1] ?? 1e4;
8419
- await new Promise((resolve) => setTimeout(resolve, delay));
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 log(msg, data) {
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
- log("track error", { type, identifier, eventId: _eventId, err: String(err) });
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
- log("onPaywallPresent", { identifier: info.identifier });
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
- log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
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
- log("onPurchase", { productId, identifier });
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
- log("transactionComplete missing product \u2014 skipping transaction track");
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
- log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
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
- log("transactionComplete track error", { err: String(err) });
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
- log("already started, skipping");
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
- log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
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
- log("expo-superwall not installed \u2014 bridge inactive");
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
- log("bridge started");
10041
+ log2("bridge started");
9879
10042
  } catch (err) {
9880
- log("subscribe failed", { err: String(err) });
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;