@datalyr/react-native 1.1.1 → 1.2.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +24 -141
  2. package/LICENSE +21 -0
  3. package/README.md +405 -217
  4. package/datalyr-react-native.podspec +31 -0
  5. package/ios/DatalyrNative.m +70 -0
  6. package/ios/DatalyrNative.swift +275 -0
  7. package/ios/DatalyrSKAdNetwork.m +26 -0
  8. package/lib/datalyr-sdk.d.ts +64 -3
  9. package/lib/datalyr-sdk.js +322 -3
  10. package/lib/index.d.ts +1 -0
  11. package/lib/index.js +4 -2
  12. package/lib/integrations/index.d.ts +6 -0
  13. package/lib/integrations/index.js +6 -0
  14. package/lib/integrations/meta-integration.d.ts +76 -0
  15. package/lib/integrations/meta-integration.js +218 -0
  16. package/lib/integrations/tiktok-integration.d.ts +82 -0
  17. package/lib/integrations/tiktok-integration.js +356 -0
  18. package/lib/native/DatalyrNativeBridge.d.ts +31 -0
  19. package/lib/native/DatalyrNativeBridge.js +168 -0
  20. package/lib/native/index.d.ts +5 -0
  21. package/lib/native/index.js +5 -0
  22. package/lib/types.d.ts +29 -0
  23. package/package.json +10 -5
  24. package/src/datalyr-sdk-expo.ts +957 -0
  25. package/src/datalyr-sdk.ts +419 -19
  26. package/src/expo.ts +38 -18
  27. package/src/index.ts +5 -2
  28. package/src/integrations/index.ts +7 -0
  29. package/src/integrations/meta-integration.ts +238 -0
  30. package/src/integrations/tiktok-integration.ts +360 -0
  31. package/src/native/DatalyrNativeBridge.ts +271 -0
  32. package/src/native/index.ts +11 -0
  33. package/src/types.ts +39 -0
  34. package/src/utils-expo.ts +25 -3
  35. package/src/utils-interface.ts +38 -0
  36. package/EXPO_INSTALL.md +0 -297
  37. package/INSTALL.md +0 -402
  38. package/examples/attribution-example.tsx +0 -377
  39. package/examples/auto-events-example.tsx +0 -403
  40. package/examples/example.tsx +0 -250
  41. package/examples/skadnetwork-example.tsx +0 -380
  42. package/examples/test-implementation.tsx +0 -163
@@ -0,0 +1,31 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "datalyr-react-native"
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = <<-DESC
10
+ Datalyr SDK for React Native with bundled Meta (Facebook) and TikTok SDKs.
11
+ Provides deferred deep linking, event forwarding, and advanced attribution
12
+ without requiring users to install additional packages.
13
+ DESC
14
+ s.homepage = package['homepage']
15
+ s.license = package['license']
16
+ s.author = package['author']
17
+ s.platform = :ios, "13.0"
18
+ s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
19
+ s.source_files = "ios/**/*.{h,m,swift}"
20
+ s.swift_version = "5.0"
21
+
22
+ s.dependency "React-Core"
23
+ s.dependency "FBSDKCoreKit", "~> 17.0"
24
+ s.dependency "TikTokBusinessSDK", "~> 1.4"
25
+
26
+ # Disable bitcode (required for TikTok SDK)
27
+ s.pod_target_xcconfig = {
28
+ 'ENABLE_BITCODE' => 'NO',
29
+ 'DEFINES_MODULE' => 'YES'
30
+ }
31
+ end
@@ -0,0 +1,70 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(DatalyrNative, NSObject)
4
+
5
+ // Meta SDK Methods
6
+ RCT_EXTERN_METHOD(initializeMetaSDK:(NSString *)appId
7
+ clientToken:(NSString *)clientToken
8
+ advertiserTrackingEnabled:(BOOL)advertiserTrackingEnabled
9
+ resolve:(RCTPromiseResolveBlock)resolve
10
+ reject:(RCTPromiseRejectBlock)reject)
11
+
12
+ RCT_EXTERN_METHOD(fetchDeferredAppLink:(RCTPromiseResolveBlock)resolve
13
+ reject:(RCTPromiseRejectBlock)reject)
14
+
15
+ RCT_EXTERN_METHOD(logMetaEvent:(NSString *)eventName
16
+ valueToSum:(NSNumber *)valueToSum
17
+ parameters:(NSDictionary *)parameters
18
+ resolve:(RCTPromiseResolveBlock)resolve
19
+ reject:(RCTPromiseRejectBlock)reject)
20
+
21
+ RCT_EXTERN_METHOD(logMetaPurchase:(double)amount
22
+ currency:(NSString *)currency
23
+ parameters:(NSDictionary *)parameters
24
+ resolve:(RCTPromiseResolveBlock)resolve
25
+ reject:(RCTPromiseRejectBlock)reject)
26
+
27
+ RCT_EXTERN_METHOD(setMetaUserData:(NSDictionary *)userData
28
+ resolve:(RCTPromiseResolveBlock)resolve
29
+ reject:(RCTPromiseRejectBlock)reject)
30
+
31
+ RCT_EXTERN_METHOD(clearMetaUserData:(RCTPromiseResolveBlock)resolve
32
+ reject:(RCTPromiseRejectBlock)reject)
33
+
34
+ RCT_EXTERN_METHOD(updateMetaTrackingAuthorization:(BOOL)enabled
35
+ resolve:(RCTPromiseResolveBlock)resolve
36
+ reject:(RCTPromiseRejectBlock)reject)
37
+
38
+ // TikTok SDK Methods
39
+ RCT_EXTERN_METHOD(initializeTikTokSDK:(NSString *)appId
40
+ tiktokAppId:(NSString *)tiktokAppId
41
+ accessToken:(NSString *)accessToken
42
+ debug:(BOOL)debug
43
+ resolve:(RCTPromiseResolveBlock)resolve
44
+ reject:(RCTPromiseRejectBlock)reject)
45
+
46
+ RCT_EXTERN_METHOD(trackTikTokEvent:(NSString *)eventName
47
+ eventId:(NSString *)eventId
48
+ properties:(NSDictionary *)properties
49
+ resolve:(RCTPromiseResolveBlock)resolve
50
+ reject:(RCTPromiseRejectBlock)reject)
51
+
52
+ RCT_EXTERN_METHOD(identifyTikTokUser:(NSString *)externalId
53
+ externalUserName:(NSString *)externalUserName
54
+ phoneNumber:(NSString *)phoneNumber
55
+ email:(NSString *)email
56
+ resolve:(RCTPromiseResolveBlock)resolve
57
+ reject:(RCTPromiseRejectBlock)reject)
58
+
59
+ RCT_EXTERN_METHOD(logoutTikTok:(RCTPromiseResolveBlock)resolve
60
+ reject:(RCTPromiseRejectBlock)reject)
61
+
62
+ RCT_EXTERN_METHOD(updateTikTokTrackingAuthorization:(BOOL)enabled
63
+ resolve:(RCTPromiseResolveBlock)resolve
64
+ reject:(RCTPromiseRejectBlock)reject)
65
+
66
+ // SDK Availability Check
67
+ RCT_EXTERN_METHOD(getSDKAvailability:(RCTPromiseResolveBlock)resolve
68
+ reject:(RCTPromiseRejectBlock)reject)
69
+
70
+ @end
@@ -0,0 +1,275 @@
1
+ import Foundation
2
+ import FBSDKCoreKit
3
+ import TikTokBusinessSDK
4
+
5
+ @objc(DatalyrNative)
6
+ class DatalyrNative: NSObject {
7
+
8
+ @objc static func requiresMainQueueSetup() -> Bool {
9
+ return false
10
+ }
11
+
12
+ // MARK: - Meta (Facebook) SDK Methods
13
+
14
+ @objc func initializeMetaSDK(
15
+ _ appId: String,
16
+ clientToken: String?,
17
+ advertiserTrackingEnabled: Bool,
18
+ resolve: @escaping RCTPromiseResolveBlock,
19
+ reject: @escaping RCTPromiseRejectBlock
20
+ ) {
21
+ DispatchQueue.main.async {
22
+ Settings.shared.appID = appId
23
+
24
+ if let token = clientToken, !token.isEmpty {
25
+ Settings.shared.clientToken = token
26
+ }
27
+
28
+ Settings.shared.isAdvertiserTrackingEnabled = advertiserTrackingEnabled
29
+ Settings.shared.isAdvertiserIDCollectionEnabled = advertiserTrackingEnabled
30
+
31
+ ApplicationDelegate.shared.application(
32
+ UIApplication.shared,
33
+ didFinishLaunchingWithOptions: nil
34
+ )
35
+
36
+ resolve(true)
37
+ }
38
+ }
39
+
40
+ @objc func fetchDeferredAppLink(
41
+ _ resolve: @escaping RCTPromiseResolveBlock,
42
+ reject: @escaping RCTPromiseRejectBlock
43
+ ) {
44
+ AppLinkUtility.fetchDeferredAppLink { url, error in
45
+ if error != nil {
46
+ // Don't reject - deferred deep link not available is expected in many cases
47
+ // Error is normal when no deferred link exists
48
+ resolve(nil)
49
+ return
50
+ }
51
+
52
+ if let url = url {
53
+ resolve(url.absoluteString)
54
+ } else {
55
+ resolve(nil)
56
+ }
57
+ }
58
+ }
59
+
60
+ @objc func logMetaEvent(
61
+ _ eventName: String,
62
+ valueToSum: NSNumber?,
63
+ parameters: NSDictionary?,
64
+ resolve: @escaping RCTPromiseResolveBlock,
65
+ reject: @escaping RCTPromiseRejectBlock
66
+ ) {
67
+ var params: [AppEvents.ParameterName: Any] = [:]
68
+
69
+ if let dict = parameters as? [String: Any] {
70
+ for (key, value) in dict {
71
+ params[AppEvents.ParameterName(key)] = value
72
+ }
73
+ }
74
+
75
+ if let value = valueToSum?.doubleValue {
76
+ AppEvents.shared.logEvent(AppEvents.Name(eventName), valueToSum: value, parameters: params)
77
+ } else if params.isEmpty {
78
+ AppEvents.shared.logEvent(AppEvents.Name(eventName))
79
+ } else {
80
+ AppEvents.shared.logEvent(AppEvents.Name(eventName), parameters: params)
81
+ }
82
+
83
+ resolve(true)
84
+ }
85
+
86
+ @objc func logMetaPurchase(
87
+ _ amount: Double,
88
+ currency: String,
89
+ parameters: NSDictionary?,
90
+ resolve: @escaping RCTPromiseResolveBlock,
91
+ reject: @escaping RCTPromiseRejectBlock
92
+ ) {
93
+ var params: [AppEvents.ParameterName: Any] = [:]
94
+
95
+ if let dict = parameters as? [String: Any] {
96
+ for (key, value) in dict {
97
+ params[AppEvents.ParameterName(key)] = value
98
+ }
99
+ }
100
+
101
+ AppEvents.shared.logPurchase(amount: amount, currency: currency, parameters: params)
102
+ resolve(true)
103
+ }
104
+
105
+ @objc func setMetaUserData(
106
+ _ userData: NSDictionary,
107
+ resolve: @escaping RCTPromiseResolveBlock,
108
+ reject: @escaping RCTPromiseRejectBlock
109
+ ) {
110
+ AppEvents.shared.setUserData(
111
+ userData["email"] as? String,
112
+ forType: .email
113
+ )
114
+ AppEvents.shared.setUserData(
115
+ userData["firstName"] as? String,
116
+ forType: .firstName
117
+ )
118
+ AppEvents.shared.setUserData(
119
+ userData["lastName"] as? String,
120
+ forType: .lastName
121
+ )
122
+ AppEvents.shared.setUserData(
123
+ userData["phone"] as? String,
124
+ forType: .phone
125
+ )
126
+ AppEvents.shared.setUserData(
127
+ userData["dateOfBirth"] as? String,
128
+ forType: .dateOfBirth
129
+ )
130
+ AppEvents.shared.setUserData(
131
+ userData["gender"] as? String,
132
+ forType: .gender
133
+ )
134
+ AppEvents.shared.setUserData(
135
+ userData["city"] as? String,
136
+ forType: .city
137
+ )
138
+ AppEvents.shared.setUserData(
139
+ userData["state"] as? String,
140
+ forType: .state
141
+ )
142
+ AppEvents.shared.setUserData(
143
+ userData["zip"] as? String,
144
+ forType: .zip
145
+ )
146
+ AppEvents.shared.setUserData(
147
+ userData["country"] as? String,
148
+ forType: .country
149
+ )
150
+
151
+ resolve(true)
152
+ }
153
+
154
+ @objc func clearMetaUserData(
155
+ _ resolve: @escaping RCTPromiseResolveBlock,
156
+ reject: @escaping RCTPromiseRejectBlock
157
+ ) {
158
+ AppEvents.shared.clearUserData()
159
+ resolve(true)
160
+ }
161
+
162
+ @objc func updateMetaTrackingAuthorization(
163
+ _ enabled: Bool,
164
+ resolve: @escaping RCTPromiseResolveBlock,
165
+ reject: @escaping RCTPromiseRejectBlock
166
+ ) {
167
+ Settings.shared.isAdvertiserTrackingEnabled = enabled
168
+ Settings.shared.isAdvertiserIDCollectionEnabled = enabled
169
+ resolve(true)
170
+ }
171
+
172
+ // MARK: - TikTok SDK Methods
173
+
174
+ @objc func initializeTikTokSDK(
175
+ _ appId: String,
176
+ tiktokAppId: String,
177
+ accessToken: String?,
178
+ debug: Bool,
179
+ resolve: @escaping RCTPromiseResolveBlock,
180
+ reject: @escaping RCTPromiseRejectBlock
181
+ ) {
182
+ DispatchQueue.main.async {
183
+ let config = TikTokConfig(appId: appId, tiktokAppId: tiktokAppId)
184
+
185
+ if let token = accessToken, !token.isEmpty {
186
+ config?.accessToken = token
187
+ }
188
+
189
+ if debug {
190
+ config?.setLogLevel(.debug)
191
+ }
192
+
193
+ if let validConfig = config {
194
+ TikTokBusiness.initializeSdk(validConfig)
195
+ resolve(true)
196
+ } else {
197
+ reject("tiktok_init_error", "Failed to create TikTok config", nil)
198
+ }
199
+ }
200
+ }
201
+
202
+ @objc func trackTikTokEvent(
203
+ _ eventName: String,
204
+ eventId: String?,
205
+ properties: NSDictionary?,
206
+ resolve: @escaping RCTPromiseResolveBlock,
207
+ reject: @escaping RCTPromiseRejectBlock
208
+ ) {
209
+ // Use TikTokBaseEvent for modern API (trackEvent methods are deprecated)
210
+ let event: TikTokBaseEvent
211
+
212
+ if let eid = eventId, !eid.isEmpty {
213
+ event = TikTokBaseEvent(eventName: eventName, eventId: eid)
214
+ } else {
215
+ event = TikTokBaseEvent(eventName: eventName)
216
+ }
217
+
218
+ // Add properties to the event
219
+ if let dict = properties as? [String: Any] {
220
+ for (key, value) in dict {
221
+ event.addProperty(withKey: key, value: value)
222
+ }
223
+ }
224
+
225
+ TikTokBusiness.trackTTEvent(event)
226
+ resolve(true)
227
+ }
228
+
229
+ @objc func identifyTikTokUser(
230
+ _ externalId: String,
231
+ externalUserName: String,
232
+ phoneNumber: String,
233
+ email: String,
234
+ resolve: @escaping RCTPromiseResolveBlock,
235
+ reject: @escaping RCTPromiseRejectBlock
236
+ ) {
237
+ // Method signature: identifyWithExternalID:externalUserName:phoneNumber:email:
238
+ TikTokBusiness.identify(
239
+ withExternalID: externalId.isEmpty ? nil : externalId,
240
+ externalUserName: externalUserName.isEmpty ? nil : externalUserName,
241
+ phoneNumber: phoneNumber.isEmpty ? nil : phoneNumber,
242
+ email: email.isEmpty ? nil : email
243
+ )
244
+ resolve(true)
245
+ }
246
+
247
+ @objc func logoutTikTok(
248
+ _ resolve: @escaping RCTPromiseResolveBlock,
249
+ reject: @escaping RCTPromiseRejectBlock
250
+ ) {
251
+ TikTokBusiness.logout()
252
+ resolve(true)
253
+ }
254
+
255
+ @objc func updateTikTokTrackingAuthorization(
256
+ _ enabled: Bool,
257
+ resolve: @escaping RCTPromiseResolveBlock,
258
+ reject: @escaping RCTPromiseRejectBlock
259
+ ) {
260
+ // TikTok SDK handles ATT automatically, but we track the change
261
+ resolve(true)
262
+ }
263
+
264
+ // MARK: - SDK Availability Check
265
+
266
+ @objc func getSDKAvailability(
267
+ _ resolve: @escaping RCTPromiseResolveBlock,
268
+ reject: @escaping RCTPromiseRejectBlock
269
+ ) {
270
+ resolve([
271
+ "meta": true,
272
+ "tiktok": true
273
+ ])
274
+ }
275
+ }
@@ -0,0 +1,26 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <StoreKit/StoreKit.h>
3
+
4
+ @interface DatalyrSKAdNetwork : NSObject <RCTBridgeModule>
5
+ @end
6
+
7
+ @implementation DatalyrSKAdNetwork
8
+
9
+ RCT_EXPORT_MODULE();
10
+
11
+ RCT_EXPORT_METHOD(updateConversionValue:(NSInteger)value
12
+ resolve:(RCTPromiseResolveBlock)resolve
13
+ reject:(RCTPromiseRejectBlock)reject) {
14
+ if (@available(iOS 14.0, *)) {
15
+ @try {
16
+ [SKAdNetwork updateConversionValue:value];
17
+ resolve(@(YES));
18
+ } @catch (NSException *exception) {
19
+ reject(@"skadnetwork_error", exception.reason, nil);
20
+ }
21
+ } else {
22
+ reject(@"ios_version_error", @"SKAdNetwork requires iOS 14.0+", nil);
23
+ }
24
+ }
25
+
26
+ @end
@@ -1,4 +1,4 @@
1
- import { DatalyrConfig, EventData, UserProperties, AutoEventConfig } from './types';
1
+ import { DatalyrConfig, EventData, UserProperties, AutoEventConfig, DeferredDeepLinkResult } from './types';
2
2
  import { AttributionData } from './attribution';
3
3
  import { SessionData } from './auto-events';
4
4
  export declare class DatalyrSDK {
@@ -93,13 +93,61 @@ export declare class DatalyrSDK {
93
93
  */
94
94
  trackWithSKAdNetwork(event: string, properties?: EventData): Promise<void>;
95
95
  /**
96
- * Track purchase with automatic revenue encoding
96
+ * Track purchase with automatic revenue encoding and platform forwarding
97
97
  */
98
98
  trackPurchase(value: number, currency?: string, productId?: string): Promise<void>;
99
99
  /**
100
- * Track subscription with automatic revenue encoding
100
+ * Track subscription with automatic revenue encoding and platform forwarding
101
101
  */
102
102
  trackSubscription(value: number, currency?: string, plan?: string): Promise<void>;
103
+ /**
104
+ * Track add to cart event
105
+ */
106
+ trackAddToCart(value: number, currency?: string, productId?: string, productName?: string): Promise<void>;
107
+ /**
108
+ * Track view content/product event
109
+ */
110
+ trackViewContent(contentId?: string, contentName?: string, contentType?: string, value?: number, currency?: string): Promise<void>;
111
+ /**
112
+ * Track initiate checkout event
113
+ */
114
+ trackInitiateCheckout(value: number, currency?: string, numItems?: number, productIds?: string[]): Promise<void>;
115
+ /**
116
+ * Track complete registration event
117
+ */
118
+ trackCompleteRegistration(method?: string): Promise<void>;
119
+ /**
120
+ * Track search event
121
+ */
122
+ trackSearch(query: string, resultIds?: string[]): Promise<void>;
123
+ /**
124
+ * Track lead/contact form submission
125
+ */
126
+ trackLead(value?: number, currency?: string): Promise<void>;
127
+ /**
128
+ * Track add payment info event
129
+ */
130
+ trackAddPaymentInfo(success?: boolean): Promise<void>;
131
+ /**
132
+ * Get deferred attribution data from platform SDKs
133
+ */
134
+ getDeferredAttributionData(): DeferredDeepLinkResult | null;
135
+ /**
136
+ * Get platform integration status
137
+ */
138
+ getPlatformIntegrationStatus(): {
139
+ meta: boolean;
140
+ tiktok: boolean;
141
+ };
142
+ /**
143
+ * Update tracking authorization status on all platform SDKs
144
+ * Call this AFTER the user responds to the ATT permission dialog
145
+ */
146
+ updateTrackingAuthorization(enabled: boolean): Promise<void>;
147
+ /**
148
+ * Handle deferred deep link data from platform SDKs
149
+ */
150
+ private handleDeferredDeepLink;
103
151
  /**
104
152
  * Get conversion value for testing (doesn't send to Apple)
105
153
  */
@@ -175,5 +223,18 @@ export declare class Datalyr {
175
223
  static trackAppUpdate(previousVersion: string, currentVersion: string): Promise<void>;
176
224
  static trackRevenue(eventName: string, properties?: EventData): Promise<void>;
177
225
  static updateAutoEventsConfig(config: Partial<AutoEventConfig>): void;
226
+ static trackAddToCart(value: number, currency?: string, productId?: string, productName?: string): Promise<void>;
227
+ static trackViewContent(contentId?: string, contentName?: string, contentType?: string, value?: number, currency?: string): Promise<void>;
228
+ static trackInitiateCheckout(value: number, currency?: string, numItems?: number, productIds?: string[]): Promise<void>;
229
+ static trackCompleteRegistration(method?: string): Promise<void>;
230
+ static trackSearch(query: string, resultIds?: string[]): Promise<void>;
231
+ static trackLead(value?: number, currency?: string): Promise<void>;
232
+ static trackAddPaymentInfo(success?: boolean): Promise<void>;
233
+ static getDeferredAttributionData(): DeferredDeepLinkResult | null;
234
+ static getPlatformIntegrationStatus(): {
235
+ meta: boolean;
236
+ tiktok: boolean;
237
+ };
238
+ static updateTrackingAuthorization(enabled: boolean): Promise<void>;
178
239
  }
179
240
  export default datalyr;