@datalyr/react-native 1.5.0 → 1.6.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 +39 -0
- package/README.md +3 -131
- package/android/build.gradle +0 -7
- package/android/src/main/java/com/datalyr/reactnative/DatalyrNativeModule.java +2 -380
- package/android/src/main/java/com/datalyr/reactnative/DatalyrPackage.java +1 -1
- package/datalyr-react-native.podspec +3 -7
- package/expo-module.config.json +4 -1
- package/ios/DatalyrNativeModule.swift +0 -266
- package/lib/datalyr-sdk.d.ts +1 -4
- package/lib/datalyr-sdk.js +7 -143
- package/lib/http-client.js +2 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/integrations/index.d.ts +3 -4
- package/lib/integrations/index.js +3 -4
- package/lib/native/DatalyrNativeBridge.d.ts +6 -22
- package/lib/native/DatalyrNativeBridge.js +6 -147
- package/lib/native/index.d.ts +1 -1
- package/lib/native/index.js +1 -1
- package/lib/types.d.ts +1 -19
- package/package.json +3 -5
- package/src/datalyr-sdk-expo.ts +6 -141
- package/src/datalyr-sdk.ts +8 -173
- package/src/http-client.ts +2 -2
- package/src/index.ts +1 -1
- package/src/integrations/index.ts +3 -4
- package/src/native/DatalyrNativeBridge.ts +6 -241
- package/src/native/index.ts +0 -2
- package/src/types.ts +2 -25
- package/src/utils-expo.ts +2 -2
- package/ios/DatalyrObjCExceptionCatcher.h +0 -14
- package/ios/DatalyrObjCExceptionCatcher.m +0 -30
- package/lib/integrations/meta-integration.d.ts +0 -77
- package/lib/integrations/meta-integration.js +0 -219
- package/lib/integrations/tiktok-integration.d.ts +0 -83
- package/lib/integrations/tiktok-integration.js +0 -360
- package/src/integrations/meta-integration.ts +0 -239
- package/src/integrations/tiktok-integration.ts +0 -363
|
@@ -7,9 +7,9 @@ Pod::Spec.new do |s|
|
|
|
7
7
|
s.version = package['version']
|
|
8
8
|
s.summary = package['description']
|
|
9
9
|
s.description = <<-DESC
|
|
10
|
-
Datalyr SDK for React Native with
|
|
11
|
-
Provides
|
|
12
|
-
|
|
10
|
+
Datalyr SDK for React Native with server-side attribution tracking.
|
|
11
|
+
Provides event capture, Apple Search Ads attribution, and Play Install
|
|
12
|
+
Referrer support. Conversion routing handled server-side via postback.
|
|
13
13
|
DESC
|
|
14
14
|
s.homepage = package['homepage']
|
|
15
15
|
s.license = package['license']
|
|
@@ -20,12 +20,8 @@ Pod::Spec.new do |s|
|
|
|
20
20
|
s.swift_version = "5.0"
|
|
21
21
|
|
|
22
22
|
s.dependency "ExpoModulesCore"
|
|
23
|
-
s.dependency "FBSDKCoreKit", "~> 18.0"
|
|
24
|
-
s.dependency "TikTokBusinessSDK", "1.6.0"
|
|
25
23
|
|
|
26
|
-
# Disable bitcode (required for TikTok SDK)
|
|
27
24
|
s.pod_target_xcconfig = {
|
|
28
|
-
'ENABLE_BITCODE' => 'NO',
|
|
29
25
|
'DEFINES_MODULE' => 'YES'
|
|
30
26
|
}
|
|
31
27
|
end
|
package/expo-module.config.json
CHANGED
|
@@ -1,283 +1,17 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
|
-
import FBSDKCoreKit
|
|
3
|
-
import TikTokBusinessSDK
|
|
4
2
|
import AdServices
|
|
5
3
|
import AppTrackingTransparency
|
|
6
4
|
import AdSupport
|
|
7
5
|
|
|
8
6
|
public class DatalyrNativeModule: Module {
|
|
9
|
-
private var tiktokInitialized = false
|
|
10
|
-
private var metaInitialized = false
|
|
11
7
|
|
|
12
8
|
public func definition() -> ModuleDefinition {
|
|
13
9
|
Name("DatalyrNative")
|
|
14
10
|
|
|
15
|
-
// MARK: - Meta (Facebook) SDK Methods
|
|
16
|
-
|
|
17
|
-
AsyncFunction("initializeMetaSDK") { (appId: String, clientToken: String?, advertiserTrackingEnabled: Bool, promise: Promise) in
|
|
18
|
-
DispatchQueue.main.async { [weak self] in
|
|
19
|
-
Settings.shared.appID = appId
|
|
20
|
-
|
|
21
|
-
if let token = clientToken, !token.isEmpty {
|
|
22
|
-
Settings.shared.clientToken = token
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
Settings.shared.isAdvertiserTrackingEnabled = advertiserTrackingEnabled
|
|
26
|
-
Settings.shared.isAdvertiserIDCollectionEnabled = advertiserTrackingEnabled
|
|
27
|
-
|
|
28
|
-
var initError: NSError?
|
|
29
|
-
let success = DatalyrObjCExceptionCatcher.tryBlock({
|
|
30
|
-
ApplicationDelegate.shared.application(
|
|
31
|
-
UIApplication.shared,
|
|
32
|
-
didFinishLaunchingWithOptions: nil
|
|
33
|
-
)
|
|
34
|
-
}, error: &initError)
|
|
35
|
-
|
|
36
|
-
if success {
|
|
37
|
-
self?.metaInitialized = true
|
|
38
|
-
promise.resolve(true)
|
|
39
|
-
} else {
|
|
40
|
-
let message = initError?.localizedDescription ?? "Unknown ObjC exception during Meta SDK init"
|
|
41
|
-
promise.reject("meta_init_error", message)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
AsyncFunction("fetchDeferredAppLink") { (promise: Promise) in
|
|
47
|
-
DispatchQueue.main.async {
|
|
48
|
-
AppLinkUtility.fetchDeferredAppLink { url, error in
|
|
49
|
-
if error != nil {
|
|
50
|
-
promise.resolve(nil)
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if let url = url {
|
|
55
|
-
promise.resolve(url.absoluteString)
|
|
56
|
-
} else {
|
|
57
|
-
promise.resolve(nil)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
AsyncFunction("logMetaEvent") { (eventName: String, valueToSum: Double?, parameters: [String: Any]?, promise: Promise) in
|
|
64
|
-
guard self.metaInitialized else {
|
|
65
|
-
promise.reject("meta_not_initialized", "Meta SDK not initialized. Call initializeMetaSDK first.")
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
DispatchQueue.main.async {
|
|
70
|
-
var params: [AppEvents.ParameterName: Any] = [:]
|
|
71
|
-
|
|
72
|
-
if let dict = parameters {
|
|
73
|
-
for (key, value) in dict {
|
|
74
|
-
params[AppEvents.ParameterName(key)] = value
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
var logError: NSError?
|
|
79
|
-
DatalyrObjCExceptionCatcher.tryBlock({
|
|
80
|
-
if let value = valueToSum {
|
|
81
|
-
AppEvents.shared.logEvent(AppEvents.Name(eventName), valueToSum: value, parameters: params)
|
|
82
|
-
} else if params.isEmpty {
|
|
83
|
-
AppEvents.shared.logEvent(AppEvents.Name(eventName))
|
|
84
|
-
} else {
|
|
85
|
-
AppEvents.shared.logEvent(AppEvents.Name(eventName), parameters: params)
|
|
86
|
-
}
|
|
87
|
-
}, error: &logError)
|
|
88
|
-
|
|
89
|
-
if let logError = logError {
|
|
90
|
-
promise.reject("meta_event_error", logError.localizedDescription)
|
|
91
|
-
} else {
|
|
92
|
-
promise.resolve(true)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
AsyncFunction("logMetaPurchase") { (amount: Double, currency: String, parameters: [String: Any]?, promise: Promise) in
|
|
98
|
-
guard self.metaInitialized else {
|
|
99
|
-
promise.reject("meta_not_initialized", "Meta SDK not initialized. Call initializeMetaSDK first.")
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
DispatchQueue.main.async {
|
|
104
|
-
var params: [AppEvents.ParameterName: Any] = [:]
|
|
105
|
-
|
|
106
|
-
if let dict = parameters {
|
|
107
|
-
for (key, value) in dict {
|
|
108
|
-
params[AppEvents.ParameterName(key)] = value
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
var logError: NSError?
|
|
113
|
-
DatalyrObjCExceptionCatcher.tryBlock({
|
|
114
|
-
AppEvents.shared.logPurchase(amount: amount, currency: currency, parameters: params)
|
|
115
|
-
}, error: &logError)
|
|
116
|
-
|
|
117
|
-
if let logError = logError {
|
|
118
|
-
promise.reject("meta_event_error", logError.localizedDescription)
|
|
119
|
-
} else {
|
|
120
|
-
promise.resolve(true)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
AsyncFunction("setMetaUserData") { (userData: [String: Any], promise: Promise) in
|
|
126
|
-
guard self.metaInitialized else {
|
|
127
|
-
promise.reject("meta_not_initialized", "Meta SDK not initialized. Call initializeMetaSDK first.")
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
DispatchQueue.main.async {
|
|
132
|
-
if let email = userData["email"] as? String { AppEvents.shared.setUserData(email, forType: .email) }
|
|
133
|
-
if let firstName = userData["firstName"] as? String { AppEvents.shared.setUserData(firstName, forType: .firstName) }
|
|
134
|
-
if let lastName = userData["lastName"] as? String { AppEvents.shared.setUserData(lastName, forType: .lastName) }
|
|
135
|
-
if let phone = userData["phone"] as? String { AppEvents.shared.setUserData(phone, forType: .phone) }
|
|
136
|
-
if let dateOfBirth = userData["dateOfBirth"] as? String { AppEvents.shared.setUserData(dateOfBirth, forType: .dateOfBirth) }
|
|
137
|
-
if let gender = userData["gender"] as? String { AppEvents.shared.setUserData(gender, forType: .gender) }
|
|
138
|
-
if let city = userData["city"] as? String { AppEvents.shared.setUserData(city, forType: .city) }
|
|
139
|
-
if let state = userData["state"] as? String { AppEvents.shared.setUserData(state, forType: .state) }
|
|
140
|
-
if let zip = userData["zip"] as? String { AppEvents.shared.setUserData(zip, forType: .zip) }
|
|
141
|
-
if let country = userData["country"] as? String { AppEvents.shared.setUserData(country, forType: .country) }
|
|
142
|
-
|
|
143
|
-
promise.resolve(true)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
AsyncFunction("clearMetaUserData") { (promise: Promise) in
|
|
148
|
-
guard self.metaInitialized else {
|
|
149
|
-
promise.reject("meta_not_initialized", "Meta SDK not initialized. Call initializeMetaSDK first.")
|
|
150
|
-
return
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
DispatchQueue.main.async {
|
|
154
|
-
AppEvents.shared.clearUserData()
|
|
155
|
-
promise.resolve(true)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
AsyncFunction("updateMetaTrackingAuthorization") { (enabled: Bool, promise: Promise) in
|
|
160
|
-
guard self.metaInitialized else {
|
|
161
|
-
promise.reject("meta_not_initialized", "Meta SDK not initialized. Call initializeMetaSDK first.")
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
DispatchQueue.main.async {
|
|
166
|
-
Settings.shared.isAdvertiserTrackingEnabled = enabled
|
|
167
|
-
Settings.shared.isAdvertiserIDCollectionEnabled = enabled
|
|
168
|
-
promise.resolve(true)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// MARK: - TikTok SDK Methods
|
|
173
|
-
|
|
174
|
-
AsyncFunction("initializeTikTokSDK") { (appId: String, tiktokAppId: String, accessToken: String?, debug: Bool, promise: Promise) in
|
|
175
|
-
DispatchQueue.main.async { [weak self] in
|
|
176
|
-
guard let token = accessToken, !token.isEmpty else {
|
|
177
|
-
promise.reject("tiktok_init_error", "TikTok accessToken is required. The deprecated init without accessToken has been removed.")
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
let config = TikTokConfig(accessToken: token, appId: appId, tiktokAppId: tiktokAppId)
|
|
182
|
-
|
|
183
|
-
if debug {
|
|
184
|
-
config?.setLogLevel(TikTokLogLevelDebug)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
guard let validConfig = config else {
|
|
188
|
-
promise.reject("tiktok_init_error", "Failed to create TikTok config")
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
var initError: NSError?
|
|
193
|
-
let success = DatalyrObjCExceptionCatcher.tryBlock({
|
|
194
|
-
TikTokBusiness.initializeSdk(validConfig)
|
|
195
|
-
}, error: &initError)
|
|
196
|
-
|
|
197
|
-
if success {
|
|
198
|
-
self?.tiktokInitialized = true
|
|
199
|
-
promise.resolve(true)
|
|
200
|
-
} else {
|
|
201
|
-
let message = initError?.localizedDescription ?? "Unknown ObjC exception during TikTok SDK init"
|
|
202
|
-
promise.reject("tiktok_init_error", message)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
AsyncFunction("trackTikTokEvent") { (eventName: String, eventId: String?, properties: [String: Any]?, promise: Promise) in
|
|
208
|
-
guard self.tiktokInitialized else {
|
|
209
|
-
promise.reject("tiktok_not_initialized", "TikTok SDK not initialized. Call initializeTikTokSDK first.")
|
|
210
|
-
return
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
DispatchQueue.main.async {
|
|
214
|
-
let event: TikTokBaseEvent
|
|
215
|
-
|
|
216
|
-
if let eid = eventId, !eid.isEmpty {
|
|
217
|
-
event = TikTokBaseEvent(eventName: eventName, eventId: eid)
|
|
218
|
-
} else {
|
|
219
|
-
event = TikTokBaseEvent(eventName: eventName)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if let dict = properties {
|
|
223
|
-
for (key, value) in dict {
|
|
224
|
-
event.addProperty(withKey: key, value: value)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
var trackError: NSError?
|
|
229
|
-
DatalyrObjCExceptionCatcher.tryBlock({
|
|
230
|
-
TikTokBusiness.trackTTEvent(event)
|
|
231
|
-
}, error: &trackError)
|
|
232
|
-
|
|
233
|
-
if let trackError = trackError {
|
|
234
|
-
promise.reject("tiktok_event_error", trackError.localizedDescription)
|
|
235
|
-
} else {
|
|
236
|
-
promise.resolve(true)
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
AsyncFunction("identifyTikTokUser") { (externalId: String, externalUserName: String, phoneNumber: String, email: String, promise: Promise) in
|
|
242
|
-
guard self.tiktokInitialized else {
|
|
243
|
-
promise.reject("tiktok_not_initialized", "TikTok SDK not initialized. Call initializeTikTokSDK first.")
|
|
244
|
-
return
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
DispatchQueue.main.async {
|
|
248
|
-
TikTokBusiness.identify(
|
|
249
|
-
withExternalID: externalId.isEmpty ? nil : externalId,
|
|
250
|
-
externalUserName: externalUserName.isEmpty ? nil : externalUserName,
|
|
251
|
-
phoneNumber: phoneNumber.isEmpty ? nil : phoneNumber,
|
|
252
|
-
email: email.isEmpty ? nil : email
|
|
253
|
-
)
|
|
254
|
-
promise.resolve(true)
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
AsyncFunction("logoutTikTok") { (promise: Promise) in
|
|
259
|
-
guard self.tiktokInitialized else {
|
|
260
|
-
promise.reject("tiktok_not_initialized", "TikTok SDK not initialized. Call initializeTikTokSDK first.")
|
|
261
|
-
return
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
DispatchQueue.main.async {
|
|
265
|
-
TikTokBusiness.logout()
|
|
266
|
-
promise.resolve(true)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
AsyncFunction("updateTikTokTrackingAuthorization") { (enabled: Bool, promise: Promise) in
|
|
271
|
-
// TikTok SDK handles ATT automatically, but we track the change
|
|
272
|
-
promise.resolve(true)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
11
|
// MARK: - SDK Availability Check
|
|
276
12
|
|
|
277
13
|
AsyncFunction("getSDKAvailability") { (promise: Promise) in
|
|
278
14
|
promise.resolve([
|
|
279
|
-
"meta": true,
|
|
280
|
-
"tiktok": true,
|
|
281
15
|
"appleSearchAds": true
|
|
282
16
|
])
|
|
283
17
|
}
|
package/lib/datalyr-sdk.d.ts
CHANGED
|
@@ -162,8 +162,6 @@ export declare class DatalyrSDK {
|
|
|
162
162
|
* Get platform integration status
|
|
163
163
|
*/
|
|
164
164
|
getPlatformIntegrationStatus(): {
|
|
165
|
-
meta: boolean;
|
|
166
|
-
tiktok: boolean;
|
|
167
165
|
appleSearchAds: boolean;
|
|
168
166
|
playInstallReferrer: boolean;
|
|
169
167
|
};
|
|
@@ -276,9 +274,8 @@ export declare class Datalyr {
|
|
|
276
274
|
static trackAddPaymentInfo(success?: boolean): Promise<void>;
|
|
277
275
|
static getDeferredAttributionData(): DeferredDeepLinkResult | null;
|
|
278
276
|
static getPlatformIntegrationStatus(): {
|
|
279
|
-
meta: boolean;
|
|
280
|
-
tiktok: boolean;
|
|
281
277
|
appleSearchAds: boolean;
|
|
278
|
+
playInstallReferrer: boolean;
|
|
282
279
|
};
|
|
283
280
|
static getAppleSearchAdsAttribution(): AppleSearchAdsAttribution | null;
|
|
284
281
|
static updateTrackingAuthorization(enabled: boolean): Promise<void>;
|
package/lib/datalyr-sdk.js
CHANGED
|
@@ -7,7 +7,7 @@ import { journeyManager } from './journey';
|
|
|
7
7
|
import { AutoEventsManager } from './auto-events';
|
|
8
8
|
import { ConversionValueEncoder, ConversionTemplates } from './ConversionValueEncoder';
|
|
9
9
|
import { SKAdNetworkBridge } from './native/SKAdNetworkBridge';
|
|
10
|
-
import {
|
|
10
|
+
import { appleSearchAdsIntegration, playInstallReferrerIntegration } from './integrations';
|
|
11
11
|
import { AdvertiserInfoBridge } from './native/DatalyrNativeBridge';
|
|
12
12
|
import { networkStatusManager } from './network-status';
|
|
13
13
|
export class DatalyrSDK {
|
|
@@ -49,7 +49,7 @@ export class DatalyrSDK {
|
|
|
49
49
|
* Initialize the SDK with configuration
|
|
50
50
|
*/
|
|
51
51
|
async initialize(config) {
|
|
52
|
-
var _a
|
|
52
|
+
var _a;
|
|
53
53
|
try {
|
|
54
54
|
debugLog('Initializing Datalyr SDK...', { workspaceId: config.workspaceId });
|
|
55
55
|
// Validate configuration
|
|
@@ -152,22 +152,6 @@ export class DatalyrSDK {
|
|
|
152
152
|
// Google Play Install Referrer (Android only)
|
|
153
153
|
playInstallReferrerIntegration.initialize(),
|
|
154
154
|
];
|
|
155
|
-
// Add Meta initialization if configured
|
|
156
|
-
if ((_b = config.meta) === null || _b === void 0 ? void 0 : _b.appId) {
|
|
157
|
-
platformInitPromises.push(metaIntegration.initialize(config.meta, config.debug).then(async () => {
|
|
158
|
-
// After Meta initializes, fetch deferred deep link
|
|
159
|
-
if (config.enableAttribution !== false) {
|
|
160
|
-
const deferredLink = await metaIntegration.fetchDeferredDeepLink();
|
|
161
|
-
if (deferredLink) {
|
|
162
|
-
await this.handleDeferredDeepLink(deferredLink);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}));
|
|
166
|
-
}
|
|
167
|
-
// Add TikTok initialization if configured
|
|
168
|
-
if (((_c = config.tiktok) === null || _c === void 0 ? void 0 : _c.appId) && ((_d = config.tiktok) === null || _d === void 0 ? void 0 : _d.tiktokAppId)) {
|
|
169
|
-
platformInitPromises.push(tiktokIntegration.initialize(config.tiktok, config.debug));
|
|
170
|
-
}
|
|
171
155
|
// Wait for all platform integrations to complete
|
|
172
156
|
await Promise.all(platformInitPromises);
|
|
173
157
|
// Cache advertiser info (IDFA/GAID, ATT status) once at init to avoid per-event native bridge calls
|
|
@@ -178,8 +162,6 @@ export class DatalyrSDK {
|
|
|
178
162
|
errorLog('Failed to cache advertiser info:', error);
|
|
179
163
|
}
|
|
180
164
|
debugLog('Platform integrations initialized', {
|
|
181
|
-
meta: metaIntegration.isAvailable(),
|
|
182
|
-
tiktok: tiktokIntegration.isAvailable(),
|
|
183
165
|
appleSearchAds: appleSearchAdsIntegration.isAvailable(),
|
|
184
166
|
playInstallReferrer: playInstallReferrerIntegration.isAvailable(),
|
|
185
167
|
});
|
|
@@ -195,7 +177,7 @@ export class DatalyrSDK {
|
|
|
195
177
|
const installData = await attributionManager.trackInstall();
|
|
196
178
|
await this.track('app_install', {
|
|
197
179
|
platform: Platform.OS === 'ios' || Platform.OS === 'android' ? Platform.OS : 'android',
|
|
198
|
-
sdk_version: '1.
|
|
180
|
+
sdk_version: '1.6.0',
|
|
199
181
|
...installData,
|
|
200
182
|
});
|
|
201
183
|
}
|
|
@@ -287,28 +269,6 @@ export class DatalyrSDK {
|
|
|
287
269
|
const dateOfBirth = ((properties === null || properties === void 0 ? void 0 : properties.date_of_birth) || (properties === null || properties === void 0 ? void 0 : properties.dob) || (properties === null || properties === void 0 ? void 0 : properties.birthday));
|
|
288
270
|
const gender = properties === null || properties === void 0 ? void 0 : properties.gender;
|
|
289
271
|
const city = properties === null || properties === void 0 ? void 0 : properties.city;
|
|
290
|
-
const state = properties === null || properties === void 0 ? void 0 : properties.state;
|
|
291
|
-
const zip = ((properties === null || properties === void 0 ? void 0 : properties.zip) || (properties === null || properties === void 0 ? void 0 : properties.postal_code) || (properties === null || properties === void 0 ? void 0 : properties.zipcode));
|
|
292
|
-
const country = properties === null || properties === void 0 ? void 0 : properties.country;
|
|
293
|
-
// Meta Advanced Matching
|
|
294
|
-
if (metaIntegration.isAvailable()) {
|
|
295
|
-
metaIntegration.setUserData({
|
|
296
|
-
email,
|
|
297
|
-
firstName,
|
|
298
|
-
lastName,
|
|
299
|
-
phone,
|
|
300
|
-
dateOfBirth,
|
|
301
|
-
gender,
|
|
302
|
-
city,
|
|
303
|
-
state,
|
|
304
|
-
zip,
|
|
305
|
-
country,
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
// TikTok identification
|
|
309
|
-
if (tiktokIntegration.isAvailable()) {
|
|
310
|
-
tiktokIntegration.identify(email, phone, userId);
|
|
311
|
-
}
|
|
312
272
|
}
|
|
313
273
|
catch (error) {
|
|
314
274
|
errorLog('Error identifying user:', error);
|
|
@@ -483,10 +443,6 @@ export class DatalyrSDK {
|
|
|
483
443
|
await Storage.removeItem(STORAGE_KEYS.USER_PROPERTIES);
|
|
484
444
|
// Generate new session
|
|
485
445
|
this.state.sessionId = await getOrCreateSessionId();
|
|
486
|
-
// Clear user data from platform SDKs
|
|
487
|
-
if (metaIntegration.isAvailable()) {
|
|
488
|
-
metaIntegration.clearUserData();
|
|
489
|
-
}
|
|
490
446
|
debugLog('User data reset completed');
|
|
491
447
|
}
|
|
492
448
|
catch (error) {
|
|
@@ -632,14 +588,6 @@ export class DatalyrSDK {
|
|
|
632
588
|
if (productId)
|
|
633
589
|
properties.product_id = productId;
|
|
634
590
|
await this.trackWithSKAdNetwork('purchase', properties);
|
|
635
|
-
// Forward to Meta if available
|
|
636
|
-
if (metaIntegration.isAvailable()) {
|
|
637
|
-
metaIntegration.logPurchase(value, currency, { fb_content_id: productId });
|
|
638
|
-
}
|
|
639
|
-
// Forward to TikTok if available
|
|
640
|
-
if (tiktokIntegration.isAvailable()) {
|
|
641
|
-
tiktokIntegration.logPurchase(value, currency, productId, 'product');
|
|
642
|
-
}
|
|
643
591
|
}
|
|
644
592
|
/**
|
|
645
593
|
* Track subscription with automatic revenue encoding and platform forwarding
|
|
@@ -649,14 +597,6 @@ export class DatalyrSDK {
|
|
|
649
597
|
if (plan)
|
|
650
598
|
properties.plan = plan;
|
|
651
599
|
await this.trackWithSKAdNetwork('subscribe', properties);
|
|
652
|
-
// Forward to Meta if available
|
|
653
|
-
if (metaIntegration.isAvailable()) {
|
|
654
|
-
metaIntegration.logEvent('Subscribe', value, { subscription_plan: plan });
|
|
655
|
-
}
|
|
656
|
-
// Forward to TikTok if available
|
|
657
|
-
if (tiktokIntegration.isAvailable()) {
|
|
658
|
-
tiktokIntegration.logSubscription(value, currency, plan);
|
|
659
|
-
}
|
|
660
600
|
}
|
|
661
601
|
// MARK: - Standard E-commerce Events
|
|
662
602
|
/**
|
|
@@ -669,18 +609,6 @@ export class DatalyrSDK {
|
|
|
669
609
|
if (productName)
|
|
670
610
|
properties.product_name = productName;
|
|
671
611
|
await this.trackWithSKAdNetwork('add_to_cart', properties);
|
|
672
|
-
// Forward to Meta
|
|
673
|
-
if (metaIntegration.isAvailable()) {
|
|
674
|
-
metaIntegration.logEvent('AddToCart', value, {
|
|
675
|
-
currency,
|
|
676
|
-
content_ids: productId ? [productId] : undefined,
|
|
677
|
-
content_name: productName,
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
// Forward to TikTok
|
|
681
|
-
if (tiktokIntegration.isAvailable()) {
|
|
682
|
-
tiktokIntegration.logAddToCart(value, currency, productId, 'product');
|
|
683
|
-
}
|
|
684
612
|
}
|
|
685
613
|
/**
|
|
686
614
|
* Track view content/product event
|
|
@@ -696,19 +624,6 @@ export class DatalyrSDK {
|
|
|
696
624
|
if (currency)
|
|
697
625
|
properties.currency = currency;
|
|
698
626
|
await this.track('view_content', properties);
|
|
699
|
-
// Forward to Meta
|
|
700
|
-
if (metaIntegration.isAvailable()) {
|
|
701
|
-
metaIntegration.logEvent('ViewContent', value, {
|
|
702
|
-
content_ids: contentId ? [contentId] : undefined,
|
|
703
|
-
content_name: contentName,
|
|
704
|
-
content_type: contentType,
|
|
705
|
-
currency,
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
// Forward to TikTok
|
|
709
|
-
if (tiktokIntegration.isAvailable()) {
|
|
710
|
-
tiktokIntegration.logViewContent(contentId, contentName, contentType);
|
|
711
|
-
}
|
|
712
627
|
}
|
|
713
628
|
/**
|
|
714
629
|
* Track initiate checkout event
|
|
@@ -720,18 +635,6 @@ export class DatalyrSDK {
|
|
|
720
635
|
if (productIds)
|
|
721
636
|
properties.product_ids = productIds;
|
|
722
637
|
await this.trackWithSKAdNetwork('initiate_checkout', properties);
|
|
723
|
-
// Forward to Meta
|
|
724
|
-
if (metaIntegration.isAvailable()) {
|
|
725
|
-
metaIntegration.logEvent('InitiateCheckout', value, {
|
|
726
|
-
currency,
|
|
727
|
-
num_items: numItems,
|
|
728
|
-
content_ids: productIds,
|
|
729
|
-
});
|
|
730
|
-
}
|
|
731
|
-
// Forward to TikTok
|
|
732
|
-
if (tiktokIntegration.isAvailable()) {
|
|
733
|
-
tiktokIntegration.logInitiateCheckout(value, currency, numItems);
|
|
734
|
-
}
|
|
735
638
|
}
|
|
736
639
|
/**
|
|
737
640
|
* Track complete registration event
|
|
@@ -741,14 +644,6 @@ export class DatalyrSDK {
|
|
|
741
644
|
if (method)
|
|
742
645
|
properties.method = method;
|
|
743
646
|
await this.trackWithSKAdNetwork('complete_registration', properties);
|
|
744
|
-
// Forward to Meta
|
|
745
|
-
if (metaIntegration.isAvailable()) {
|
|
746
|
-
metaIntegration.logEvent('CompleteRegistration', undefined, { registration_method: method });
|
|
747
|
-
}
|
|
748
|
-
// Forward to TikTok
|
|
749
|
-
if (tiktokIntegration.isAvailable()) {
|
|
750
|
-
tiktokIntegration.logCompleteRegistration(method);
|
|
751
|
-
}
|
|
752
647
|
}
|
|
753
648
|
/**
|
|
754
649
|
* Track search event
|
|
@@ -758,17 +653,6 @@ export class DatalyrSDK {
|
|
|
758
653
|
if (resultIds)
|
|
759
654
|
properties.result_ids = resultIds;
|
|
760
655
|
await this.track('search', properties);
|
|
761
|
-
// Forward to Meta
|
|
762
|
-
if (metaIntegration.isAvailable()) {
|
|
763
|
-
metaIntegration.logEvent('Search', undefined, {
|
|
764
|
-
search_string: query,
|
|
765
|
-
content_ids: resultIds,
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
// Forward to TikTok
|
|
769
|
-
if (tiktokIntegration.isAvailable()) {
|
|
770
|
-
tiktokIntegration.logSearch(query);
|
|
771
|
-
}
|
|
772
656
|
}
|
|
773
657
|
/**
|
|
774
658
|
* Track lead/contact form submission
|
|
@@ -780,43 +664,25 @@ export class DatalyrSDK {
|
|
|
780
664
|
if (currency)
|
|
781
665
|
properties.currency = currency;
|
|
782
666
|
await this.trackWithSKAdNetwork('lead', properties);
|
|
783
|
-
// Forward to Meta
|
|
784
|
-
if (metaIntegration.isAvailable()) {
|
|
785
|
-
metaIntegration.logEvent('Lead', value, { currency });
|
|
786
|
-
}
|
|
787
|
-
// Forward to TikTok
|
|
788
|
-
if (tiktokIntegration.isAvailable()) {
|
|
789
|
-
tiktokIntegration.logLead(value, currency);
|
|
790
|
-
}
|
|
791
667
|
}
|
|
792
668
|
/**
|
|
793
669
|
* Track add payment info event
|
|
794
670
|
*/
|
|
795
671
|
async trackAddPaymentInfo(success = true) {
|
|
796
672
|
await this.track('add_payment_info', { success });
|
|
797
|
-
// Forward to Meta
|
|
798
|
-
if (metaIntegration.isAvailable()) {
|
|
799
|
-
metaIntegration.logEvent('AddPaymentInfo', undefined, { success: success ? 1 : 0 });
|
|
800
|
-
}
|
|
801
|
-
// Forward to TikTok
|
|
802
|
-
if (tiktokIntegration.isAvailable()) {
|
|
803
|
-
tiktokIntegration.logAddPaymentInfo(success);
|
|
804
|
-
}
|
|
805
673
|
}
|
|
806
674
|
// MARK: - Platform Integration Methods
|
|
807
675
|
/**
|
|
808
676
|
* Get deferred attribution data from platform SDKs
|
|
809
677
|
*/
|
|
810
678
|
getDeferredAttributionData() {
|
|
811
|
-
return
|
|
679
|
+
return null;
|
|
812
680
|
}
|
|
813
681
|
/**
|
|
814
682
|
* Get platform integration status
|
|
815
683
|
*/
|
|
816
684
|
getPlatformIntegrationStatus() {
|
|
817
685
|
return {
|
|
818
|
-
meta: metaIntegration.isAvailable(),
|
|
819
|
-
tiktok: tiktokIntegration.isAvailable(),
|
|
820
686
|
appleSearchAds: appleSearchAdsIntegration.isAvailable(),
|
|
821
687
|
playInstallReferrer: playInstallReferrerIntegration.isAvailable(),
|
|
822
688
|
};
|
|
@@ -845,8 +711,6 @@ export class DatalyrSDK {
|
|
|
845
711
|
errorLog('SDK not initialized. Call initialize() first.');
|
|
846
712
|
return;
|
|
847
713
|
}
|
|
848
|
-
metaIntegration.updateTrackingAuthorization(enabled);
|
|
849
|
-
tiktokIntegration.updateTrackingAuthorization(enabled);
|
|
850
714
|
// Refresh cached advertiser info after ATT status change
|
|
851
715
|
try {
|
|
852
716
|
this.cachedAdvertiserInfo = await AdvertiserInfoBridge.getAdvertiserInfo();
|
|
@@ -957,8 +821,8 @@ export class DatalyrSDK {
|
|
|
957
821
|
carrier: deviceInfo.carrier,
|
|
958
822
|
network_type: getNetworkType(),
|
|
959
823
|
timestamp: Date.now(),
|
|
960
|
-
sdk_version: '1.
|
|
961
|
-
// Advertiser data (IDFA/GAID, ATT status) for
|
|
824
|
+
sdk_version: '1.6.0',
|
|
825
|
+
// Advertiser data (IDFA/GAID, ATT status) for server-side postback
|
|
962
826
|
...(advertiserInfo ? {
|
|
963
827
|
idfa: advertiserInfo.idfa,
|
|
964
828
|
idfv: advertiserInfo.idfv,
|
|
@@ -1218,7 +1082,7 @@ export class Datalyr {
|
|
|
1218
1082
|
static updateAutoEventsConfig(config) {
|
|
1219
1083
|
datalyr.updateAutoEventsConfig(config);
|
|
1220
1084
|
}
|
|
1221
|
-
// Standard e-commerce events
|
|
1085
|
+
// Standard e-commerce events
|
|
1222
1086
|
static async trackAddToCart(value, currency = 'USD', productId, productName) {
|
|
1223
1087
|
await datalyr.trackAddToCart(value, currency, productId, productName);
|
|
1224
1088
|
}
|
package/lib/http-client.js
CHANGED
|
@@ -45,7 +45,7 @@ export class HttpClient {
|
|
|
45
45
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
46
46
|
const headers = {
|
|
47
47
|
'Content-Type': 'application/json',
|
|
48
|
-
'User-Agent': `@datalyr/react-native/1.
|
|
48
|
+
'User-Agent': `@datalyr/react-native/1.5.0`,
|
|
49
49
|
};
|
|
50
50
|
// Server-side tracking uses X-API-Key header
|
|
51
51
|
if (this.config.useServerTracking !== false) {
|
|
@@ -152,7 +152,7 @@ export class HttpClient {
|
|
|
152
152
|
},
|
|
153
153
|
context: {
|
|
154
154
|
library: '@datalyr/react-native',
|
|
155
|
-
version: '1.
|
|
155
|
+
version: '1.5.0',
|
|
156
156
|
source: 'mobile_app', // Explicitly set source for mobile
|
|
157
157
|
userProperties: payload.userProperties,
|
|
158
158
|
},
|
package/lib/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export * from './event-queue';
|
|
|
12
12
|
export { DatalyrSDK };
|
|
13
13
|
export { ConversionValueEncoder, ConversionTemplates } from './ConversionValueEncoder';
|
|
14
14
|
export { SKAdNetworkBridge } from './native/SKAdNetworkBridge';
|
|
15
|
-
export {
|
|
15
|
+
export { appleSearchAdsIntegration, playInstallReferrerIntegration } from './integrations';
|
|
16
16
|
export { networkStatusManager } from './network-status';
|
|
17
17
|
export type { NetworkState, NetworkStateListener } from './network-status';
|
|
18
18
|
export type { AppleSearchAdsAttribution } from './native/DatalyrNativeBridge';
|
package/lib/index.js
CHANGED
|
@@ -20,7 +20,7 @@ export { DatalyrSDK };
|
|
|
20
20
|
export { ConversionValueEncoder, ConversionTemplates } from './ConversionValueEncoder';
|
|
21
21
|
export { SKAdNetworkBridge } from './native/SKAdNetworkBridge';
|
|
22
22
|
// Export platform integrations
|
|
23
|
-
export {
|
|
23
|
+
export { appleSearchAdsIntegration, playInstallReferrerIntegration } from './integrations';
|
|
24
24
|
// Export network status manager
|
|
25
25
|
export { networkStatusManager } from './network-status';
|
|
26
26
|
// Default export for compatibility
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Platform
|
|
3
|
-
*
|
|
2
|
+
* Platform Integrations
|
|
3
|
+
* Apple Search Ads and Google Play Install Referrer
|
|
4
|
+
* Conversion routing to Meta/TikTok/Google is handled server-side via postback.
|
|
4
5
|
*/
|
|
5
|
-
export { MetaIntegration, metaIntegration } from './meta-integration';
|
|
6
|
-
export { TikTokIntegration, tiktokIntegration } from './tiktok-integration';
|
|
7
6
|
export { AppleSearchAdsIntegration, appleSearchAdsIntegration } from './apple-search-ads-integration';
|
|
8
7
|
export { playInstallReferrerIntegration } from './play-install-referrer';
|
|
9
8
|
export type { PlayInstallReferrer } from './play-install-referrer';
|