@datalyr/react-native 1.4.9 → 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 +17 -127
- 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 +8 -4
- package/lib/datalyr-sdk.js +83 -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 +96 -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
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TikTok Business SDK Integration
|
|
3
|
-
* Uses bundled native iOS SDK for event forwarding and user identification
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Platform } from 'react-native';
|
|
7
|
-
import { TikTokConfig } from '../types';
|
|
8
|
-
import { TikTokNativeBridge, isNativeModuleAvailable } from '../native/DatalyrNativeBridge';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* TikTok standard event names (current as of 2025)
|
|
12
|
-
* Note: CompletePayment and SubmitForm are legacy, use Purchase and Lead instead
|
|
13
|
-
*/
|
|
14
|
-
const TikTokEvents = {
|
|
15
|
-
// Commerce events
|
|
16
|
-
PURCHASE: 'Purchase',
|
|
17
|
-
ADD_TO_CART: 'AddToCart',
|
|
18
|
-
ADD_TO_WISHLIST: 'AddToWishlist',
|
|
19
|
-
INITIATE_CHECKOUT: 'InitiateCheckout',
|
|
20
|
-
ADD_PAYMENT_INFO: 'AddPaymentInfo',
|
|
21
|
-
VIEW_CONTENT: 'ViewContent',
|
|
22
|
-
SEARCH: 'Search',
|
|
23
|
-
|
|
24
|
-
// User events
|
|
25
|
-
COMPLETE_REGISTRATION: 'CompleteRegistration',
|
|
26
|
-
SUBSCRIBE: 'Subscribe',
|
|
27
|
-
START_TRIAL: 'StartTrial',
|
|
28
|
-
LEAD: 'Lead',
|
|
29
|
-
CONTACT: 'Contact',
|
|
30
|
-
|
|
31
|
-
// App events
|
|
32
|
-
DOWNLOAD: 'Download',
|
|
33
|
-
SCHEDULE: 'Schedule',
|
|
34
|
-
SUBMIT_APPLICATION: 'SubmitApplication',
|
|
35
|
-
} as const;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* TikTok Integration class for handling TikTok Business SDK operations
|
|
39
|
-
* Uses native iOS SDK bundled via CocoaPods (no additional npm packages required)
|
|
40
|
-
*/
|
|
41
|
-
export class TikTokIntegration {
|
|
42
|
-
private config: TikTokConfig | null = null;
|
|
43
|
-
private initialized: boolean = false;
|
|
44
|
-
private available: boolean = false;
|
|
45
|
-
private debug: boolean = false;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Initialize TikTok SDK with configuration
|
|
49
|
-
* Supported on both iOS and Android via native modules
|
|
50
|
-
*/
|
|
51
|
-
async initialize(config: TikTokConfig, debug: boolean = false): Promise<void> {
|
|
52
|
-
this.debug = debug;
|
|
53
|
-
this.config = config;
|
|
54
|
-
|
|
55
|
-
// Only available on iOS and Android via native modules
|
|
56
|
-
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
|
|
57
|
-
this.log('TikTok SDK only available on iOS and Android');
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
this.available = isNativeModuleAvailable();
|
|
62
|
-
|
|
63
|
-
if (!this.available) {
|
|
64
|
-
this.log('TikTok native module not available');
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const success = await TikTokNativeBridge.initialize(
|
|
70
|
-
config.appId,
|
|
71
|
-
config.tiktokAppId,
|
|
72
|
-
config.accessToken,
|
|
73
|
-
debug
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
if (success) {
|
|
77
|
-
this.initialized = true;
|
|
78
|
-
this.log(`TikTok SDK initialized with App ID: ${config.tiktokAppId}`);
|
|
79
|
-
} else {
|
|
80
|
-
console.warn('[Datalyr/TikTok] TikTok SDK not initialized (accessToken may be missing). Events will still be sent server-side via Datalyr postbacks.');
|
|
81
|
-
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.warn('[Datalyr/TikTok] TikTok SDK init failed. Events will still be sent server-side via Datalyr postbacks.', error);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Update tracking authorization status (call after ATT prompt)
|
|
89
|
-
*/
|
|
90
|
-
async updateTrackingAuthorization(enabled: boolean): Promise<void> {
|
|
91
|
-
if (!this.available || !this.initialized) return;
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
// TikTok SDK auto-handles ATT, but we track the event
|
|
95
|
-
if (enabled) {
|
|
96
|
-
await this.trackEvent('ATTAuthorized');
|
|
97
|
-
}
|
|
98
|
-
await TikTokNativeBridge.updateTrackingAuthorization(enabled);
|
|
99
|
-
this.log(`TikTok ATT status: ${enabled ? 'authorized' : 'not authorized'}`);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
this.logError('Failed to update TikTok tracking authorization:', error);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Log purchase event to TikTok (uses Purchase - TikTok's current standard event)
|
|
107
|
-
*/
|
|
108
|
-
async logPurchase(
|
|
109
|
-
value: number,
|
|
110
|
-
currency: string,
|
|
111
|
-
contentId?: string,
|
|
112
|
-
contentType?: string,
|
|
113
|
-
parameters?: Record<string, any>
|
|
114
|
-
): Promise<void> {
|
|
115
|
-
if (!this.available || !this.initialized) return;
|
|
116
|
-
if (this.config?.enableAppEvents === false) return;
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
const properties: Record<string, any> = {
|
|
120
|
-
value,
|
|
121
|
-
currency,
|
|
122
|
-
...parameters,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
if (contentId) properties.content_id = contentId;
|
|
126
|
-
if (contentType) properties.content_type = contentType;
|
|
127
|
-
|
|
128
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.PURCHASE, undefined, properties);
|
|
129
|
-
this.log(`TikTok Purchase event logged: ${value} ${currency}`);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
this.logError('Failed to log TikTok purchase:', error);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Log subscription event to TikTok
|
|
137
|
-
*/
|
|
138
|
-
async logSubscription(value: number, currency: string, plan?: string): Promise<void> {
|
|
139
|
-
if (!this.available || !this.initialized) return;
|
|
140
|
-
if (this.config?.enableAppEvents === false) return;
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
const properties: Record<string, any> = {
|
|
144
|
-
value,
|
|
145
|
-
currency,
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
if (plan) {
|
|
149
|
-
properties.content_id = plan;
|
|
150
|
-
properties.content_type = 'subscription';
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.SUBSCRIBE, undefined, properties);
|
|
154
|
-
this.log(`TikTok subscription event logged: ${value} ${currency}`);
|
|
155
|
-
} catch (error) {
|
|
156
|
-
this.logError('Failed to log TikTok subscription:', error);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Log add to cart event
|
|
162
|
-
*/
|
|
163
|
-
async logAddToCart(value: number, currency: string, contentId?: string, contentType?: string): Promise<void> {
|
|
164
|
-
if (!this.available || !this.initialized) return;
|
|
165
|
-
if (this.config?.enableAppEvents === false) return;
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
const properties: Record<string, any> = {
|
|
169
|
-
value,
|
|
170
|
-
currency,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
if (contentId) properties.content_id = contentId;
|
|
174
|
-
if (contentType) properties.content_type = contentType;
|
|
175
|
-
|
|
176
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.ADD_TO_CART, undefined, properties);
|
|
177
|
-
this.log('TikTok add to cart event logged');
|
|
178
|
-
} catch (error) {
|
|
179
|
-
this.logError('Failed to log TikTok add to cart:', error);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Log view content event
|
|
185
|
-
*/
|
|
186
|
-
async logViewContent(contentId?: string, contentName?: string, contentType?: string): Promise<void> {
|
|
187
|
-
if (!this.available || !this.initialized) return;
|
|
188
|
-
if (this.config?.enableAppEvents === false) return;
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
const properties: Record<string, any> = {};
|
|
192
|
-
if (contentId) properties.content_id = contentId;
|
|
193
|
-
if (contentName) properties.content_name = contentName;
|
|
194
|
-
if (contentType) properties.content_type = contentType;
|
|
195
|
-
|
|
196
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.VIEW_CONTENT, undefined, properties);
|
|
197
|
-
this.log('TikTok view content event logged');
|
|
198
|
-
} catch (error) {
|
|
199
|
-
this.logError('Failed to log TikTok view content:', error);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Log initiate checkout event
|
|
205
|
-
*/
|
|
206
|
-
async logInitiateCheckout(value: number, currency: string, numItems?: number): Promise<void> {
|
|
207
|
-
if (!this.available || !this.initialized) return;
|
|
208
|
-
if (this.config?.enableAppEvents === false) return;
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
const properties: Record<string, any> = {
|
|
212
|
-
value,
|
|
213
|
-
currency,
|
|
214
|
-
};
|
|
215
|
-
if (numItems) properties.quantity = numItems;
|
|
216
|
-
|
|
217
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.INITIATE_CHECKOUT, undefined, properties);
|
|
218
|
-
this.log('TikTok initiate checkout event logged');
|
|
219
|
-
} catch (error) {
|
|
220
|
-
this.logError('Failed to log TikTok initiate checkout:', error);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Log complete registration event
|
|
226
|
-
*/
|
|
227
|
-
async logCompleteRegistration(method?: string): Promise<void> {
|
|
228
|
-
if (!this.available || !this.initialized) return;
|
|
229
|
-
if (this.config?.enableAppEvents === false) return;
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
const properties: Record<string, any> = {};
|
|
233
|
-
if (method) properties.registration_method = method;
|
|
234
|
-
|
|
235
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.COMPLETE_REGISTRATION, undefined, properties);
|
|
236
|
-
this.log('TikTok complete registration event logged');
|
|
237
|
-
} catch (error) {
|
|
238
|
-
this.logError('Failed to log TikTok complete registration:', error);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Log search event
|
|
244
|
-
*/
|
|
245
|
-
async logSearch(query: string): Promise<void> {
|
|
246
|
-
if (!this.available || !this.initialized) return;
|
|
247
|
-
if (this.config?.enableAppEvents === false) return;
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.SEARCH, undefined, { query });
|
|
251
|
-
this.log('TikTok search event logged');
|
|
252
|
-
} catch (error) {
|
|
253
|
-
this.logError('Failed to log TikTok search:', error);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Log lead event (uses Lead - current standard, SubmitForm is legacy)
|
|
259
|
-
*/
|
|
260
|
-
async logLead(value?: number, currency?: string): Promise<void> {
|
|
261
|
-
if (!this.available || !this.initialized) return;
|
|
262
|
-
if (this.config?.enableAppEvents === false) return;
|
|
263
|
-
|
|
264
|
-
try {
|
|
265
|
-
const properties: Record<string, any> = {};
|
|
266
|
-
if (value !== undefined) properties.value = value;
|
|
267
|
-
if (currency) properties.currency = currency;
|
|
268
|
-
|
|
269
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.LEAD, undefined, properties);
|
|
270
|
-
this.log('TikTok lead event logged');
|
|
271
|
-
} catch (error) {
|
|
272
|
-
this.logError('Failed to log TikTok lead:', error);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Log add payment info event
|
|
278
|
-
*/
|
|
279
|
-
async logAddPaymentInfo(success: boolean): Promise<void> {
|
|
280
|
-
if (!this.available || !this.initialized) return;
|
|
281
|
-
if (this.config?.enableAppEvents === false) return;
|
|
282
|
-
|
|
283
|
-
try {
|
|
284
|
-
await TikTokNativeBridge.trackEvent(TikTokEvents.ADD_PAYMENT_INFO, undefined, { success });
|
|
285
|
-
this.log('TikTok add payment info event logged');
|
|
286
|
-
} catch (error) {
|
|
287
|
-
this.logError('Failed to log TikTok add payment info:', error);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Log custom event to TikTok
|
|
293
|
-
*/
|
|
294
|
-
async trackEvent(eventName: string, properties?: Record<string, any>): Promise<void> {
|
|
295
|
-
if (!this.available || !this.initialized) return;
|
|
296
|
-
if (this.config?.enableAppEvents === false) return;
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
await TikTokNativeBridge.trackEvent(eventName, undefined, properties || {});
|
|
300
|
-
this.log(`TikTok event logged: ${eventName}`);
|
|
301
|
-
} catch (error) {
|
|
302
|
-
this.logError('Failed to log TikTok event:', error);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Identify user for improved attribution matching
|
|
308
|
-
*/
|
|
309
|
-
async identify(email?: string, phone?: string, externalId?: string): Promise<void> {
|
|
310
|
-
if (!this.available || !this.initialized) return;
|
|
311
|
-
|
|
312
|
-
// Only call identify if we have at least one value
|
|
313
|
-
if (!email && !phone && !externalId) return;
|
|
314
|
-
|
|
315
|
-
try {
|
|
316
|
-
await TikTokNativeBridge.identify(externalId, email, phone);
|
|
317
|
-
this.log('TikTok user identification set');
|
|
318
|
-
} catch (error) {
|
|
319
|
-
this.logError('Failed to identify TikTok user:', error);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Clear user session (call on logout)
|
|
325
|
-
*/
|
|
326
|
-
async logout(): Promise<void> {
|
|
327
|
-
if (!this.available || !this.initialized) return;
|
|
328
|
-
|
|
329
|
-
try {
|
|
330
|
-
await TikTokNativeBridge.logout();
|
|
331
|
-
this.log('TikTok user logged out');
|
|
332
|
-
} catch (error) {
|
|
333
|
-
this.logError('Failed to logout TikTok user:', error);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Check if TikTok SDK is available and initialized
|
|
339
|
-
*/
|
|
340
|
-
isAvailable(): boolean {
|
|
341
|
-
return this.available && this.initialized;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Check if TikTok SDK native module is installed
|
|
346
|
-
*/
|
|
347
|
-
isInstalled(): boolean {
|
|
348
|
-
return this.available;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
private log(message: string, data?: any): void {
|
|
352
|
-
if (this.debug) {
|
|
353
|
-
console.log(`[Datalyr/TikTok] ${message}`, data || '');
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
private logError(message: string, error: any): void {
|
|
358
|
-
console.error(`[Datalyr/TikTok] ${message}`, error);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Export singleton instance
|
|
363
|
-
export const tiktokIntegration = new TikTokIntegration();
|