@datalyr/react-native 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,14 @@ Mobile analytics and attribution SDK for React Native and Expo. Track events, id
23
23
  - [Auto Events](#auto-events)
24
24
  - [SKAdNetwork](#skadnetwork)
25
25
  - [Platform Integrations](#platform-integrations)
26
+ - [Meta (Facebook)](#meta-facebook)
27
+ - [TikTok](#tiktok)
28
+ - [Google Ads](#google-ads)
26
29
  - [Apple Search Ads](#apple-search-ads)
30
+ - [Third-Party Integrations](#third-party-integrations)
31
+ - [Superwall](#superwall)
32
+ - [RevenueCat](#revenuecat)
33
+ - [Migrating from AppsFlyer / Adjust](#migrating-from-appsflyer--adjust)
27
34
  - [Expo Support](#expo-support)
28
35
  - [TypeScript](#typescript)
29
36
  - [Troubleshooting](#troubleshooting)
@@ -414,7 +421,52 @@ await Datalyr.trackPurchase(99.99, 'USD');
414
421
 
415
422
  ## Platform Integrations
416
423
 
417
- Conversion event routing to Meta, TikTok, and Google is handled server-side via the postback system. No client-side SDK configuration is needed for these platforms.
424
+ Conversion events are routed to ad platforms server-side via the Datalyr postback system. No client-side ad SDKs (Facebook SDK, TikTok SDK, etc.) are needed in your app. The SDK captures click IDs and attribution data from ad URLs, then the backend handles hashing, formatting, and sending conversions to each platform's API.
425
+
426
+ ### Meta (Facebook)
427
+
428
+ Conversions are sent to Meta via the [Conversions API (CAPI)](https://developers.facebook.com/docs/marketing-api/conversions-api/).
429
+
430
+ **What the SDK does:** Captures `fbclid` from ad click URLs, collects IDFA (when ATT authorized on iOS), and sends user data (email, phone) with events.
431
+
432
+ **What the backend does:** Hashes PII (SHA-256), formats the CAPI payload, and sends conversions with the `fbclid` and `_fbc`/`_fbp` cookies for matching.
433
+
434
+ **Setup:**
435
+ 1. Connect your Meta ad account in the Datalyr dashboard (Settings > Connections)
436
+ 2. Select your Meta Pixel
437
+ 3. Create postback rules to map events (e.g., `purchase` → `Purchase`, `lead` → `Lead`)
438
+
439
+ No Facebook SDK needed in your app. No `Info.plist` changes, no `FacebookAppID`.
440
+
441
+ ### TikTok
442
+
443
+ Conversions are sent to TikTok via the [Events API](https://business-api.tiktok.com/portal/docs?id=1741601162187777).
444
+
445
+ **What the SDK does:** Captures `ttclid` from ad click URLs and collects device identifiers (IDFA on iOS, GAID on Android).
446
+
447
+ **What the backend does:** Hashes user data, formats the Events API payload, and sends conversions with the `ttclid` and `_ttp` cookie for matching.
448
+
449
+ **Setup:**
450
+ 1. Connect your TikTok Ads account in the Datalyr dashboard (Settings > Connections)
451
+ 2. Select your TikTok Pixel
452
+ 3. Create postback rules to map events (e.g., `purchase` → `CompletePayment`, `add_to_cart` → `AddToCart`)
453
+
454
+ No TikTok SDK needed in your app. No access tokens, no native configuration.
455
+
456
+ ### Google Ads
457
+
458
+ Conversions are sent to Google via the [Google Ads API](https://developers.google.com/google-ads/api/docs/conversions/overview).
459
+
460
+ **What the SDK does:** Captures `gclid`, `gbraid`, and `wbraid` from ad click URLs. Collects user data for enhanced conversions.
461
+
462
+ **What the backend does:** Hashes user data, maps events to Google conversion actions, and sends conversions with click IDs for attribution.
463
+
464
+ **Setup:**
465
+ 1. Connect your Google Ads account in the Datalyr dashboard (Settings > Connections)
466
+ 2. Select your conversion actions
467
+ 3. Create postback rules to map events (e.g., `purchase` → your Google conversion action)
468
+
469
+ No Google SDK needed in your app beyond the Play Install Referrer (already included for Android).
418
470
 
419
471
  ### Apple Search Ads
420
472
 
@@ -535,6 +587,43 @@ await Datalyr.trackPurchase(99.99, 'USD');
535
587
 
536
588
  ---
537
589
 
590
+ ## Third-Party Integrations
591
+
592
+ ### Superwall
593
+
594
+ Pass Datalyr attribution data to Superwall to personalize paywalls by ad source, campaign, ad set, and keyword.
595
+
596
+ ```typescript
597
+ import Datalyr from '@datalyr/react-native';
598
+ import Superwall from '@superwall/react-native-superwall';
599
+
600
+ // After both SDKs are initialized
601
+ Superwall.setUserAttributes(Datalyr.getSuperwallAttributes());
602
+
603
+ // Your placements will now have attribution data available as filters
604
+ Superwall.register({ placement: 'onboarding_paywall' });
605
+ ```
606
+
607
+ Call after `Datalyr.initialize()` completes. If using ATT on iOS, call again after the user responds to the ATT prompt to include the IDFA.
608
+
609
+ ### RevenueCat
610
+
611
+ Pass Datalyr attribution data to RevenueCat for revenue attribution and offering targeting.
612
+
613
+ ```typescript
614
+ import Datalyr from '@datalyr/react-native';
615
+ import Purchases from 'react-native-purchases';
616
+
617
+ // After both SDKs are configured
618
+ Purchases.setAttributes(Datalyr.getRevenueCatAttributes());
619
+ ```
620
+
621
+ Call after configuring the Purchases SDK and before the first purchase. If using ATT, call again after permission is granted to include IDFA.
622
+
623
+ > Datalyr also receives Superwall and RevenueCat events via server-side webhooks for analytics. The SDK methods and webhook integration are independent — you can use one or both.
624
+
625
+ ---
626
+
538
627
  ## Troubleshooting
539
628
 
540
629
  ### Events Not Appearing
@@ -176,7 +176,17 @@ export declare class DatalyrSDK {
176
176
  */
177
177
  getPlayInstallReferrer(): Record<string, any> | null;
178
178
  /**
179
- * Update tracking authorization status on all platform SDKs
179
+ * Get attribution data formatted for Superwall's setUserAttributes()
180
+ * Returns a flat Record<string, string> with only non-empty values
181
+ */
182
+ getSuperwallAttributes(): Record<string, string>;
183
+ /**
184
+ * Get attribution data formatted for RevenueCat's Purchases.setAttributes()
185
+ * Returns a flat Record<string, string> with $-prefixed reserved keys
186
+ */
187
+ getRevenueCatAttributes(): Record<string, string>;
188
+ /**
189
+ * Update tracking authorization status
180
190
  * Call this AFTER the user responds to the ATT permission dialog
181
191
  */
182
192
  updateTrackingAuthorization(enabled: boolean): Promise<void>;
@@ -279,5 +289,7 @@ export declare class Datalyr {
279
289
  };
280
290
  static getAppleSearchAdsAttribution(): AppleSearchAdsAttribution | null;
281
291
  static updateTrackingAuthorization(enabled: boolean): Promise<void>;
292
+ static getSuperwallAttributes(): Record<string, string>;
293
+ static getRevenueCatAttributes(): Record<string, string>;
282
294
  }
283
295
  export default datalyr;
@@ -177,7 +177,7 @@ export class DatalyrSDK {
177
177
  const installData = await attributionManager.trackInstall();
178
178
  await this.track('app_install', {
179
179
  platform: Platform.OS === 'ios' || Platform.OS === 'android' ? Platform.OS : 'android',
180
- sdk_version: '1.6.0',
180
+ sdk_version: '1.6.1',
181
181
  ...installData,
182
182
  });
183
183
  }
@@ -702,8 +702,83 @@ export class DatalyrSDK {
702
702
  const data = playInstallReferrerIntegration.getReferrerData();
703
703
  return data ? playInstallReferrerIntegration.getAttributionData() : null;
704
704
  }
705
+ // MARK: - Third-Party Integration Methods
705
706
  /**
706
- * Update tracking authorization status on all platform SDKs
707
+ * Get attribution data formatted for Superwall's setUserAttributes()
708
+ * Returns a flat Record<string, string> with only non-empty values
709
+ */
710
+ getSuperwallAttributes() {
711
+ const attribution = attributionManager.getAttributionData();
712
+ const advertiser = this.cachedAdvertiserInfo;
713
+ const attrs = {};
714
+ const set = (key, value) => {
715
+ if (value != null && String(value) !== '')
716
+ attrs[key] = String(value);
717
+ };
718
+ set('datalyr_id', this.state.visitorId);
719
+ set('media_source', attribution.utm_source);
720
+ set('campaign', attribution.utm_campaign);
721
+ set('adgroup', attribution.adset_id || attribution.utm_content);
722
+ set('ad', attribution.ad_id);
723
+ set('keyword', attribution.keyword);
724
+ set('network', attribution.network);
725
+ set('utm_source', attribution.utm_source);
726
+ set('utm_medium', attribution.utm_medium);
727
+ set('utm_campaign', attribution.utm_campaign);
728
+ set('utm_term', attribution.utm_term);
729
+ set('utm_content', attribution.utm_content);
730
+ set('lyr', attribution.lyr);
731
+ set('fbclid', attribution.fbclid);
732
+ set('gclid', attribution.gclid);
733
+ set('ttclid', attribution.ttclid);
734
+ set('idfa', advertiser === null || advertiser === void 0 ? void 0 : advertiser.idfa);
735
+ set('gaid', advertiser === null || advertiser === void 0 ? void 0 : advertiser.gaid);
736
+ set('att_status', advertiser === null || advertiser === void 0 ? void 0 : advertiser.att_status);
737
+ return attrs;
738
+ }
739
+ /**
740
+ * Get attribution data formatted for RevenueCat's Purchases.setAttributes()
741
+ * Returns a flat Record<string, string> with $-prefixed reserved keys
742
+ */
743
+ getRevenueCatAttributes() {
744
+ const attribution = attributionManager.getAttributionData();
745
+ const advertiser = this.cachedAdvertiserInfo;
746
+ const attrs = {};
747
+ const set = (key, value) => {
748
+ if (value != null && String(value) !== '')
749
+ attrs[key] = String(value);
750
+ };
751
+ // Reserved attributes ($ prefix)
752
+ set('$datalyrId', this.state.visitorId);
753
+ set('$mediaSource', attribution.utm_source);
754
+ set('$campaign', attribution.utm_campaign);
755
+ set('$adGroup', attribution.adset_id);
756
+ set('$ad', attribution.ad_id);
757
+ set('$keyword', attribution.keyword);
758
+ set('$idfa', advertiser === null || advertiser === void 0 ? void 0 : advertiser.idfa);
759
+ set('$gpsAdId', advertiser === null || advertiser === void 0 ? void 0 : advertiser.gaid);
760
+ if ((advertiser === null || advertiser === void 0 ? void 0 : advertiser.att_status) != null) {
761
+ const statusMap = { 0: 'notDetermined', 1: 'restricted', 2: 'denied', 3: 'authorized' };
762
+ set('$attConsentStatus', statusMap[advertiser.att_status] || String(advertiser.att_status));
763
+ }
764
+ // Custom attributes
765
+ set('utm_source', attribution.utm_source);
766
+ set('utm_medium', attribution.utm_medium);
767
+ set('utm_campaign', attribution.utm_campaign);
768
+ set('utm_term', attribution.utm_term);
769
+ set('utm_content', attribution.utm_content);
770
+ set('lyr', attribution.lyr);
771
+ set('fbclid', attribution.fbclid);
772
+ set('gclid', attribution.gclid);
773
+ set('ttclid', attribution.ttclid);
774
+ set('wbraid', attribution.wbraid);
775
+ set('gbraid', attribution.gbraid);
776
+ set('network', attribution.network);
777
+ set('creative_id', attribution.creative_id);
778
+ return attrs;
779
+ }
780
+ /**
781
+ * Update tracking authorization status
707
782
  * Call this AFTER the user responds to the ATT permission dialog
708
783
  */
709
784
  async updateTrackingAuthorization(enabled) {
@@ -821,7 +896,7 @@ export class DatalyrSDK {
821
896
  carrier: deviceInfo.carrier,
822
897
  network_type: getNetworkType(),
823
898
  timestamp: Date.now(),
824
- sdk_version: '1.6.0',
899
+ sdk_version: '1.6.1',
825
900
  // Advertiser data (IDFA/GAID, ATT status) for server-side postback
826
901
  ...(advertiserInfo ? {
827
902
  idfa: advertiserInfo.idfa,
@@ -1117,6 +1192,13 @@ export class Datalyr {
1117
1192
  static async updateTrackingAuthorization(enabled) {
1118
1193
  await datalyr.updateTrackingAuthorization(enabled);
1119
1194
  }
1195
+ // Third-party integration methods
1196
+ static getSuperwallAttributes() {
1197
+ return datalyr.getSuperwallAttributes();
1198
+ }
1199
+ static getRevenueCatAttributes() {
1200
+ return datalyr.getRevenueCatAttributes();
1201
+ }
1120
1202
  }
1121
1203
  // Export default instance for backward compatibility
1122
1204
  export default datalyr;
package/lib/types.d.ts CHANGED
@@ -187,3 +187,7 @@ export interface AttributionData {
187
187
  clickId?: string;
188
188
  installTime?: string;
189
189
  }
190
+ /** Flat dictionary for Superwall's setUserAttributes() */
191
+ export type SuperwallAttributes = Record<string, string>;
192
+ /** Flat dictionary for RevenueCat's Purchases.setAttributes() */
193
+ export type RevenueCatAttributes = Record<string, string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalyr/react-native",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Datalyr SDK for React Native & Expo - Server-side attribution tracking for iOS and Android",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -196,7 +196,7 @@ export class DatalyrSDKExpo {
196
196
  const installData = await attributionManager.trackInstall();
197
197
  await this.track('app_install', {
198
198
  platform: Platform.OS,
199
- sdk_version: '1.6.0',
199
+ sdk_version: '1.6.1',
200
200
  sdk_variant: 'expo',
201
201
  ...installData,
202
202
  });
@@ -606,6 +606,87 @@ export class DatalyrSDKExpo {
606
606
  return appleSearchAdsIntegration.getAttributionData();
607
607
  }
608
608
 
609
+ // MARK: - Third-Party Integration Methods
610
+
611
+ /**
612
+ * Get attribution data formatted for Superwall's setUserAttributes()
613
+ */
614
+ getSuperwallAttributes(): Record<string, string> {
615
+ const attribution = attributionManager.getAttributionData();
616
+ const advertiser = this.cachedAdvertiserInfo;
617
+ const attrs: Record<string, string> = {};
618
+
619
+ const set = (key: string, value: any) => {
620
+ if (value != null && String(value) !== '') attrs[key] = String(value);
621
+ };
622
+
623
+ set('datalyr_id', this.state.visitorId);
624
+ set('media_source', attribution.utm_source);
625
+ set('campaign', attribution.utm_campaign);
626
+ set('adgroup', attribution.adset_id || attribution.utm_content);
627
+ set('ad', attribution.ad_id);
628
+ set('keyword', attribution.keyword);
629
+ set('network', attribution.network);
630
+ set('utm_source', attribution.utm_source);
631
+ set('utm_medium', attribution.utm_medium);
632
+ set('utm_campaign', attribution.utm_campaign);
633
+ set('utm_term', attribution.utm_term);
634
+ set('utm_content', attribution.utm_content);
635
+ set('lyr', attribution.lyr);
636
+ set('fbclid', attribution.fbclid);
637
+ set('gclid', attribution.gclid);
638
+ set('ttclid', attribution.ttclid);
639
+ set('idfa', advertiser?.idfa);
640
+ set('gaid', advertiser?.gaid);
641
+ set('att_status', advertiser?.att_status);
642
+
643
+ return attrs;
644
+ }
645
+
646
+ /**
647
+ * Get attribution data formatted for RevenueCat's Purchases.setAttributes()
648
+ */
649
+ getRevenueCatAttributes(): Record<string, string> {
650
+ const attribution = attributionManager.getAttributionData();
651
+ const advertiser = this.cachedAdvertiserInfo;
652
+ const attrs: Record<string, string> = {};
653
+
654
+ const set = (key: string, value: any) => {
655
+ if (value != null && String(value) !== '') attrs[key] = String(value);
656
+ };
657
+
658
+ // Reserved attributes ($ prefix)
659
+ set('$datalyrId', this.state.visitorId);
660
+ set('$mediaSource', attribution.utm_source);
661
+ set('$campaign', attribution.utm_campaign);
662
+ set('$adGroup', attribution.adset_id);
663
+ set('$ad', attribution.ad_id);
664
+ set('$keyword', attribution.keyword);
665
+ set('$idfa', advertiser?.idfa);
666
+ set('$gpsAdId', advertiser?.gaid);
667
+ if (advertiser?.att_status != null) {
668
+ const statusMap: Record<number, string> = { 0: 'notDetermined', 1: 'restricted', 2: 'denied', 3: 'authorized' };
669
+ set('$attConsentStatus', statusMap[advertiser.att_status] || String(advertiser.att_status));
670
+ }
671
+
672
+ // Custom attributes
673
+ set('utm_source', attribution.utm_source);
674
+ set('utm_medium', attribution.utm_medium);
675
+ set('utm_campaign', attribution.utm_campaign);
676
+ set('utm_term', attribution.utm_term);
677
+ set('utm_content', attribution.utm_content);
678
+ set('lyr', attribution.lyr);
679
+ set('fbclid', attribution.fbclid);
680
+ set('gclid', attribution.gclid);
681
+ set('ttclid', attribution.ttclid);
682
+ set('wbraid', attribution.wbraid);
683
+ set('gbraid', attribution.gbraid);
684
+ set('network', attribution.network);
685
+ set('creative_id', attribution.creative_id);
686
+
687
+ return attrs;
688
+ }
689
+
609
690
  async updateTrackingAuthorization(authorized: boolean): Promise<void> {
610
691
  // Refresh cached advertiser info after ATT status change
611
692
  try {
@@ -700,7 +781,7 @@ export class DatalyrSDKExpo {
700
781
  carrier: deviceInfo.carrier,
701
782
  network_type: networkType,
702
783
  timestamp: Date.now(),
703
- sdk_version: '1.6.0',
784
+ sdk_version: '1.6.1',
704
785
  sdk_variant: 'expo',
705
786
  // Advertiser data (IDFA/GAID, ATT status) for server-side postback
706
787
  ...(advertiserInfo ? {
@@ -960,6 +1041,16 @@ export class DatalyrExpo {
960
1041
  static async updateTrackingAuthorization(authorized: boolean): Promise<void> {
961
1042
  await datalyrExpo.updateTrackingAuthorization(authorized);
962
1043
  }
1044
+
1045
+ // Third-party integration methods
1046
+
1047
+ static getSuperwallAttributes(): Record<string, string> {
1048
+ return datalyrExpo.getSuperwallAttributes();
1049
+ }
1050
+
1051
+ static getRevenueCatAttributes(): Record<string, string> {
1052
+ return datalyrExpo.getRevenueCatAttributes();
1053
+ }
963
1054
  }
964
1055
 
965
1056
  export default datalyrExpo;
@@ -228,7 +228,7 @@ export class DatalyrSDK {
228
228
  const installData = await attributionManager.trackInstall();
229
229
  await this.track('app_install', {
230
230
  platform: Platform.OS === 'ios' || Platform.OS === 'android' ? Platform.OS : 'android',
231
- sdk_version: '1.6.0',
231
+ sdk_version: '1.6.1',
232
232
  ...installData,
233
233
  });
234
234
  }
@@ -862,8 +862,91 @@ export class DatalyrSDK {
862
862
  return data ? playInstallReferrerIntegration.getAttributionData() : null;
863
863
  }
864
864
 
865
+ // MARK: - Third-Party Integration Methods
866
+
865
867
  /**
866
- * Update tracking authorization status on all platform SDKs
868
+ * Get attribution data formatted for Superwall's setUserAttributes()
869
+ * Returns a flat Record<string, string> with only non-empty values
870
+ */
871
+ getSuperwallAttributes(): Record<string, string> {
872
+ const attribution = attributionManager.getAttributionData();
873
+ const advertiser = this.cachedAdvertiserInfo;
874
+ const attrs: Record<string, string> = {};
875
+
876
+ const set = (key: string, value: any) => {
877
+ if (value != null && String(value) !== '') attrs[key] = String(value);
878
+ };
879
+
880
+ set('datalyr_id', this.state.visitorId);
881
+ set('media_source', attribution.utm_source);
882
+ set('campaign', attribution.utm_campaign);
883
+ set('adgroup', attribution.adset_id || attribution.utm_content);
884
+ set('ad', attribution.ad_id);
885
+ set('keyword', attribution.keyword);
886
+ set('network', attribution.network);
887
+ set('utm_source', attribution.utm_source);
888
+ set('utm_medium', attribution.utm_medium);
889
+ set('utm_campaign', attribution.utm_campaign);
890
+ set('utm_term', attribution.utm_term);
891
+ set('utm_content', attribution.utm_content);
892
+ set('lyr', attribution.lyr);
893
+ set('fbclid', attribution.fbclid);
894
+ set('gclid', attribution.gclid);
895
+ set('ttclid', attribution.ttclid);
896
+ set('idfa', advertiser?.idfa);
897
+ set('gaid', advertiser?.gaid);
898
+ set('att_status', advertiser?.att_status);
899
+
900
+ return attrs;
901
+ }
902
+
903
+ /**
904
+ * Get attribution data formatted for RevenueCat's Purchases.setAttributes()
905
+ * Returns a flat Record<string, string> with $-prefixed reserved keys
906
+ */
907
+ getRevenueCatAttributes(): Record<string, string> {
908
+ const attribution = attributionManager.getAttributionData();
909
+ const advertiser = this.cachedAdvertiserInfo;
910
+ const attrs: Record<string, string> = {};
911
+
912
+ const set = (key: string, value: any) => {
913
+ if (value != null && String(value) !== '') attrs[key] = String(value);
914
+ };
915
+
916
+ // Reserved attributes ($ prefix)
917
+ set('$datalyrId', this.state.visitorId);
918
+ set('$mediaSource', attribution.utm_source);
919
+ set('$campaign', attribution.utm_campaign);
920
+ set('$adGroup', attribution.adset_id);
921
+ set('$ad', attribution.ad_id);
922
+ set('$keyword', attribution.keyword);
923
+ set('$idfa', advertiser?.idfa);
924
+ set('$gpsAdId', advertiser?.gaid);
925
+ if (advertiser?.att_status != null) {
926
+ const statusMap: Record<number, string> = { 0: 'notDetermined', 1: 'restricted', 2: 'denied', 3: 'authorized' };
927
+ set('$attConsentStatus', statusMap[advertiser.att_status] || String(advertiser.att_status));
928
+ }
929
+
930
+ // Custom attributes
931
+ set('utm_source', attribution.utm_source);
932
+ set('utm_medium', attribution.utm_medium);
933
+ set('utm_campaign', attribution.utm_campaign);
934
+ set('utm_term', attribution.utm_term);
935
+ set('utm_content', attribution.utm_content);
936
+ set('lyr', attribution.lyr);
937
+ set('fbclid', attribution.fbclid);
938
+ set('gclid', attribution.gclid);
939
+ set('ttclid', attribution.ttclid);
940
+ set('wbraid', attribution.wbraid);
941
+ set('gbraid', attribution.gbraid);
942
+ set('network', attribution.network);
943
+ set('creative_id', attribution.creative_id);
944
+
945
+ return attrs;
946
+ }
947
+
948
+ /**
949
+ * Update tracking authorization status
867
950
  * Call this AFTER the user responds to the ATT permission dialog
868
951
  */
869
952
  async updateTrackingAuthorization(enabled: boolean): Promise<void> {
@@ -991,7 +1074,7 @@ export class DatalyrSDK {
991
1074
  carrier: deviceInfo.carrier,
992
1075
  network_type: getNetworkType(),
993
1076
  timestamp: Date.now(),
994
- sdk_version: '1.6.0',
1077
+ sdk_version: '1.6.1',
995
1078
  // Advertiser data (IDFA/GAID, ATT status) for server-side postback
996
1079
  ...(advertiserInfo ? {
997
1080
  idfa: advertiserInfo.idfa,
@@ -1364,6 +1447,16 @@ export class Datalyr {
1364
1447
  static async updateTrackingAuthorization(enabled: boolean): Promise<void> {
1365
1448
  await datalyr.updateTrackingAuthorization(enabled);
1366
1449
  }
1450
+
1451
+ // Third-party integration methods
1452
+
1453
+ static getSuperwallAttributes(): Record<string, string> {
1454
+ return datalyr.getSuperwallAttributes();
1455
+ }
1456
+
1457
+ static getRevenueCatAttributes(): Record<string, string> {
1458
+ return datalyr.getRevenueCatAttributes();
1459
+ }
1367
1460
  }
1368
1461
 
1369
1462
  // Export default instance for backward compatibility
package/src/types.ts CHANGED
@@ -227,4 +227,12 @@ export interface AttributionData {
227
227
  content?: string;
228
228
  clickId?: string;
229
229
  installTime?: string;
230
- }
230
+ }
231
+
232
+ // Third-Party Integration Attributes
233
+
234
+ /** Flat dictionary for Superwall's setUserAttributes() */
235
+ export type SuperwallAttributes = Record<string, string>;
236
+
237
+ /** Flat dictionary for RevenueCat's Purchases.setAttributes() */
238
+ export type RevenueCatAttributes = Record<string, string>;