@datalyr/react-native 1.2.1 → 1.3.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/CHANGELOG.md +19 -0
- package/README.md +145 -9
- package/android/build.gradle +54 -0
- package/android/src/main/AndroidManifest.xml +14 -0
- package/android/src/main/java/com/datalyr/reactnative/DatalyrNativeModule.java +423 -0
- package/android/src/main/java/com/datalyr/reactnative/DatalyrPackage.java +30 -0
- package/android/src/main/java/com/datalyr/reactnative/DatalyrPlayInstallReferrerModule.java +229 -0
- package/datalyr-react-native.podspec +2 -2
- package/ios/DatalyrSKAdNetwork.m +400 -1
- package/ios/PrivacyInfo.xcprivacy +48 -0
- package/lib/ConversionValueEncoder.d.ts +13 -1
- package/lib/ConversionValueEncoder.js +57 -23
- package/lib/datalyr-sdk.d.ts +31 -2
- package/lib/datalyr-sdk.js +138 -30
- package/lib/index.d.ts +5 -1
- package/lib/index.js +4 -1
- package/lib/integrations/index.d.ts +3 -1
- package/lib/integrations/index.js +2 -1
- package/lib/integrations/meta-integration.d.ts +1 -0
- package/lib/integrations/meta-integration.js +4 -3
- package/lib/integrations/play-install-referrer.d.ts +78 -0
- package/lib/integrations/play-install-referrer.js +166 -0
- package/lib/integrations/tiktok-integration.d.ts +1 -0
- package/lib/integrations/tiktok-integration.js +4 -3
- package/lib/journey.d.ts +106 -0
- package/lib/journey.js +258 -0
- package/lib/native/DatalyrNativeBridge.d.ts +42 -3
- package/lib/native/DatalyrNativeBridge.js +63 -9
- package/lib/native/SKAdNetworkBridge.d.ts +142 -0
- package/lib/native/SKAdNetworkBridge.js +328 -0
- package/lib/network-status.d.ts +84 -0
- package/lib/network-status.js +281 -0
- package/lib/types.d.ts +51 -0
- package/lib/utils.d.ts +6 -1
- package/lib/utils.js +52 -2
- package/package.json +13 -4
- package/src/ConversionValueEncoder.ts +67 -26
- package/src/datalyr-sdk-expo.ts +55 -6
- package/src/datalyr-sdk.ts +161 -38
- package/src/expo.ts +4 -0
- package/src/index.ts +7 -1
- package/src/integrations/index.ts +3 -1
- package/src/integrations/meta-integration.ts +4 -3
- package/src/integrations/play-install-referrer.ts +218 -0
- package/src/integrations/tiktok-integration.ts +4 -3
- package/src/journey.ts +338 -0
- package/src/native/DatalyrNativeBridge.ts +99 -13
- package/src/native/SKAdNetworkBridge.ts +481 -2
- package/src/network-status.ts +312 -0
- package/src/types.ts +74 -6
- package/src/utils.ts +62 -6
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Native Bridge for Meta, TikTok,
|
|
2
|
+
* Native Bridge for Meta, TikTok, Apple Search Ads, and Play Install Referrer
|
|
3
3
|
* Uses bundled native modules instead of separate npm packages
|
|
4
|
+
*
|
|
5
|
+
* Supported Platforms:
|
|
6
|
+
* - iOS: Meta SDK, TikTok SDK, Apple Search Ads (AdServices)
|
|
7
|
+
* - Android: Meta SDK, TikTok SDK, Play Install Referrer
|
|
4
8
|
*/
|
|
5
9
|
/**
|
|
6
|
-
* Apple Search Ads attribution data returned from AdServices API
|
|
10
|
+
* Apple Search Ads attribution data returned from AdServices API (iOS only)
|
|
7
11
|
*/
|
|
8
12
|
export interface AppleSearchAdsAttribution {
|
|
9
13
|
attribution: boolean;
|
|
@@ -19,17 +23,36 @@ export interface AppleSearchAdsAttribution {
|
|
|
19
23
|
conversionType?: string;
|
|
20
24
|
countryOrRegion?: string;
|
|
21
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Play Install Referrer data (Android only)
|
|
28
|
+
*/
|
|
29
|
+
export interface PlayInstallReferrerData {
|
|
30
|
+
referrerUrl: string;
|
|
31
|
+
referrerClickTimestamp: number;
|
|
32
|
+
installBeginTimestamp: number;
|
|
33
|
+
installCompleteTimestamp?: number;
|
|
34
|
+
gclid?: string;
|
|
35
|
+
fbclid?: string;
|
|
36
|
+
ttclid?: string;
|
|
37
|
+
utmSource?: string;
|
|
38
|
+
utmMedium?: string;
|
|
39
|
+
utmCampaign?: string;
|
|
40
|
+
utmTerm?: string;
|
|
41
|
+
utmContent?: string;
|
|
42
|
+
referrer?: string;
|
|
43
|
+
}
|
|
22
44
|
/**
|
|
23
45
|
* Check if native module is available
|
|
24
46
|
*/
|
|
25
47
|
export declare const isNativeModuleAvailable: () => boolean;
|
|
26
48
|
/**
|
|
27
|
-
* Get SDK availability status
|
|
49
|
+
* Get SDK availability status for all platforms
|
|
28
50
|
*/
|
|
29
51
|
export declare const getSDKAvailability: () => Promise<{
|
|
30
52
|
meta: boolean;
|
|
31
53
|
tiktok: boolean;
|
|
32
54
|
appleSearchAds: boolean;
|
|
55
|
+
playInstallReferrer: boolean;
|
|
33
56
|
}>;
|
|
34
57
|
export declare const MetaNativeBridge: {
|
|
35
58
|
initialize(appId: string, clientToken?: string, advertiserTrackingEnabled?: boolean): Promise<boolean>;
|
|
@@ -55,3 +78,19 @@ export declare const AppleSearchAdsNativeBridge: {
|
|
|
55
78
|
*/
|
|
56
79
|
getAttribution(): Promise<AppleSearchAdsAttribution | null>;
|
|
57
80
|
};
|
|
81
|
+
export declare const PlayInstallReferrerNativeBridge: {
|
|
82
|
+
/**
|
|
83
|
+
* Check if Play Install Referrer is available
|
|
84
|
+
* Only available on Android with Google Play Services
|
|
85
|
+
*/
|
|
86
|
+
isAvailable(): Promise<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* Get install referrer data from Google Play
|
|
89
|
+
*
|
|
90
|
+
* Returns UTM parameters, click IDs (gclid, fbclid, ttclid), and timestamps
|
|
91
|
+
* from the Google Play Store referrer.
|
|
92
|
+
*
|
|
93
|
+
* Call this on first app launch to capture install attribution.
|
|
94
|
+
*/
|
|
95
|
+
getInstallReferrer(): Promise<PlayInstallReferrerData | null>;
|
|
96
|
+
};
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Native Bridge for Meta, TikTok,
|
|
2
|
+
* Native Bridge for Meta, TikTok, Apple Search Ads, and Play Install Referrer
|
|
3
3
|
* Uses bundled native modules instead of separate npm packages
|
|
4
|
+
*
|
|
5
|
+
* Supported Platforms:
|
|
6
|
+
* - iOS: Meta SDK, TikTok SDK, Apple Search Ads (AdServices)
|
|
7
|
+
* - Android: Meta SDK, TikTok SDK, Play Install Referrer
|
|
4
8
|
*/
|
|
9
|
+
var _a;
|
|
5
10
|
import { NativeModules, Platform } from 'react-native';
|
|
6
|
-
// Native
|
|
7
|
-
const DatalyrNative =
|
|
11
|
+
// Native modules - available on both iOS and Android
|
|
12
|
+
const DatalyrNative = (_a = NativeModules.DatalyrNative) !== null && _a !== void 0 ? _a : null;
|
|
13
|
+
// Play Install Referrer - Android only
|
|
14
|
+
const DatalyrPlayInstallReferrer = Platform.OS === 'android' ? NativeModules.DatalyrPlayInstallReferrer : null;
|
|
8
15
|
/**
|
|
9
16
|
* Check if native module is available
|
|
10
17
|
*/
|
|
@@ -12,17 +19,28 @@ export const isNativeModuleAvailable = () => {
|
|
|
12
19
|
return DatalyrNative !== null;
|
|
13
20
|
};
|
|
14
21
|
/**
|
|
15
|
-
* Get SDK availability status
|
|
22
|
+
* Get SDK availability status for all platforms
|
|
16
23
|
*/
|
|
17
24
|
export const getSDKAvailability = async () => {
|
|
25
|
+
const defaultAvailability = {
|
|
26
|
+
meta: false,
|
|
27
|
+
tiktok: false,
|
|
28
|
+
appleSearchAds: false,
|
|
29
|
+
playInstallReferrer: false,
|
|
30
|
+
};
|
|
18
31
|
if (!DatalyrNative) {
|
|
19
|
-
return
|
|
32
|
+
return defaultAvailability;
|
|
20
33
|
}
|
|
21
34
|
try {
|
|
22
|
-
|
|
35
|
+
const result = await DatalyrNative.getSDKAvailability();
|
|
36
|
+
return {
|
|
37
|
+
...defaultAvailability,
|
|
38
|
+
...result,
|
|
39
|
+
playInstallReferrer: Platform.OS === 'android' && DatalyrPlayInstallReferrer !== null,
|
|
40
|
+
};
|
|
23
41
|
}
|
|
24
42
|
catch (_a) {
|
|
25
|
-
return
|
|
43
|
+
return defaultAvailability;
|
|
26
44
|
}
|
|
27
45
|
};
|
|
28
46
|
// MARK: - Meta SDK Bridge
|
|
@@ -166,7 +184,7 @@ export const TikTokNativeBridge = {
|
|
|
166
184
|
}
|
|
167
185
|
},
|
|
168
186
|
};
|
|
169
|
-
// MARK: - Apple Search Ads Bridge
|
|
187
|
+
// MARK: - Apple Search Ads Bridge (iOS only)
|
|
170
188
|
export const AppleSearchAdsNativeBridge = {
|
|
171
189
|
/**
|
|
172
190
|
* Get Apple Search Ads attribution data
|
|
@@ -174,7 +192,7 @@ export const AppleSearchAdsNativeBridge = {
|
|
|
174
192
|
* Returns null if user didn't come from Apple Search Ads or on older iOS
|
|
175
193
|
*/
|
|
176
194
|
async getAttribution() {
|
|
177
|
-
if (!DatalyrNative)
|
|
195
|
+
if (!DatalyrNative || Platform.OS !== 'ios')
|
|
178
196
|
return null;
|
|
179
197
|
try {
|
|
180
198
|
return await DatalyrNative.getAppleSearchAdsAttribution();
|
|
@@ -185,3 +203,39 @@ export const AppleSearchAdsNativeBridge = {
|
|
|
185
203
|
}
|
|
186
204
|
},
|
|
187
205
|
};
|
|
206
|
+
// MARK: - Play Install Referrer Bridge (Android only)
|
|
207
|
+
export const PlayInstallReferrerNativeBridge = {
|
|
208
|
+
/**
|
|
209
|
+
* Check if Play Install Referrer is available
|
|
210
|
+
* Only available on Android with Google Play Services
|
|
211
|
+
*/
|
|
212
|
+
async isAvailable() {
|
|
213
|
+
if (!DatalyrPlayInstallReferrer || Platform.OS !== 'android')
|
|
214
|
+
return false;
|
|
215
|
+
try {
|
|
216
|
+
return await DatalyrPlayInstallReferrer.isAvailable();
|
|
217
|
+
}
|
|
218
|
+
catch (_a) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
/**
|
|
223
|
+
* Get install referrer data from Google Play
|
|
224
|
+
*
|
|
225
|
+
* Returns UTM parameters, click IDs (gclid, fbclid, ttclid), and timestamps
|
|
226
|
+
* from the Google Play Store referrer.
|
|
227
|
+
*
|
|
228
|
+
* Call this on first app launch to capture install attribution.
|
|
229
|
+
*/
|
|
230
|
+
async getInstallReferrer() {
|
|
231
|
+
if (!DatalyrPlayInstallReferrer || Platform.OS !== 'android')
|
|
232
|
+
return null;
|
|
233
|
+
try {
|
|
234
|
+
return await DatalyrPlayInstallReferrer.getInstallReferrer();
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
console.error('[Datalyr/PlayInstallReferrer] Get referrer failed:', error);
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
};
|
|
@@ -1,4 +1,146 @@
|
|
|
1
|
+
export type SKANCoarseValue = 'low' | 'medium' | 'high';
|
|
2
|
+
export interface SKANConversionResult {
|
|
3
|
+
fineValue: number;
|
|
4
|
+
coarseValue: SKANCoarseValue;
|
|
5
|
+
lockWindow: boolean;
|
|
6
|
+
priority: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PostbackUpdateResponse {
|
|
9
|
+
success: boolean;
|
|
10
|
+
framework: 'AdAttributionKit' | 'SKAdNetwork';
|
|
11
|
+
fineValue: number;
|
|
12
|
+
coarseValue: string;
|
|
13
|
+
lockWindow: boolean;
|
|
14
|
+
type?: 'reengagement';
|
|
15
|
+
}
|
|
16
|
+
export interface AttributionFrameworkInfo {
|
|
17
|
+
framework: 'AdAttributionKit' | 'SKAdNetwork' | 'none';
|
|
18
|
+
version: string;
|
|
19
|
+
reengagement_available: boolean;
|
|
20
|
+
overlapping_windows: boolean;
|
|
21
|
+
fine_value_range: {
|
|
22
|
+
min: number;
|
|
23
|
+
max: number;
|
|
24
|
+
};
|
|
25
|
+
coarse_values: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface EnhancedAttributionInfo extends AttributionFrameworkInfo {
|
|
28
|
+
geo_postback_available: boolean;
|
|
29
|
+
development_postbacks: boolean;
|
|
30
|
+
features: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface PostbackEnvironmentResponse {
|
|
33
|
+
environment: 'production' | 'sandbox';
|
|
34
|
+
isSandbox: boolean;
|
|
35
|
+
note: string;
|
|
36
|
+
}
|
|
37
|
+
export interface OverlappingWindowPostbackResponse {
|
|
38
|
+
success: boolean;
|
|
39
|
+
framework: string;
|
|
40
|
+
version: string;
|
|
41
|
+
fineValue: number;
|
|
42
|
+
coarseValue: string;
|
|
43
|
+
lockWindow: boolean;
|
|
44
|
+
windowIndex: number;
|
|
45
|
+
overlappingWindows: boolean;
|
|
46
|
+
note?: string;
|
|
47
|
+
}
|
|
1
48
|
export declare class SKAdNetworkBridge {
|
|
49
|
+
private static _isSKAN4Available;
|
|
50
|
+
/**
|
|
51
|
+
* SKAN 3.0 - Update conversion value (0-63)
|
|
52
|
+
* @deprecated Use updatePostbackConversionValue for iOS 16.1+
|
|
53
|
+
*/
|
|
2
54
|
static updateConversionValue(value: number): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* SKAN 4.0 - Update postback conversion value with coarse value and lock window
|
|
57
|
+
* Falls back to SKAN 3.0 on iOS 14.0-16.0
|
|
58
|
+
*/
|
|
59
|
+
static updatePostbackConversionValue(result: SKANConversionResult): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Check if SKAN 4.0 is available (iOS 16.1+)
|
|
62
|
+
*/
|
|
63
|
+
static isSKAN4Available(): Promise<boolean>;
|
|
3
64
|
static isAvailable(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Check if AdAttributionKit is available (iOS 17.4+)
|
|
67
|
+
* AdAttributionKit is Apple's replacement for SKAdNetwork with enhanced features
|
|
68
|
+
*/
|
|
69
|
+
private static _isAdAttributionKitAvailable;
|
|
70
|
+
static isAdAttributionKitAvailable(): Promise<boolean>;
|
|
71
|
+
/**
|
|
72
|
+
* Register for ad network attribution
|
|
73
|
+
* Uses AdAttributionKit on iOS 17.4+, SKAdNetwork on earlier versions
|
|
74
|
+
*/
|
|
75
|
+
static registerForAttribution(): Promise<{
|
|
76
|
+
framework: string;
|
|
77
|
+
registered: boolean;
|
|
78
|
+
} | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Get attribution framework info
|
|
81
|
+
* Returns details about which framework is being used and its capabilities
|
|
82
|
+
*/
|
|
83
|
+
static getAttributionInfo(): Promise<AttributionFrameworkInfo | null>;
|
|
84
|
+
/**
|
|
85
|
+
* Check if overlapping conversion windows are available (iOS 18.4+)
|
|
86
|
+
* Overlapping windows allow multiple conversion windows to be active simultaneously
|
|
87
|
+
*/
|
|
88
|
+
private static _isOverlappingWindowsAvailable;
|
|
89
|
+
static isOverlappingWindowsAvailable(): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Update conversion value for re-engagement attribution (AdAttributionKit iOS 17.4+ only)
|
|
92
|
+
* Re-engagement tracks users who return to the app via an ad after initial install.
|
|
93
|
+
*
|
|
94
|
+
* @param result - Conversion result with fine value (0-63), coarse value, and lock window
|
|
95
|
+
* @returns Response with framework info, or null if not supported
|
|
96
|
+
*/
|
|
97
|
+
static updateReengagementConversionValue(result: SKANConversionResult): Promise<PostbackUpdateResponse | null>;
|
|
98
|
+
/**
|
|
99
|
+
* Get a summary of attribution capabilities for the current device
|
|
100
|
+
*/
|
|
101
|
+
static getCapabilitiesSummary(): Promise<{
|
|
102
|
+
skadnetwork3: boolean;
|
|
103
|
+
skadnetwork4: boolean;
|
|
104
|
+
adAttributionKit: boolean;
|
|
105
|
+
reengagement: boolean;
|
|
106
|
+
overlappingWindows: boolean;
|
|
107
|
+
geoPostback: boolean;
|
|
108
|
+
developmentPostbacks: boolean;
|
|
109
|
+
framework: string;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* Check if geo-level postback data is available (iOS 18.4+)
|
|
113
|
+
* Geo postbacks include country code information for regional analytics
|
|
114
|
+
*/
|
|
115
|
+
private static _isGeoPostbackAvailable;
|
|
116
|
+
static isGeoPostbackAvailable(): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Set postback environment for testing (iOS 18.4+)
|
|
119
|
+
* Note: Actual sandbox mode requires Developer Mode enabled in iOS Settings
|
|
120
|
+
*
|
|
121
|
+
* @param environment - 'production' or 'sandbox'
|
|
122
|
+
*/
|
|
123
|
+
static setPostbackEnvironment(environment: 'production' | 'sandbox'): Promise<PostbackEnvironmentResponse | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Get enhanced attribution info including iOS 18.4+ features
|
|
126
|
+
* Returns details about geo postbacks, development mode, and all available features
|
|
127
|
+
*/
|
|
128
|
+
static getEnhancedAttributionInfo(): Promise<EnhancedAttributionInfo | null>;
|
|
129
|
+
/**
|
|
130
|
+
* Update postback with overlapping window support (iOS 18.4+)
|
|
131
|
+
* Allows tracking conversions across multiple time windows simultaneously
|
|
132
|
+
*
|
|
133
|
+
* @param result - Conversion result with fine value, coarse value, and lock window
|
|
134
|
+
* @param windowIndex - Window index: 0 (0-2 days), 1 (3-7 days), 2 (8-35 days)
|
|
135
|
+
*/
|
|
136
|
+
static updatePostbackWithWindow(result: SKANConversionResult, windowIndex: 0 | 1 | 2): Promise<OverlappingWindowPostbackResponse | null>;
|
|
137
|
+
/**
|
|
138
|
+
* Enable development/sandbox mode for testing attribution
|
|
139
|
+
* Convenience method that sets sandbox environment
|
|
140
|
+
*/
|
|
141
|
+
static enableDevelopmentMode(): Promise<boolean>;
|
|
142
|
+
/**
|
|
143
|
+
* Disable development mode (switch to production)
|
|
144
|
+
*/
|
|
145
|
+
static disableDevelopmentMode(): Promise<boolean>;
|
|
4
146
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
const { DatalyrSKAdNetwork } = NativeModules;
|
|
3
3
|
export class SKAdNetworkBridge {
|
|
4
|
+
/**
|
|
5
|
+
* SKAN 3.0 - Update conversion value (0-63)
|
|
6
|
+
* @deprecated Use updatePostbackConversionValue for iOS 16.1+
|
|
7
|
+
*/
|
|
4
8
|
static async updateConversionValue(value) {
|
|
5
9
|
if (Platform.OS !== 'ios') {
|
|
6
10
|
return false; // Android doesn't support SKAdNetwork
|
|
@@ -19,7 +23,331 @@ export class SKAdNetworkBridge {
|
|
|
19
23
|
return false;
|
|
20
24
|
}
|
|
21
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* SKAN 4.0 - Update postback conversion value with coarse value and lock window
|
|
28
|
+
* Falls back to SKAN 3.0 on iOS 14.0-16.0
|
|
29
|
+
*/
|
|
30
|
+
static async updatePostbackConversionValue(result) {
|
|
31
|
+
if (Platform.OS !== 'ios') {
|
|
32
|
+
return false; // Android doesn't support SKAdNetwork
|
|
33
|
+
}
|
|
34
|
+
if (!DatalyrSKAdNetwork) {
|
|
35
|
+
console.warn('[Datalyr] SKAdNetwork native module not found. Ensure native bridge is properly configured.');
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const response = await DatalyrSKAdNetwork.updatePostbackConversionValue(result.fineValue, result.coarseValue, result.lockWindow);
|
|
40
|
+
const isSKAN4 = await this.isSKAN4Available();
|
|
41
|
+
if (isSKAN4) {
|
|
42
|
+
console.log(`[Datalyr] SKAN 4.0 postback updated: fineValue=${result.fineValue}, coarseValue=${result.coarseValue}, lockWindow=${result.lockWindow}`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log(`[Datalyr] SKAN 3.0 fallback: conversionValue=${result.fineValue}`);
|
|
46
|
+
}
|
|
47
|
+
return response.success;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.warn('[Datalyr] Failed to update SKAdNetwork postback conversion value:', error);
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if SKAN 4.0 is available (iOS 16.1+)
|
|
56
|
+
*/
|
|
57
|
+
static async isSKAN4Available() {
|
|
58
|
+
if (Platform.OS !== 'ios') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (this._isSKAN4Available !== null) {
|
|
62
|
+
return this._isSKAN4Available;
|
|
63
|
+
}
|
|
64
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.isSKAN4Available)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
this._isSKAN4Available = await DatalyrSKAdNetwork.isSKAN4Available();
|
|
69
|
+
return this._isSKAN4Available;
|
|
70
|
+
}
|
|
71
|
+
catch (_a) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
22
75
|
static isAvailable() {
|
|
23
76
|
return Platform.OS === 'ios' && !!DatalyrSKAdNetwork;
|
|
24
77
|
}
|
|
78
|
+
static async isAdAttributionKitAvailable() {
|
|
79
|
+
if (Platform.OS !== 'ios') {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (this._isAdAttributionKitAvailable !== null) {
|
|
83
|
+
return this._isAdAttributionKitAvailable;
|
|
84
|
+
}
|
|
85
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.isAdAttributionKitAvailable)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
this._isAdAttributionKitAvailable = await DatalyrSKAdNetwork.isAdAttributionKitAvailable();
|
|
90
|
+
return this._isAdAttributionKitAvailable;
|
|
91
|
+
}
|
|
92
|
+
catch (_a) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Register for ad network attribution
|
|
98
|
+
* Uses AdAttributionKit on iOS 17.4+, SKAdNetwork on earlier versions
|
|
99
|
+
*/
|
|
100
|
+
static async registerForAttribution() {
|
|
101
|
+
if (Platform.OS !== 'ios') {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.registerForAttribution)) {
|
|
105
|
+
console.warn('[Datalyr] Attribution registration not available');
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const result = await DatalyrSKAdNetwork.registerForAttribution();
|
|
110
|
+
console.log(`[Datalyr] Registered for attribution: ${result.framework}`);
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.warn('[Datalyr] Failed to register for attribution:', error);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get attribution framework info
|
|
120
|
+
* Returns details about which framework is being used and its capabilities
|
|
121
|
+
*/
|
|
122
|
+
static async getAttributionInfo() {
|
|
123
|
+
if (Platform.OS !== 'ios') {
|
|
124
|
+
return {
|
|
125
|
+
framework: 'none',
|
|
126
|
+
version: '0',
|
|
127
|
+
reengagement_available: false,
|
|
128
|
+
overlapping_windows: false,
|
|
129
|
+
fine_value_range: { min: 0, max: 0 },
|
|
130
|
+
coarse_values: [],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.getAttributionInfo)) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
return await DatalyrSKAdNetwork.getAttributionInfo();
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.warn('[Datalyr] Failed to get attribution info:', error);
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
static async isOverlappingWindowsAvailable() {
|
|
145
|
+
if (Platform.OS !== 'ios') {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
if (this._isOverlappingWindowsAvailable !== null) {
|
|
149
|
+
return this._isOverlappingWindowsAvailable;
|
|
150
|
+
}
|
|
151
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.isOverlappingWindowsAvailable)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
this._isOverlappingWindowsAvailable = await DatalyrSKAdNetwork.isOverlappingWindowsAvailable();
|
|
156
|
+
return this._isOverlappingWindowsAvailable;
|
|
157
|
+
}
|
|
158
|
+
catch (_a) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Update conversion value for re-engagement attribution (AdAttributionKit iOS 17.4+ only)
|
|
164
|
+
* Re-engagement tracks users who return to the app via an ad after initial install.
|
|
165
|
+
*
|
|
166
|
+
* @param result - Conversion result with fine value (0-63), coarse value, and lock window
|
|
167
|
+
* @returns Response with framework info, or null if not supported
|
|
168
|
+
*/
|
|
169
|
+
static async updateReengagementConversionValue(result) {
|
|
170
|
+
if (Platform.OS !== 'ios') {
|
|
171
|
+
return null; // Android doesn't support AdAttributionKit
|
|
172
|
+
}
|
|
173
|
+
// Check if AdAttributionKit is available (required for re-engagement)
|
|
174
|
+
const isAAKAvailable = await this.isAdAttributionKitAvailable();
|
|
175
|
+
if (!isAAKAvailable) {
|
|
176
|
+
console.warn('[Datalyr] Re-engagement attribution requires iOS 17.4+ (AdAttributionKit)');
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.updateReengagementConversionValue)) {
|
|
180
|
+
console.warn('[Datalyr] Re-engagement native module not available');
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const response = await DatalyrSKAdNetwork.updateReengagementConversionValue(result.fineValue, result.coarseValue, result.lockWindow);
|
|
185
|
+
console.log(`[Datalyr] AdAttributionKit re-engagement updated: fineValue=${result.fineValue}, coarseValue=${result.coarseValue}, lockWindow=${result.lockWindow}`);
|
|
186
|
+
return response;
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
console.warn('[Datalyr] Failed to update re-engagement conversion value:', error);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get a summary of attribution capabilities for the current device
|
|
195
|
+
*/
|
|
196
|
+
static async getCapabilitiesSummary() {
|
|
197
|
+
var _a, _b;
|
|
198
|
+
const info = await this.getAttributionInfo();
|
|
199
|
+
const isSKAN4 = await this.isSKAN4Available();
|
|
200
|
+
const isAAK = await this.isAdAttributionKitAvailable();
|
|
201
|
+
const isOverlapping = await this.isOverlappingWindowsAvailable();
|
|
202
|
+
const isGeo = await this.isGeoPostbackAvailable();
|
|
203
|
+
return {
|
|
204
|
+
skadnetwork3: Platform.OS === 'ios',
|
|
205
|
+
skadnetwork4: isSKAN4,
|
|
206
|
+
adAttributionKit: isAAK,
|
|
207
|
+
reengagement: (_a = info === null || info === void 0 ? void 0 : info.reengagement_available) !== null && _a !== void 0 ? _a : false,
|
|
208
|
+
overlappingWindows: isOverlapping,
|
|
209
|
+
geoPostback: isGeo,
|
|
210
|
+
developmentPostbacks: isGeo, // Same iOS version requirement
|
|
211
|
+
framework: (_b = info === null || info === void 0 ? void 0 : info.framework) !== null && _b !== void 0 ? _b : 'none',
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
static async isGeoPostbackAvailable() {
|
|
215
|
+
if (Platform.OS !== 'ios') {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
if (this._isGeoPostbackAvailable !== null) {
|
|
219
|
+
return this._isGeoPostbackAvailable;
|
|
220
|
+
}
|
|
221
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.isGeoPostbackAvailable)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
this._isGeoPostbackAvailable = await DatalyrSKAdNetwork.isGeoPostbackAvailable();
|
|
226
|
+
return this._isGeoPostbackAvailable;
|
|
227
|
+
}
|
|
228
|
+
catch (_a) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Set postback environment for testing (iOS 18.4+)
|
|
234
|
+
* Note: Actual sandbox mode requires Developer Mode enabled in iOS Settings
|
|
235
|
+
*
|
|
236
|
+
* @param environment - 'production' or 'sandbox'
|
|
237
|
+
*/
|
|
238
|
+
static async setPostbackEnvironment(environment) {
|
|
239
|
+
if (Platform.OS !== 'ios') {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.setPostbackEnvironment)) {
|
|
243
|
+
console.warn('[Datalyr] Development postbacks require iOS 18.4+');
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
const result = await DatalyrSKAdNetwork.setPostbackEnvironment(environment);
|
|
248
|
+
console.log(`[Datalyr] Postback environment: ${result.environment}`);
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
console.warn('[Datalyr] Failed to set postback environment:', error);
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get enhanced attribution info including iOS 18.4+ features
|
|
258
|
+
* Returns details about geo postbacks, development mode, and all available features
|
|
259
|
+
*/
|
|
260
|
+
static async getEnhancedAttributionInfo() {
|
|
261
|
+
if (Platform.OS !== 'ios') {
|
|
262
|
+
return {
|
|
263
|
+
framework: 'none',
|
|
264
|
+
version: '0',
|
|
265
|
+
reengagement_available: false,
|
|
266
|
+
overlapping_windows: false,
|
|
267
|
+
geo_postback_available: false,
|
|
268
|
+
development_postbacks: false,
|
|
269
|
+
fine_value_range: { min: 0, max: 0 },
|
|
270
|
+
coarse_values: [],
|
|
271
|
+
features: [],
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.getEnhancedAttributionInfo)) {
|
|
275
|
+
// Fallback to basic info if enhanced not available
|
|
276
|
+
const basicInfo = await this.getAttributionInfo();
|
|
277
|
+
if (basicInfo) {
|
|
278
|
+
return {
|
|
279
|
+
...basicInfo,
|
|
280
|
+
geo_postback_available: false,
|
|
281
|
+
development_postbacks: false,
|
|
282
|
+
features: [],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
288
|
+
return await DatalyrSKAdNetwork.getEnhancedAttributionInfo();
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
console.warn('[Datalyr] Failed to get enhanced attribution info:', error);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Update postback with overlapping window support (iOS 18.4+)
|
|
297
|
+
* Allows tracking conversions across multiple time windows simultaneously
|
|
298
|
+
*
|
|
299
|
+
* @param result - Conversion result with fine value, coarse value, and lock window
|
|
300
|
+
* @param windowIndex - Window index: 0 (0-2 days), 1 (3-7 days), 2 (8-35 days)
|
|
301
|
+
*/
|
|
302
|
+
static async updatePostbackWithWindow(result, windowIndex) {
|
|
303
|
+
if (Platform.OS !== 'ios') {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
if (!(DatalyrSKAdNetwork === null || DatalyrSKAdNetwork === void 0 ? void 0 : DatalyrSKAdNetwork.updatePostbackWithWindow)) {
|
|
307
|
+
console.warn('[Datalyr] Overlapping windows require iOS 16.1+ (full support on iOS 18.4+)');
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
const response = await DatalyrSKAdNetwork.updatePostbackWithWindow(result.fineValue, result.coarseValue, result.lockWindow, windowIndex);
|
|
312
|
+
console.log(`[Datalyr] Postback updated for window ${windowIndex}: fineValue=${result.fineValue}, overlapping=${response.overlappingWindows}`);
|
|
313
|
+
return response;
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
console.warn('[Datalyr] Failed to update postback with window:', error);
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Enable development/sandbox mode for testing attribution
|
|
322
|
+
* Convenience method that sets sandbox environment
|
|
323
|
+
*/
|
|
324
|
+
static async enableDevelopmentMode() {
|
|
325
|
+
var _a;
|
|
326
|
+
const result = await this.setPostbackEnvironment('sandbox');
|
|
327
|
+
return (_a = result === null || result === void 0 ? void 0 : result.isSandbox) !== null && _a !== void 0 ? _a : false;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Disable development mode (switch to production)
|
|
331
|
+
*/
|
|
332
|
+
static async disableDevelopmentMode() {
|
|
333
|
+
const result = await this.setPostbackEnvironment('production');
|
|
334
|
+
return result !== null && !result.isSandbox;
|
|
335
|
+
}
|
|
25
336
|
}
|
|
337
|
+
SKAdNetworkBridge._isSKAN4Available = null;
|
|
338
|
+
/**
|
|
339
|
+
* Check if AdAttributionKit is available (iOS 17.4+)
|
|
340
|
+
* AdAttributionKit is Apple's replacement for SKAdNetwork with enhanced features
|
|
341
|
+
*/
|
|
342
|
+
SKAdNetworkBridge._isAdAttributionKitAvailable = null;
|
|
343
|
+
/**
|
|
344
|
+
* Check if overlapping conversion windows are available (iOS 18.4+)
|
|
345
|
+
* Overlapping windows allow multiple conversion windows to be active simultaneously
|
|
346
|
+
*/
|
|
347
|
+
SKAdNetworkBridge._isOverlappingWindowsAvailable = null;
|
|
348
|
+
// ===== iOS 18.4+ Features =====
|
|
349
|
+
/**
|
|
350
|
+
* Check if geo-level postback data is available (iOS 18.4+)
|
|
351
|
+
* Geo postbacks include country code information for regional analytics
|
|
352
|
+
*/
|
|
353
|
+
SKAdNetworkBridge._isGeoPostbackAvailable = null;
|