@datalyr/react-native 1.2.0 → 1.3.0
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 +8 -0
- package/README.md +30 -1
- 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/DatalyrNative.m +4 -0
- package/ios/DatalyrNative.swift +58 -1
- package/ios/DatalyrSKAdNetwork.m +52 -1
- package/lib/ConversionValueEncoder.d.ts +13 -1
- package/lib/ConversionValueEncoder.js +57 -23
- package/lib/datalyr-sdk.d.ts +34 -2
- package/lib/datalyr-sdk.js +90 -8
- package/lib/index.d.ts +4 -1
- package/lib/index.js +2 -1
- package/lib/integrations/apple-search-ads-integration.d.ts +43 -0
- package/lib/integrations/apple-search-ads-integration.js +106 -0
- package/lib/integrations/index.d.ts +4 -1
- package/lib/integrations/index.js +3 -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 +74 -0
- package/lib/integrations/play-install-referrer.js +156 -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 +67 -2
- package/lib/native/DatalyrNativeBridge.js +80 -7
- package/lib/native/SKAdNetworkBridge.d.ts +21 -0
- package/lib/native/SKAdNetworkBridge.js +54 -0
- package/package.json +9 -3
- package/src/ConversionValueEncoder.ts +67 -26
- package/src/datalyr-sdk-expo.ts +98 -9
- package/src/datalyr-sdk.ts +109 -14
- package/src/expo.ts +8 -0
- package/src/index.ts +6 -1
- package/src/integrations/apple-search-ads-integration.ts +119 -0
- package/src/integrations/index.ts +4 -1
- package/src/integrations/meta-integration.ts +4 -3
- package/src/integrations/play-install-referrer.ts +203 -0
- package/src/integrations/tiktok-integration.ts +4 -3
- package/src/journey.ts +338 -0
- package/src/native/DatalyrNativeBridge.ts +137 -9
- package/src/native/SKAdNetworkBridge.ts +86 -2
|
@@ -1,10 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Native Bridge for Meta and
|
|
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
10
|
import { NativeModules, Platform } from 'react-native';
|
|
7
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Apple Search Ads attribution data returned from AdServices API (iOS only)
|
|
14
|
+
*/
|
|
15
|
+
export interface AppleSearchAdsAttribution {
|
|
16
|
+
attribution: boolean;
|
|
17
|
+
orgId?: number;
|
|
18
|
+
orgName?: string;
|
|
19
|
+
campaignId?: number;
|
|
20
|
+
campaignName?: string;
|
|
21
|
+
adGroupId?: number;
|
|
22
|
+
adGroupName?: string;
|
|
23
|
+
keywordId?: number;
|
|
24
|
+
keyword?: string;
|
|
25
|
+
clickDate?: string;
|
|
26
|
+
conversionType?: string;
|
|
27
|
+
countryOrRegion?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Play Install Referrer data (Android only)
|
|
32
|
+
*/
|
|
33
|
+
export interface PlayInstallReferrerData {
|
|
34
|
+
referrerUrl: string;
|
|
35
|
+
referrerClickTimestamp: number;
|
|
36
|
+
installBeginTimestamp: number;
|
|
37
|
+
installCompleteTimestamp?: number;
|
|
38
|
+
gclid?: string;
|
|
39
|
+
fbclid?: string;
|
|
40
|
+
ttclid?: string;
|
|
41
|
+
utmSource?: string;
|
|
42
|
+
utmMedium?: string;
|
|
43
|
+
utmCampaign?: string;
|
|
44
|
+
utmTerm?: string;
|
|
45
|
+
utmContent?: string;
|
|
46
|
+
referrer?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
8
49
|
interface DatalyrNativeModule {
|
|
9
50
|
// Meta SDK Methods
|
|
10
51
|
initializeMetaSDK(
|
|
@@ -48,13 +89,29 @@ interface DatalyrNativeModule {
|
|
|
48
89
|
logoutTikTok(): Promise<boolean>;
|
|
49
90
|
updateTikTokTrackingAuthorization(enabled: boolean): Promise<boolean>;
|
|
50
91
|
|
|
92
|
+
// Apple Search Ads Methods (iOS only)
|
|
93
|
+
getAppleSearchAdsAttribution(): Promise<AppleSearchAdsAttribution | null>;
|
|
94
|
+
|
|
51
95
|
// SDK Availability
|
|
52
|
-
getSDKAvailability(): Promise<{
|
|
96
|
+
getSDKAvailability(): Promise<{
|
|
97
|
+
meta: boolean;
|
|
98
|
+
tiktok: boolean;
|
|
99
|
+
appleSearchAds: boolean;
|
|
100
|
+
playInstallReferrer?: boolean;
|
|
101
|
+
}>;
|
|
53
102
|
}
|
|
54
103
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
104
|
+
interface PlayInstallReferrerModule {
|
|
105
|
+
isAvailable(): Promise<boolean>;
|
|
106
|
+
getInstallReferrer(): Promise<PlayInstallReferrerData | null>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Native modules - available on both iOS and Android
|
|
110
|
+
const DatalyrNative: DatalyrNativeModule | null = NativeModules.DatalyrNative ?? null;
|
|
111
|
+
|
|
112
|
+
// Play Install Referrer - Android only
|
|
113
|
+
const DatalyrPlayInstallReferrer: PlayInstallReferrerModule | null =
|
|
114
|
+
Platform.OS === 'android' ? NativeModules.DatalyrPlayInstallReferrer : null;
|
|
58
115
|
|
|
59
116
|
/**
|
|
60
117
|
* Check if native module is available
|
|
@@ -64,20 +121,34 @@ export const isNativeModuleAvailable = (): boolean => {
|
|
|
64
121
|
};
|
|
65
122
|
|
|
66
123
|
/**
|
|
67
|
-
* Get SDK availability status
|
|
124
|
+
* Get SDK availability status for all platforms
|
|
68
125
|
*/
|
|
69
126
|
export const getSDKAvailability = async (): Promise<{
|
|
70
127
|
meta: boolean;
|
|
71
128
|
tiktok: boolean;
|
|
129
|
+
appleSearchAds: boolean;
|
|
130
|
+
playInstallReferrer: boolean;
|
|
72
131
|
}> => {
|
|
132
|
+
const defaultAvailability = {
|
|
133
|
+
meta: false,
|
|
134
|
+
tiktok: false,
|
|
135
|
+
appleSearchAds: false,
|
|
136
|
+
playInstallReferrer: false,
|
|
137
|
+
};
|
|
138
|
+
|
|
73
139
|
if (!DatalyrNative) {
|
|
74
|
-
return
|
|
140
|
+
return defaultAvailability;
|
|
75
141
|
}
|
|
76
142
|
|
|
77
143
|
try {
|
|
78
|
-
|
|
144
|
+
const result = await DatalyrNative.getSDKAvailability();
|
|
145
|
+
return {
|
|
146
|
+
...defaultAvailability,
|
|
147
|
+
...result,
|
|
148
|
+
playInstallReferrer: Platform.OS === 'android' && DatalyrPlayInstallReferrer !== null,
|
|
149
|
+
};
|
|
79
150
|
} catch {
|
|
80
|
-
return
|
|
151
|
+
return defaultAvailability;
|
|
81
152
|
}
|
|
82
153
|
};
|
|
83
154
|
|
|
@@ -269,3 +340,60 @@ export const TikTokNativeBridge = {
|
|
|
269
340
|
}
|
|
270
341
|
},
|
|
271
342
|
};
|
|
343
|
+
|
|
344
|
+
// MARK: - Apple Search Ads Bridge (iOS only)
|
|
345
|
+
|
|
346
|
+
export const AppleSearchAdsNativeBridge = {
|
|
347
|
+
/**
|
|
348
|
+
* Get Apple Search Ads attribution data
|
|
349
|
+
* Uses AdServices framework (iOS 14.3+)
|
|
350
|
+
* Returns null if user didn't come from Apple Search Ads or on older iOS
|
|
351
|
+
*/
|
|
352
|
+
async getAttribution(): Promise<AppleSearchAdsAttribution | null> {
|
|
353
|
+
if (!DatalyrNative || Platform.OS !== 'ios') return null;
|
|
354
|
+
|
|
355
|
+
try {
|
|
356
|
+
return await DatalyrNative.getAppleSearchAdsAttribution();
|
|
357
|
+
} catch (error) {
|
|
358
|
+
console.error('[Datalyr/AppleSearchAds] Get attribution failed:', error);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// MARK: - Play Install Referrer Bridge (Android only)
|
|
365
|
+
|
|
366
|
+
export const PlayInstallReferrerNativeBridge = {
|
|
367
|
+
/**
|
|
368
|
+
* Check if Play Install Referrer is available
|
|
369
|
+
* Only available on Android with Google Play Services
|
|
370
|
+
*/
|
|
371
|
+
async isAvailable(): Promise<boolean> {
|
|
372
|
+
if (!DatalyrPlayInstallReferrer || Platform.OS !== 'android') return false;
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
return await DatalyrPlayInstallReferrer.isAvailable();
|
|
376
|
+
} catch {
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Get install referrer data from Google Play
|
|
383
|
+
*
|
|
384
|
+
* Returns UTM parameters, click IDs (gclid, fbclid, ttclid), and timestamps
|
|
385
|
+
* from the Google Play Store referrer.
|
|
386
|
+
*
|
|
387
|
+
* Call this on first app launch to capture install attribution.
|
|
388
|
+
*/
|
|
389
|
+
async getInstallReferrer(): Promise<PlayInstallReferrerData | null> {
|
|
390
|
+
if (!DatalyrPlayInstallReferrer || Platform.OS !== 'android') return null;
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
return await DatalyrPlayInstallReferrer.getInstallReferrer();
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error('[Datalyr/PlayInstallReferrer] Get referrer failed:', error);
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
};
|
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
|
|
3
|
+
// SKAN 4.0 coarse value type
|
|
4
|
+
export type SKANCoarseValue = 'low' | 'medium' | 'high';
|
|
5
|
+
|
|
6
|
+
// SKAN 4.0 conversion result
|
|
7
|
+
export interface SKANConversionResult {
|
|
8
|
+
fineValue: number; // 0-63
|
|
9
|
+
coarseValue: SKANCoarseValue;
|
|
10
|
+
lockWindow: boolean;
|
|
11
|
+
priority: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
interface SKAdNetworkModule {
|
|
4
15
|
updateConversionValue(value: number): Promise<boolean>;
|
|
16
|
+
updatePostbackConversionValue(
|
|
17
|
+
fineValue: number,
|
|
18
|
+
coarseValue: string,
|
|
19
|
+
lockWindow: boolean
|
|
20
|
+
): Promise<boolean>;
|
|
21
|
+
isSKAN4Available(): Promise<boolean>;
|
|
5
22
|
}
|
|
6
23
|
|
|
7
|
-
const { DatalyrSKAdNetwork } = NativeModules as {
|
|
8
|
-
DatalyrSKAdNetwork?: SKAdNetworkModule
|
|
24
|
+
const { DatalyrSKAdNetwork } = NativeModules as {
|
|
25
|
+
DatalyrSKAdNetwork?: SKAdNetworkModule
|
|
9
26
|
};
|
|
10
27
|
|
|
11
28
|
export class SKAdNetworkBridge {
|
|
29
|
+
private static _isSKAN4Available: boolean | null = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* SKAN 3.0 - Update conversion value (0-63)
|
|
33
|
+
* @deprecated Use updatePostbackConversionValue for iOS 16.1+
|
|
34
|
+
*/
|
|
12
35
|
static async updateConversionValue(value: number): Promise<boolean> {
|
|
13
36
|
if (Platform.OS !== 'ios') {
|
|
14
37
|
return false; // Android doesn't support SKAdNetwork
|
|
@@ -29,6 +52,67 @@ export class SKAdNetworkBridge {
|
|
|
29
52
|
}
|
|
30
53
|
}
|
|
31
54
|
|
|
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 async updatePostbackConversionValue(
|
|
60
|
+
result: SKANConversionResult
|
|
61
|
+
): Promise<boolean> {
|
|
62
|
+
if (Platform.OS !== 'ios') {
|
|
63
|
+
return false; // Android doesn't support SKAdNetwork
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!DatalyrSKAdNetwork) {
|
|
67
|
+
console.warn('[Datalyr] SKAdNetwork native module not found. Ensure native bridge is properly configured.');
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const success = await DatalyrSKAdNetwork.updatePostbackConversionValue(
|
|
73
|
+
result.fineValue,
|
|
74
|
+
result.coarseValue,
|
|
75
|
+
result.lockWindow
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const isSKAN4 = await this.isSKAN4Available();
|
|
79
|
+
if (isSKAN4) {
|
|
80
|
+
console.log(`[Datalyr] SKAN 4.0 postback updated: fineValue=${result.fineValue}, coarseValue=${result.coarseValue}, lockWindow=${result.lockWindow}`);
|
|
81
|
+
} else {
|
|
82
|
+
console.log(`[Datalyr] SKAN 3.0 fallback: conversionValue=${result.fineValue}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return success;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.warn('[Datalyr] Failed to update SKAdNetwork postback conversion value:', error);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if SKAN 4.0 is available (iOS 16.1+)
|
|
94
|
+
*/
|
|
95
|
+
static async isSKAN4Available(): Promise<boolean> {
|
|
96
|
+
if (Platform.OS !== 'ios') {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (this._isSKAN4Available !== null) {
|
|
101
|
+
return this._isSKAN4Available;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!DatalyrSKAdNetwork?.isSKAN4Available) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
this._isSKAN4Available = await DatalyrSKAdNetwork.isSKAN4Available();
|
|
110
|
+
return this._isSKAN4Available;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
32
116
|
static isAvailable(): boolean {
|
|
33
117
|
return Platform.OS === 'ios' && !!DatalyrSKAdNetwork;
|
|
34
118
|
}
|