@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 +90 -1
- package/lib/datalyr-sdk.d.ts +13 -1
- package/lib/datalyr-sdk.js +85 -3
- package/lib/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/datalyr-sdk-expo.ts +93 -2
- package/src/datalyr-sdk.ts +96 -3
- package/src/types.ts +9 -1
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
|
|
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
|
package/lib/datalyr-sdk.d.ts
CHANGED
|
@@ -176,7 +176,17 @@ export declare class DatalyrSDK {
|
|
|
176
176
|
*/
|
|
177
177
|
getPlayInstallReferrer(): Record<string, any> | null;
|
|
178
178
|
/**
|
|
179
|
-
*
|
|
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;
|
package/lib/datalyr-sdk.js
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
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.
|
|
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
package/src/datalyr-sdk-expo.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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;
|
package/src/datalyr-sdk.ts
CHANGED
|
@@ -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.
|
|
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
|
-
*
|
|
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.
|
|
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>;
|