expo-tiktok-ads-events 0.1.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/.eslintrc.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ['universe/native', 'universe/web'],
4
+ ignorePatterns: ['build'],
5
+ };
package/README.md ADDED
@@ -0,0 +1,350 @@
1
+ # expo-tiktok-ads-events
2
+
3
+ Expo module for TikTok Business SDK integration, enabling event tracking for TikTok advertising campaigns.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install expo-tiktok-ads-events
9
+ # or
10
+ yarn add expo-tiktok-ads-events
11
+ ```
12
+
13
+ ## Setup
14
+
15
+ ### Initialization
16
+
17
+ ```typescript
18
+ import TiktokAdsEvents from 'expo-tiktok-ads-events';
19
+ import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
20
+
21
+ // Request tracking permission (iOS 14+)
22
+ const { status } = await requestTrackingPermissionsAsync();
23
+
24
+ // Initialize SDK
25
+ await TiktokAdsEvents.initializeSdk(
26
+ 'YOUR_ACCESS_TOKEN', // TikTok Ads Manager access token
27
+ 'YOUR_APP_ID', // App ID
28
+ 'YOUR_TIKTOK_APP_ID' // TikTok App ID
29
+ );
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ### Standard Events
35
+
36
+ The module exports all TikTok standard events:
37
+
38
+ ```typescript
39
+ import TiktokAdsEvents, { TikTokStandardEvents } from 'expo-tiktok-ads-events';
40
+
41
+ // Track event without properties
42
+ await TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.launch_app);
43
+
44
+ // Track event with properties
45
+ await TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.add_payment_info, [
46
+ { key: 'currency', value: 'USD' },
47
+ { key: 'value', value: 99.99 },
48
+ { key: 'payment_method', value: 'credit_card' }
49
+ ]);
50
+ ```
51
+
52
+ #### Available Events
53
+
54
+ - `achieve_level` - Level achieved
55
+ - `add_payment_info` - Payment info added
56
+ - `complete_tutorial` - Tutorial completed
57
+ - `create_group` - Group created
58
+ - `create_role` - Role created
59
+ - `generate_lead` - Lead generated
60
+ - `in_app_ad_click` - In-app ad clicked
61
+ - `in_app_ad_impr` - In-app ad impression
62
+ - `install_app` - App installed
63
+ - `join_group` - Group joined
64
+ - `launch_app` - App launched
65
+ - `loan_application` - Loan application
66
+ - `loan_approval` - Loan approval
67
+ - `loan_disbursal` - Loan disbursal
68
+ - `login` - User login
69
+ - `rate` - Rating given
70
+ - `registration` - User registration
71
+ - `search` - Search performed
72
+ - `spend_credits` - Credits spent
73
+ - `start_trial` - Trial started
74
+ - `subscribe` - Subscription
75
+ - `unlock_achievement` - Achievement unlocked
76
+
77
+ ### Custom Events
78
+
79
+ ```typescript
80
+ // Create custom event
81
+ await TiktokAdsEvents.trackCustomEvent(
82
+ 'custom_event_name', // Event name
83
+ 'EVENT_ID_123', // Unique event ID
84
+ [ // Optional properties
85
+ { key: 'category', value: 'gaming' },
86
+ { key: 'score', value: 1500 }
87
+ ]
88
+ );
89
+ ```
90
+
91
+ ### User Identification
92
+
93
+ ```typescript
94
+ import { TikTokIdentify } from 'expo-tiktok-ads-events';
95
+
96
+ // Identify user
97
+ await TikTokIdentify({
98
+ externalId: 'USER_123',
99
+ externalUserName: 'John Doe',
100
+ phoneNumber: '+1234567890',
101
+ email: 'john@example.com'
102
+ });
103
+
104
+ // Or using direct method
105
+ await TiktokAdsEvents.identify(
106
+ 'USER_123', // External ID (required)
107
+ 'John Doe', // Name (optional)
108
+ '+1234567890', // Phone (optional)
109
+ 'john@example.com' // Email (optional)
110
+ );
111
+ ```
112
+
113
+ ### Helper Functions
114
+
115
+ ```typescript
116
+ import { TikTokLaunchApp } from 'expo-tiktok-ads-events';
117
+
118
+ // Helper for launch_app event
119
+ await TikTokLaunchApp();
120
+
121
+ // With properties
122
+ await TikTokLaunchApp([
123
+ { key: 'source', value: 'notification' }
124
+ ]);
125
+ ```
126
+
127
+ ### Debug Information
128
+
129
+ ```typescript
130
+ // Get anonymous user ID
131
+ const anonymousId = await TiktokAdsEvents.getAnonymousID();
132
+
133
+ // Get current access token
134
+ const accessToken = await TiktokAdsEvents.getAccessToken();
135
+
136
+ // Get test event code
137
+ const testEventCode = await TiktokAdsEvents.getTestEventCode();
138
+ ```
139
+
140
+ ## Complete Example
141
+
142
+ ```typescript
143
+ import { useEffect } from 'react';
144
+ import TiktokAdsEvents, {
145
+ TikTokLaunchApp,
146
+ TikTokIdentify,
147
+ TikTokStandardEvents
148
+ } from 'expo-tiktok-ads-events';
149
+ import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
150
+
151
+ export default function App() {
152
+ useEffect(() => {
153
+ (async () => {
154
+ // 1. Request tracking permission
155
+ const { status } = await requestTrackingPermissionsAsync();
156
+
157
+ if (status === 'granted') {
158
+ // 2. Initialize SDK
159
+ await TiktokAdsEvents.initializeSdk(
160
+ 'YOUR_ACCESS_TOKEN',
161
+ 'YOUR_APP_ID',
162
+ 'YOUR_TIKTOK_APP_ID'
163
+ );
164
+
165
+ // 3. Identify user
166
+ await TikTokIdentify({
167
+ externalId: 'USER_123',
168
+ email: 'user@example.com'
169
+ });
170
+
171
+ // 4. Track app launch
172
+ await TikTokLaunchApp();
173
+
174
+ // 5. Get debug info
175
+ const anonymousId = await TiktokAdsEvents.getAnonymousID();
176
+ console.log('Anonymous ID:', anonymousId);
177
+ }
178
+ })();
179
+ }, []);
180
+
181
+ const handlePurchase = async () => {
182
+ // Track purchase with properties
183
+ await TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.subscribe, [
184
+ { key: 'currency', value: 'USD' },
185
+ { key: 'value', value: 29.90 },
186
+ { key: 'content_type', value: 'subscription' },
187
+ { key: 'content_id', value: 'plan_premium' }
188
+ ]);
189
+ };
190
+
191
+ return (
192
+ // Your component
193
+ );
194
+ }
195
+ ```
196
+
197
+ ## Event Properties
198
+
199
+ ### Common Properties
200
+
201
+ - `currency` - Currency code (e.g., "USD", "EUR")
202
+ - `value` - Monetary value
203
+ - `content_type` - Content type
204
+ - `content_id` - Content ID
205
+ - `content_name` - Content name
206
+ - `quantity` - Quantity
207
+ - `description` - Description
208
+ - `query` - Search query
209
+ - `status` - Status
210
+
211
+ ### TypeScript Types
212
+
213
+ ```typescript
214
+ type EventProperty = {
215
+ key: string;
216
+ value: string | number;
217
+ };
218
+ ```
219
+
220
+ ## Testing Events
221
+
222
+ 1. Get test code:
223
+ ```typescript
224
+ const testCode = await TiktokAdsEvents.getTestEventCode();
225
+ console.log('Use this code in TikTok Events Manager:', testCode);
226
+ ```
227
+
228
+ 2. Go to [TikTok Events Manager](https://ads.tiktok.com/events_manager/)
229
+
230
+ 3. Select your pixel/app
231
+
232
+ 4. Navigate to "Test Events"
233
+
234
+ 5. Enter the test code
235
+
236
+ 6. Trigger events in your app and see them in real-time
237
+
238
+ ## SDK Configuration
239
+
240
+ The SDK is automatically configured with:
241
+
242
+ - ✅ Tracking enabled
243
+ - ✅ Launch tracking enabled
244
+ - ✅ Retention tracking enabled
245
+ - ✅ SKAdNetwork enabled (iOS)
246
+ - ✅ Debug mode enabled (development)
247
+
248
+ ## Compatibility
249
+
250
+ - iOS 15.1+
251
+ - Android (in development)
252
+ - Expo SDK 54+
253
+
254
+ ## Troubleshooting
255
+
256
+ ### Events Not Appearing in TikTok
257
+
258
+ 1. Verify tracking permission is granted (iOS)
259
+ 2. Confirm credentials are correct
260
+ 3. Use test mode to validate events
261
+ 4. Wait up to 24 hours for production events to appear
262
+
263
+ ### Empty Anonymous ID
264
+
265
+ Anonymous ID is generated after successful initialization. Make sure to call `initializeSdk` first.
266
+
267
+ ### Initialization Error
268
+
269
+ Check:
270
+ - Valid access token
271
+ - Correct app IDs
272
+ - Internet connection
273
+
274
+ ## API Reference
275
+
276
+ ### Methods
277
+
278
+ #### `initializeSdk(accessToken, appId, tiktokAppId)`
279
+ Initialize the TikTok Business SDK.
280
+
281
+ **Parameters:**
282
+ - `accessToken` (string): TikTok Ads Manager access token
283
+ - `appId` (string): Your app ID
284
+ - `tiktokAppId` (string): TikTok app ID
285
+
286
+ **Returns:** Promise<string>
287
+
288
+ #### `trackTTEvent(eventName, properties?)`
289
+ Track a standard TikTok event.
290
+
291
+ **Parameters:**
292
+ - `eventName` (TikTokStandardEventValue): Event name from TikTokStandardEvents
293
+ - `properties` (EventProperty[]): Optional array of event properties
294
+
295
+ **Returns:** Promise<string>
296
+
297
+ #### `trackCustomEvent(eventName, eventID, properties?)`
298
+ Track a custom event.
299
+
300
+ **Parameters:**
301
+ - `eventName` (string): Custom event name
302
+ - `eventID` (string): Unique event identifier
303
+ - `properties` (EventProperty[]): Optional array of event properties
304
+
305
+ **Returns:** Promise<void>
306
+
307
+ #### `identify(externalId, externalUserName?, phoneNumber?, email?)`
308
+ Identify a user.
309
+
310
+ **Parameters:**
311
+ - `externalId` (string): External user ID (required)
312
+ - `externalUserName` (string): User name (optional)
313
+ - `phoneNumber` (string): Phone number (optional)
314
+ - `email` (string): Email address (optional)
315
+
316
+ **Returns:** Promise<void>
317
+
318
+ #### `getAnonymousID()`
319
+ Get the anonymous user ID.
320
+
321
+ **Returns:** Promise<string>
322
+
323
+ #### `getAccessToken()`
324
+ Get the current access token.
325
+
326
+ **Returns:** Promise<string>
327
+
328
+ #### `getTestEventCode()`
329
+ Get the test event code for debugging.
330
+
331
+ **Returns:** Promise<string>
332
+
333
+ ## License
334
+
335
+ MIT
336
+
337
+ ## Author
338
+
339
+ Bruno Verçosa - [Pixel Logic Apps](https://github.com/Pixel-Logic-Apps)
340
+
341
+ ## Contributing
342
+
343
+ Contributions are welcome! Please open an issue or submit a pull request.
344
+
345
+ ## Links
346
+
347
+ - [TikTok for Business](https://business.tiktok.com/)
348
+ - [TikTok Ads Manager](https://ads.tiktok.com/)
349
+ - [TikTok Events API](https://business-api.tiktok.com/portal/docs)
350
+ - [Expo Modules Documentation](https://docs.expo.dev/modules/)
@@ -0,0 +1,43 @@
1
+ apply plugin: 'com.android.library'
2
+
3
+ group = 'expo.modules.tiktokadsevents'
4
+ version = '0.1.0'
5
+
6
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
+ apply from: expoModulesCorePlugin
8
+ applyKotlinExpoModulesCorePlugin()
9
+ useCoreDependencies()
10
+ useExpoPublishing()
11
+
12
+ // If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
13
+ // The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
14
+ // Most of the time, you may like to manage the Android SDK versions yourself.
15
+ def useManagedAndroidSdkVersions = false
16
+ if (useManagedAndroidSdkVersions) {
17
+ useDefaultAndroidSdkVersions()
18
+ } else {
19
+ buildscript {
20
+ // Simple helper that allows the root project to override versions declared by this library.
21
+ ext.safeExtGet = { prop, fallback ->
22
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
23
+ }
24
+ }
25
+ project.android {
26
+ compileSdkVersion safeExtGet("compileSdkVersion", 36)
27
+ defaultConfig {
28
+ minSdkVersion safeExtGet("minSdkVersion", 24)
29
+ targetSdkVersion safeExtGet("targetSdkVersion", 36)
30
+ }
31
+ }
32
+ }
33
+
34
+ android {
35
+ namespace "expo.modules.tiktokadsevents"
36
+ defaultConfig {
37
+ versionCode 1
38
+ versionName "0.1.0"
39
+ }
40
+ lintOptions {
41
+ abortOnError false
42
+ }
43
+ }
@@ -0,0 +1,2 @@
1
+ <manifest>
2
+ </manifest>
@@ -0,0 +1,50 @@
1
+ package expo.modules.tiktokadsevents
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+ import java.net.URL
6
+
7
+ class ExpoTiktokAdsEventsModule : Module() {
8
+ // Each module class must implement the definition function. The definition consists of components
9
+ // that describes the module's functionality and behavior.
10
+ // See https://docs.expo.dev/modules/module-api for more details about available components.
11
+ override fun definition() = ModuleDefinition {
12
+ // Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
13
+ // Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
14
+ // The module will be accessible from `requireNativeModule('ExpoTiktokAdsEvents')` in JavaScript.
15
+ Name("ExpoTiktokAdsEvents")
16
+
17
+ // Defines constant property on the module.
18
+ Constant("PI") {
19
+ Math.PI
20
+ }
21
+
22
+ // Defines event names that the module can send to JavaScript.
23
+ Events("onChange")
24
+
25
+ // Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
26
+ Function("hello") {
27
+ "Hello world! 👋"
28
+ }
29
+
30
+ // Defines a JavaScript function that always returns a Promise and whose native code
31
+ // is by default dispatched on the different thread than the JavaScript runtime runs on.
32
+ AsyncFunction("setValueAsync") { value: String ->
33
+ // Send an event to JavaScript.
34
+ sendEvent("onChange", mapOf(
35
+ "value" to value
36
+ ))
37
+ }
38
+
39
+ // Enables the module to be used as a native view. Definition components that are accepted as part of
40
+ // the view definition: Prop, Events.
41
+ View(ExpoTiktokAdsEventsView::class) {
42
+ // Defines a setter for the `url` prop.
43
+ Prop("url") { view: ExpoTiktokAdsEventsView, url: URL ->
44
+ view.webView.loadUrl(url.toString())
45
+ }
46
+ // Defines an event that the view can send to JavaScript.
47
+ Events("onLoad")
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,30 @@
1
+ package expo.modules.tiktokadsevents
2
+
3
+ import android.content.Context
4
+ import android.webkit.WebView
5
+ import android.webkit.WebViewClient
6
+ import expo.modules.kotlin.AppContext
7
+ import expo.modules.kotlin.viewevent.EventDispatcher
8
+ import expo.modules.kotlin.views.ExpoView
9
+
10
+ class ExpoTiktokAdsEventsView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
11
+ // Creates and initializes an event dispatcher for the `onLoad` event.
12
+ // The name of the event is inferred from the value and needs to match the event name defined in the module.
13
+ private val onLoad by EventDispatcher()
14
+
15
+ // Defines a WebView that will be used as the root subview.
16
+ internal val webView = WebView(context).apply {
17
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
18
+ webViewClient = object : WebViewClient() {
19
+ override fun onPageFinished(view: WebView, url: String) {
20
+ // Sends an event to JavaScript. Triggers a callback defined on the view component in JavaScript.
21
+ onLoad(mapOf("url" to url))
22
+ }
23
+ }
24
+ }
25
+
26
+ init {
27
+ // Adds the WebView to the view hierarchy.
28
+ addView(webView)
29
+ }
30
+ }
@@ -0,0 +1,50 @@
1
+ import { NativeModule } from 'expo';
2
+ export declare const TikTokStandardEvents: {
3
+ readonly achieve_level: "achieve_level";
4
+ readonly add_payment_info: "add_payment_info";
5
+ readonly complete_tutorial: "complete_tutorial";
6
+ readonly create_group: "create_group";
7
+ readonly create_role: "create_role";
8
+ readonly generate_lead: "generate_lead";
9
+ readonly in_app_ad_click: "in_app_ad_click";
10
+ readonly in_app_ad_impr: "in_app_ad_impr";
11
+ readonly install_app: "install_app";
12
+ readonly join_group: "join_group";
13
+ readonly launch_app: "launch_app";
14
+ readonly loan_application: "loan_application";
15
+ readonly loan_approval: "loan_approval";
16
+ readonly loan_disbursal: "loan_disbursal";
17
+ readonly login: "login";
18
+ readonly rate: "rate";
19
+ readonly registration: "registration";
20
+ readonly search: "search";
21
+ readonly spend_credits: "spend_credits";
22
+ readonly start_trial: "start_trial";
23
+ readonly subscribe: "subscribe";
24
+ readonly unlock_achievement: "unlock_achievement";
25
+ };
26
+ export type TikTokStandardEventKey = keyof typeof TikTokStandardEvents;
27
+ export type TikTokStandardEventValue = typeof TikTokStandardEvents[TikTokStandardEventKey];
28
+ export type EventProperty = {
29
+ key: string;
30
+ value: string | number;
31
+ };
32
+ declare class TiktokAdsEventsModule extends NativeModule {
33
+ initializeSdk(accessToken: string, appId: string, tiktokAppId: string): Promise<string>;
34
+ trackTTEvent(name: TikTokStandardEventValue, properties?: EventProperty[]): Promise<string>;
35
+ trackCustomEvent(eventName: string, eventID: string, properties?: EventProperty[]): Promise<void>;
36
+ identify(externalId: string, externalUserName?: string, phoneNumber?: string, email?: string): Promise<void>;
37
+ getAnonymousID(): Promise<string>;
38
+ getAccessToken(): Promise<string>;
39
+ getTestEventCode(): Promise<string>;
40
+ }
41
+ declare const TiktokAdsEvents: TiktokAdsEventsModule;
42
+ export default TiktokAdsEvents;
43
+ export declare function TikTokLaunchApp(properties?: EventProperty[]): Promise<string>;
44
+ export declare function TikTokIdentify(params: {
45
+ externalId: string;
46
+ externalUserName?: string;
47
+ phoneNumber?: string;
48
+ email?: string;
49
+ }): Promise<void>;
50
+ //# sourceMappingURL=ExpoTiktokAdsEventsModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoTiktokAdsEventsModule.d.ts","sourceRoot":"","sources":["../src/ExpoTiktokAdsEventsModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;CAuBvB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,MAAM,OAAO,oBAAoB,CAAC;AACvE,MAAM,MAAM,wBAAwB,GAAG,OAAO,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;AAC3F,MAAM,MAAM,aAAa,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAEpE,OAAO,OAAO,qBAAsB,SAAQ,YAAY;IACtD,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACvF,YAAY,CAAC,IAAI,EAAE,wBAAwB,EAAE,UAAU,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3F,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IACjG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5G,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IACjC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IACjC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CACpC;AAED,QAAA,MAAM,eAAe,uBAAgE,CAAC;AACtF,eAAe,eAAe,CAAC;AAE/B,wBAAsB,eAAe,CAAC,UAAU,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpJ"}
@@ -0,0 +1,35 @@
1
+ import { requireNativeModule } from 'expo';
2
+ export const TikTokStandardEvents = {
3
+ achieve_level: 'achieve_level',
4
+ add_payment_info: 'add_payment_info',
5
+ complete_tutorial: 'complete_tutorial',
6
+ create_group: 'create_group',
7
+ create_role: 'create_role',
8
+ generate_lead: 'generate_lead',
9
+ in_app_ad_click: 'in_app_ad_click',
10
+ in_app_ad_impr: 'in_app_ad_impr',
11
+ install_app: 'install_app',
12
+ join_group: 'join_group',
13
+ launch_app: 'launch_app',
14
+ loan_application: 'loan_application',
15
+ loan_approval: 'loan_approval',
16
+ loan_disbursal: 'loan_disbursal',
17
+ login: 'login',
18
+ rate: 'rate',
19
+ registration: 'registration',
20
+ search: 'search',
21
+ spend_credits: 'spend_credits',
22
+ start_trial: 'start_trial',
23
+ subscribe: 'subscribe',
24
+ unlock_achievement: 'unlock_achievement',
25
+ };
26
+ const TiktokAdsEvents = requireNativeModule('TiktokAdsEvents');
27
+ export default TiktokAdsEvents;
28
+ export async function TikTokLaunchApp(properties) {
29
+ return TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.launch_app, properties);
30
+ }
31
+ export async function TikTokIdentify(params) {
32
+ const { externalId, externalUserName, phoneNumber, email } = params;
33
+ return TiktokAdsEvents.identify(externalId, externalUserName, phoneNumber, email);
34
+ }
35
+ //# sourceMappingURL=ExpoTiktokAdsEventsModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoTiktokAdsEventsModule.js","sourceRoot":"","sources":["../src/ExpoTiktokAdsEventsModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAEzD,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,iBAAiB,EAAE,mBAAmB;IACtC,YAAY,EAAE,cAAc;IAC5B,WAAW,EAAE,aAAa;IAC1B,aAAa,EAAE,eAAe;IAC9B,eAAe,EAAE,iBAAiB;IAClC,cAAc,EAAE,gBAAgB;IAChC,WAAW,EAAE,aAAa;IAC1B,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,kBAAkB;IACpC,aAAa,EAAE,eAAe;IAC9B,cAAc,EAAE,gBAAgB;IAChC,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,YAAY,EAAE,cAAc;IAC5B,MAAM,EAAE,QAAQ;IAChB,aAAa,EAAE,eAAe;IAC9B,WAAW,EAAE,aAAa;IAC1B,SAAS,EAAE,WAAW;IACtB,kBAAkB,EAAE,oBAAoB;CAChC,CAAC;AAgBX,MAAM,eAAe,GAAG,mBAAmB,CAAwB,iBAAiB,CAAC,CAAC;AACtF,eAAe,eAAe,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAA4B;IAChE,OAAO,eAAe,CAAC,YAAY,CAAC,oBAAoB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAgG;IACnI,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACpE,OAAO,eAAe,CAAC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;AACpF,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo';\n\nexport const TikTokStandardEvents = {\n achieve_level: 'achieve_level',\n add_payment_info: 'add_payment_info',\n complete_tutorial: 'complete_tutorial',\n create_group: 'create_group',\n create_role: 'create_role',\n generate_lead: 'generate_lead',\n in_app_ad_click: 'in_app_ad_click',\n in_app_ad_impr: 'in_app_ad_impr',\n install_app: 'install_app',\n join_group: 'join_group',\n launch_app: 'launch_app',\n loan_application: 'loan_application',\n loan_approval: 'loan_approval',\n loan_disbursal: 'loan_disbursal',\n login: 'login',\n rate: 'rate',\n registration: 'registration',\n search: 'search',\n spend_credits: 'spend_credits',\n start_trial: 'start_trial',\n subscribe: 'subscribe',\n unlock_achievement: 'unlock_achievement',\n} as const;\n\nexport type TikTokStandardEventKey = keyof typeof TikTokStandardEvents;\nexport type TikTokStandardEventValue = typeof TikTokStandardEvents[TikTokStandardEventKey];\nexport type EventProperty = { key: string; value: string | number };\n\ndeclare class TiktokAdsEventsModule extends NativeModule {\n initializeSdk(accessToken: string, appId: string, tiktokAppId: string): Promise<string>;\n trackTTEvent(name: TikTokStandardEventValue, properties?: EventProperty[]): Promise<string>;\n trackCustomEvent(eventName: string, eventID: string, properties?: EventProperty[]): Promise<void>;\n identify(externalId: string, externalUserName?: string, phoneNumber?: string, email?: string): Promise<void>;\n getAnonymousID(): Promise<string>;\n getAccessToken(): Promise<string>;\n getTestEventCode(): Promise<string>;\n}\n\nconst TiktokAdsEvents = requireNativeModule<TiktokAdsEventsModule>('TiktokAdsEvents');\nexport default TiktokAdsEvents;\n\nexport async function TikTokLaunchApp(properties?: EventProperty[]): Promise<string> {\n return TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.launch_app, properties);\n}\n\nexport async function TikTokIdentify(params: { externalId: string; externalUserName?: string; phoneNumber?: string; email?: string; }): Promise<void> {\n const { externalId, externalUserName, phoneNumber, email } = params;\n return TiktokAdsEvents.identify(externalId, externalUserName, phoneNumber, email);\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export { default, TikTokLaunchApp, TikTokIdentify } from './ExpoTiktokAdsEventsModule';
2
+ export { default as ExpoTiktokAdsEvents } from './ExpoTiktokAdsEventsModule';
3
+ export { TikTokStandardEvents, TikTokStandardEventKey, TikTokStandardEventValue } from './ExpoTiktokAdsEventsModule';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default, TikTokLaunchApp, TikTokIdentify } from './ExpoTiktokAdsEventsModule';
2
+ export { default as ExpoTiktokAdsEvents } from './ExpoTiktokAdsEventsModule';
3
+ export { TikTokStandardEvents } from './ExpoTiktokAdsEventsModule';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAoD,MAAM,6BAA6B,CAAC","sourcesContent":["export { default, TikTokLaunchApp, TikTokIdentify } from './ExpoTiktokAdsEventsModule';\nexport { default as ExpoTiktokAdsEvents } from './ExpoTiktokAdsEventsModule';\nexport { TikTokStandardEvents, TikTokStandardEventKey, TikTokStandardEventValue } from './ExpoTiktokAdsEventsModule';\n"]}
@@ -0,0 +1,9 @@
1
+ {
2
+ "platforms": ["apple", "android", "web"],
3
+ "apple": {
4
+ "modules": ["ExpoTiktokAdsEventsModule"]
5
+ },
6
+ "android": {
7
+ "modules": ["expo.modules.tiktokadsevents.ExpoTiktokAdsEventsModule"]
8
+ }
9
+ }
@@ -0,0 +1,30 @@
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 = 'ExpoTiktokAdsEvents'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = package['description']
10
+ s.license = package['license']
11
+ s.author = package['author']
12
+ s.homepage = package['homepage']
13
+ s.platforms = {
14
+ :ios => '15.1',
15
+ :tvos => '15.1'
16
+ }
17
+ s.swift_version = '5.9'
18
+ s.source = { git: 'https://github.com/Pixel-Logic-Apps/expo-tiktok-ads-events' }
19
+ s.static_framework = true
20
+
21
+ s.dependency 'ExpoModulesCore'
22
+ s.dependency 'TikTokBusinessSDK'
23
+
24
+ # Swift/Objective-C compatibility
25
+ s.pod_target_xcconfig = {
26
+ 'DEFINES_MODULE' => 'YES',
27
+ }
28
+
29
+ s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
30
+ end
@@ -0,0 +1,99 @@
1
+ import ExpoModulesCore
2
+ import TikTokBusinessSDK
3
+
4
+ public class ExpoTiktokAdsEventsModule: Module {
5
+
6
+ private func addPropertiesToEvent(_ event: TikTokBaseEvent, properties: [[String: Any]]?) {
7
+ properties?.forEach { prop in
8
+ if let key = prop["key"] as? String,
9
+ let value = prop["value"] {
10
+ event.addProperty(withKey: key, value: value)
11
+ }
12
+ }
13
+ }
14
+
15
+ public func definition() -> ModuleDefinition {
16
+ Name("TiktokAdsEvents")
17
+
18
+ AsyncFunction("initializeSdk") { (accessToken: String, appId: String, tiktokAppId: String, promise: Promise) in
19
+ let config = TikTokConfig.init(accessToken: accessToken, appId: appId, tiktokAppId: tiktokAppId)
20
+ config?.trackingEnabled = true
21
+ config?.launchTrackingEnabled = true
22
+ config?.retentionTrackingEnabled = true
23
+ config?.skAdNetworkSupportEnabled = true
24
+ config?.debugModeEnabled = true
25
+ TikTokBusiness.initializeSdk(config){ success, error in
26
+ if (success) {
27
+ promise.resolve("initialization successful")
28
+ } else {
29
+ let message = error?.localizedDescription ?? "unknown"
30
+ promise.reject("ERR_TIKTOK_INIT", message)
31
+ }
32
+ }
33
+ }
34
+
35
+ AsyncFunction("getAnonymousID") { () -> String in
36
+ TikTokBusiness.getInstance().anonymousID
37
+ }
38
+
39
+ AsyncFunction("getAccessToken") { () -> String in
40
+ TikTokBusiness.getInstance().accessToken
41
+ }
42
+
43
+ AsyncFunction("getTestEventCode") { () -> String in
44
+ TikTokBusiness.getTestEventCode()
45
+ }
46
+
47
+ AsyncFunction("trackCustomEvent") { (eventName: String, eventID: String, properties: [[String: Any]]?) in
48
+ let customEvent = TikTokBaseEvent(eventName: eventName, eventId: eventID)
49
+ self.addPropertiesToEvent(customEvent, properties: properties)
50
+ TikTokBusiness.trackTTEvent(customEvent)
51
+ }
52
+
53
+ AsyncFunction("trackTTEvent") { (eventKey: String, properties: [[String: Any]]?) -> String in
54
+ let map: [String: String] = [
55
+ "achieve_level": TTEventName.achieveLevel.rawValue,
56
+ "add_payment_info": TTEventName.addPaymentInfo.rawValue,
57
+ "complete_tutorial": TTEventName.completeTutorial.rawValue,
58
+ "create_group": TTEventName.createGroup.rawValue,
59
+ "create_role": TTEventName.createRole.rawValue,
60
+ "generate_lead": TTEventName.generateLead.rawValue,
61
+ "in_app_ad_click": TTEventName.inAppADClick.rawValue,
62
+ "in_app_ad_impr": TTEventName.inAppADImpr.rawValue,
63
+ "install_app": TTEventName.installApp.rawValue,
64
+ "join_group": TTEventName.joinGroup.rawValue,
65
+ "launch_app": TTEventName.launchAPP.rawValue,
66
+ "loan_application": TTEventName.loanApplication.rawValue,
67
+ "loan_approval": TTEventName.loanApproval.rawValue,
68
+ "loan_disbursal": TTEventName.loanDisbursal.rawValue,
69
+ "login": TTEventName.login.rawValue,
70
+ "rate": TTEventName.rate.rawValue,
71
+ "registration": TTEventName.registration.rawValue,
72
+ "search": TTEventName.search.rawValue,
73
+ "spend_credits": TTEventName.spendCredits.rawValue,
74
+ "start_trial": TTEventName.startTrial.rawValue,
75
+ "subscribe": TTEventName.subscribe.rawValue,
76
+ "unlock_achievement": TTEventName.unlockAchievement.rawValue
77
+ ]
78
+ let resolved = map[eventKey] ?? eventKey
79
+ let event = TikTokBaseEvent(name: resolved)
80
+ self.addPropertiesToEvent(event, properties: properties)
81
+ TikTokBusiness.trackTTEvent(event)
82
+ return resolved
83
+ }
84
+
85
+
86
+
87
+ AsyncFunction("anonymousID") { () -> String in
88
+ return TikTokBusiness().anonymousID + "asdasd"
89
+ }
90
+
91
+ AsyncFunction("identify") { (externalId: String, externalUserName: String?, phoneNumber: String?, email: String?) in
92
+ let name = externalUserName ?? ""
93
+ let phone = phoneNumber ?? ""
94
+ let mail = email ?? ""
95
+ TikTokBusiness.identify(withExternalID: externalId, externalUserName: name, phoneNumber: phone, email: mail)
96
+ }
97
+
98
+ }
99
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "expo-tiktok-ads-events",
3
+ "version": "0.1.0",
4
+ "description": "Expo Tiktok SDK Events",
5
+ "main": "build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "scripts": {
8
+ "build": "expo-module build",
9
+ "clean": "expo-module clean",
10
+ "lint": "expo-module lint",
11
+ "test": "expo-module test",
12
+ "prepare": "expo-module prepare",
13
+ "prepublishOnly": "expo-module prepublishOnly",
14
+ "expo-module": "expo-module",
15
+ "open:ios": "xed example/ios",
16
+ "open:android": "open -a \"Android Studio\" example/android"
17
+ },
18
+ "keywords": [
19
+ "react-native",
20
+ "expo",
21
+ "expo-tiktok-ads-events",
22
+ "ExpoTiktokAdsEvents"
23
+ ],
24
+ "repository": "https://github.com/Pixel-Logic-Apps/expo-tiktok-ads-events",
25
+ "bugs": {
26
+ "url": "https://github.com/Pixel-Logic-Apps/expo-tiktok-ads-events/issues"
27
+ },
28
+ "author": "Bruno Verçosa <bruno.vmartins@hotmail.com> (https://github.com/Pixel-Logic-Apps)",
29
+ "license": "MIT",
30
+ "homepage": "https://github.com/Pixel-Logic-Apps/expo-tiktok-ads-events#readme",
31
+ "dependencies": {},
32
+ "devDependencies": {
33
+ "@types/react": "~19.1.0",
34
+ "expo-module-scripts": "^5.0.7",
35
+ "expo": "^54.0.7",
36
+ "react-native": "0.81.4"
37
+ },
38
+ "peerDependencies": {
39
+ "expo": "*",
40
+ "react": "*",
41
+ "react-native": "*"
42
+ }
43
+ }
@@ -0,0 +1,52 @@
1
+ import { NativeModule, requireNativeModule } from 'expo';
2
+
3
+ export const TikTokStandardEvents = {
4
+ achieve_level: 'achieve_level',
5
+ add_payment_info: 'add_payment_info',
6
+ complete_tutorial: 'complete_tutorial',
7
+ create_group: 'create_group',
8
+ create_role: 'create_role',
9
+ generate_lead: 'generate_lead',
10
+ in_app_ad_click: 'in_app_ad_click',
11
+ in_app_ad_impr: 'in_app_ad_impr',
12
+ install_app: 'install_app',
13
+ join_group: 'join_group',
14
+ launch_app: 'launch_app',
15
+ loan_application: 'loan_application',
16
+ loan_approval: 'loan_approval',
17
+ loan_disbursal: 'loan_disbursal',
18
+ login: 'login',
19
+ rate: 'rate',
20
+ registration: 'registration',
21
+ search: 'search',
22
+ spend_credits: 'spend_credits',
23
+ start_trial: 'start_trial',
24
+ subscribe: 'subscribe',
25
+ unlock_achievement: 'unlock_achievement',
26
+ } as const;
27
+
28
+ export type TikTokStandardEventKey = keyof typeof TikTokStandardEvents;
29
+ export type TikTokStandardEventValue = typeof TikTokStandardEvents[TikTokStandardEventKey];
30
+ export type EventProperty = { key: string; value: string | number };
31
+
32
+ declare class TiktokAdsEventsModule extends NativeModule {
33
+ initializeSdk(accessToken: string, appId: string, tiktokAppId: string): Promise<string>;
34
+ trackTTEvent(name: TikTokStandardEventValue, properties?: EventProperty[]): Promise<string>;
35
+ trackCustomEvent(eventName: string, eventID: string, properties?: EventProperty[]): Promise<void>;
36
+ identify(externalId: string, externalUserName?: string, phoneNumber?: string, email?: string): Promise<void>;
37
+ getAnonymousID(): Promise<string>;
38
+ getAccessToken(): Promise<string>;
39
+ getTestEventCode(): Promise<string>;
40
+ }
41
+
42
+ const TiktokAdsEvents = requireNativeModule<TiktokAdsEventsModule>('TiktokAdsEvents');
43
+ export default TiktokAdsEvents;
44
+
45
+ export async function TikTokLaunchApp(properties?: EventProperty[]): Promise<string> {
46
+ return TiktokAdsEvents.trackTTEvent(TikTokStandardEvents.launch_app, properties);
47
+ }
48
+
49
+ export async function TikTokIdentify(params: { externalId: string; externalUserName?: string; phoneNumber?: string; email?: string; }): Promise<void> {
50
+ const { externalId, externalUserName, phoneNumber, email } = params;
51
+ return TiktokAdsEvents.identify(externalId, externalUserName, phoneNumber, email);
52
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { default, TikTokLaunchApp, TikTokIdentify } from './ExpoTiktokAdsEventsModule';
2
+ export { default as ExpoTiktokAdsEvents } from './ExpoTiktokAdsEventsModule';
3
+ export { TikTokStandardEvents, TikTokStandardEventKey, TikTokStandardEventValue } from './ExpoTiktokAdsEventsModule';
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ // @generated by expo-module-scripts
2
+ {
3
+ "extends": "expo-module-scripts/tsconfig.base",
4
+ "compilerOptions": {
5
+ "outDir": "./build"
6
+ },
7
+ "include": ["./src"],
8
+ "exclude": ["**/__mocks__/*", "**/__tests__/*", "**/__rsc_tests__/*"]
9
+ }