zixflow-reactnative 1.1.2 → 1.1.3
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/README.md +1857 -325
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/zixflow/reactnative/sdk/NativeZixflowModule.kt +29 -19
- package/android/src/main/java/com/zixflow/reactnative/sdk/constant/Keys.kt +1 -4
- package/android/src/main/java/com/zixflow/reactnative/sdk/logging/NativeZixflowLoggingModule.kt +2 -2
- package/android/src/main/java/com/zixflow/reactnative/sdk/messaginginapp/NativeMessagingInAppModule.kt +2 -13
- package/ios/wrappers/utils/ZixflowConfigUtils.swift +5 -9
- package/lib/commonjs/types/data-pipelines.js +3 -15
- package/lib/commonjs/types/data-pipelines.js.map +1 -1
- package/lib/commonjs/utils/param-validation.js +1 -1
- package/lib/commonjs/utils/param-validation.js.map +1 -1
- package/lib/commonjs/zixflow-cdp.js +2 -10
- package/lib/commonjs/zixflow-cdp.js.map +1 -1
- package/lib/commonjs/zixflow.js.map +1 -1
- package/lib/module/types/data-pipelines.js +2 -15
- package/lib/module/types/data-pipelines.js.map +1 -1
- package/lib/module/utils/param-validation.js +1 -1
- package/lib/module/utils/param-validation.js.map +1 -1
- package/lib/module/zixflow-cdp.js +2 -10
- package/lib/module/zixflow-cdp.js.map +1 -1
- package/lib/module/zixflow.js +0 -6
- package/lib/module/zixflow.js.map +1 -1
- package/lib/typescript/commonjs/types/data-pipelines.d.ts +4 -20
- package/lib/typescript/commonjs/types/data-pipelines.d.ts.map +1 -1
- package/lib/typescript/commonjs/zixflow-cdp.d.ts.map +1 -1
- package/lib/typescript/commonjs/zixflow.d.ts +0 -5
- package/lib/typescript/commonjs/zixflow.d.ts.map +1 -1
- package/lib/typescript/module/types/data-pipelines.d.ts +4 -20
- package/lib/typescript/module/types/data-pipelines.d.ts.map +1 -1
- package/lib/typescript/module/zixflow-cdp.d.ts.map +1 -1
- package/lib/typescript/module/zixflow.d.ts +0 -5
- package/lib/typescript/module/zixflow.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/types/data-pipelines.ts +4 -21
- package/src/utils/param-validation.ts +1 -1
- package/src/zixflow-cdp.ts +2 -12
- package/src/zixflow.ts +0 -6
- package/zixflow-reactnative-richpush.podspec +2 -2
- package/zixflow-reactnative.podspec +2 -2
package/README.md
CHANGED
|
@@ -1,517 +1,2049 @@
|
|
|
1
|
-
|
|
2
|
-
<a href="https://zixflow.com">
|
|
3
|
-
<img src="https://zixflow.com/logo.svg" height="60">
|
|
4
|
-
</a>
|
|
5
|
-
</p>
|
|
1
|
+
# Zixflow React Native SDK - Integration Guide
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
[](https://www.npmjs.com/package/zixflow-reactnative)
|
|
9
|
-

|
|
10
|
-

|
|
11
|
-

|
|
12
|
-
[](CODE_OF_CONDUCT.md)
|
|
3
|
+
Welcome to the **Zixflow React Native SDK** integration guide. This comprehensive document will help you install, configure, and use the Zixflow SDK in your React Native application to track user behavior, send push notifications, display in-app messages, and more.
|
|
13
4
|
|
|
14
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Introduction](#introduction)
|
|
10
|
+
2. [Requirements](#requirements)
|
|
11
|
+
3. [Installation](#installation)
|
|
12
|
+
- [npm Installation](#npm-installation)
|
|
13
|
+
- [Yarn Installation](#yarn-installation)
|
|
14
|
+
4. [iOS Setup](#ios-setup)
|
|
15
|
+
- [CocoaPods Integration](#cocoapods-integration)
|
|
16
|
+
- [Swift Package Manager Integration](#swift-package-manager-integration)
|
|
17
|
+
- [Push Notification Setup (APNs)](#push-notification-setup-apns)
|
|
18
|
+
- [Notification Service Extension](#notification-service-extension)
|
|
19
|
+
5. [Android Setup](#android-setup)
|
|
20
|
+
- [Gradle Configuration](#gradle-configuration)
|
|
21
|
+
- [Firebase Cloud Messaging Setup](#firebase-cloud-messaging-setup)
|
|
22
|
+
6. [Quick Start](#quick-start)
|
|
23
|
+
- [Basic Configuration](#basic-configuration)
|
|
24
|
+
- [SDK Initialization](#sdk-initialization)
|
|
25
|
+
7. [Core Features](#core-features)
|
|
26
|
+
- [User Identification](#user-identification)
|
|
27
|
+
- [Event Tracking](#event-tracking)
|
|
28
|
+
- [Screen Tracking](#screen-tracking)
|
|
29
|
+
- [User Profile Attributes](#user-profile-attributes)
|
|
30
|
+
- [Device Attributes](#device-attributes)
|
|
31
|
+
- [Clearing User Identity](#clearing-user-identity)
|
|
32
|
+
8. [Push Notifications](#push-notifications)
|
|
33
|
+
- [Requesting Permission](#requesting-permission)
|
|
34
|
+
- [Handling Push Notifications](#handling-push-notifications)
|
|
35
|
+
- [Device Token Registration](#device-token-registration)
|
|
36
|
+
9. [In-App Messaging](#in-app-messaging)
|
|
37
|
+
- [Event Listeners](#event-listeners)
|
|
38
|
+
- [Message Events](#message-events)
|
|
39
|
+
- [Dismissing Messages](#dismissing-messages)
|
|
40
|
+
10. [Location Tracking](#location-tracking)
|
|
41
|
+
11. [Advanced Configuration](#advanced-configuration)
|
|
42
|
+
- [Region Settings](#region-settings)
|
|
43
|
+
- [Log Levels](#log-levels)
|
|
44
|
+
- [Auto-Tracking Options](#auto-tracking-options)
|
|
45
|
+
- [Custom API Hosts](#custom-api-hosts)
|
|
46
|
+
12. [Troubleshooting](#troubleshooting)
|
|
47
|
+
- [Installation Issues](#installation-issues)
|
|
48
|
+
- [iOS Build Errors](#ios-build-errors)
|
|
49
|
+
- [Android Build Errors](#android-build-errors)
|
|
50
|
+
- [Push Notification Issues](#push-notification-issues)
|
|
51
|
+
- [In-App Message Issues](#in-app-message-issues)
|
|
52
|
+
13. [Example Applications](#example-applications)
|
|
53
|
+
14. [API Reference](#api-reference)
|
|
54
|
+
15. [Support & Resources](#support--resources)
|
|
55
|
+
|
|
56
|
+
---
|
|
15
57
|
|
|
16
|
-
|
|
58
|
+
## Introduction
|
|
17
59
|
|
|
18
|
-
|
|
19
|
-
|
|
60
|
+
The **Zixflow React Native SDK** enables you to:
|
|
61
|
+
|
|
62
|
+
- **Identify users** and track their behavior across your app
|
|
63
|
+
- **Send targeted push notifications** via Apple Push Notification service (APNs) or Firebase Cloud Messaging (FCM)
|
|
64
|
+
- **Display in-app messages** to engage users at the right time
|
|
65
|
+
- **Track user location** to enable location-based messaging
|
|
66
|
+
- **Manage user profiles** with custom attributes
|
|
67
|
+
- **Track events and screen views** automatically or manually
|
|
68
|
+
|
|
69
|
+
The SDK is built on top of the native Zixflow iOS and Android SDKs, providing a unified TypeScript API for React Native applications.
|
|
20
70
|
|
|
21
71
|
---
|
|
22
72
|
|
|
23
|
-
##
|
|
73
|
+
## Requirements
|
|
74
|
+
|
|
75
|
+
### React Native
|
|
24
76
|
|
|
25
|
-
|
|
77
|
+
- **React Native**: 0.60.0 or higher
|
|
78
|
+
- **React**: 16.8.0 or higher (for hooks support)
|
|
26
79
|
|
|
27
|
-
###
|
|
80
|
+
### iOS
|
|
28
81
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
82
|
+
- **iOS**: 13.0 or higher
|
|
83
|
+
- **Xcode**: 14.0 or higher
|
|
84
|
+
- **Swift**: 5.3 or higher
|
|
85
|
+
- **CocoaPods**: 1.10.0 or higher (if using CocoaPods)
|
|
86
|
+
|
|
87
|
+
### Android
|
|
88
|
+
|
|
89
|
+
- **Android**: API level 24 (Android 7.0) or higher
|
|
90
|
+
- **Kotlin**: 1.6.0 or higher
|
|
91
|
+
- **Gradle**: 7.0 or higher
|
|
92
|
+
|
|
93
|
+
### TypeScript (Recommended)
|
|
94
|
+
|
|
95
|
+
- **TypeScript**: 4.0 or higher
|
|
37
96
|
|
|
38
97
|
---
|
|
39
98
|
|
|
40
99
|
## Installation
|
|
41
100
|
|
|
101
|
+
### npm Installation
|
|
102
|
+
|
|
103
|
+
Install the SDK using npm:
|
|
104
|
+
|
|
42
105
|
```bash
|
|
43
106
|
npm install zixflow-reactnative
|
|
44
107
|
```
|
|
45
108
|
|
|
46
|
-
|
|
109
|
+
### Yarn Installation
|
|
110
|
+
|
|
111
|
+
Or install using Yarn:
|
|
47
112
|
|
|
48
113
|
```bash
|
|
49
114
|
yarn add zixflow-reactnative
|
|
50
115
|
```
|
|
51
116
|
|
|
117
|
+
After installation, proceed with platform-specific setup for iOS and Android.
|
|
118
|
+
|
|
52
119
|
---
|
|
53
120
|
|
|
54
|
-
##
|
|
121
|
+
## iOS Setup
|
|
55
122
|
|
|
56
|
-
###
|
|
123
|
+
### CocoaPods Integration
|
|
57
124
|
|
|
58
|
-
|
|
125
|
+
The Zixflow React Native SDK automatically integrates with the native iOS SDK via CocoaPods or Swift Package Manager. If you're using **React Native 0.60 or higher**, dependencies are auto-linked.
|
|
59
126
|
|
|
60
|
-
|
|
61
|
-
import {
|
|
62
|
-
Zixflow,
|
|
63
|
-
ZixflowConfig,
|
|
64
|
-
ZixflowLogLevel,
|
|
65
|
-
} from 'zixflow-reactnative';
|
|
127
|
+
1. **Navigate to the iOS directory**:
|
|
66
128
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
migrationSiteId: 'your-site-id', // Optional, for migrating from older SDKs
|
|
71
|
-
logLevel: ZixflowLogLevel.Debug,
|
|
72
|
-
trackApplicationLifecycleEvents: true,
|
|
73
|
-
inApp: {
|
|
74
|
-
siteId: 'your-site-id', // Required for in-app messaging
|
|
75
|
-
},
|
|
76
|
-
push: {
|
|
77
|
-
android: {
|
|
78
|
-
pushClickBehavior: 'ActivityPreventRestart', // Optional
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
};
|
|
129
|
+
```bash
|
|
130
|
+
cd ios
|
|
131
|
+
```
|
|
82
132
|
|
|
83
|
-
|
|
84
|
-
|
|
133
|
+
2. **Install CocoaPods dependencies**:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pod install
|
|
85
137
|
```
|
|
86
138
|
|
|
87
|
-
|
|
139
|
+
3. **Open the workspace in Xcode**:
|
|
88
140
|
|
|
89
|
-
|
|
141
|
+
```bash
|
|
142
|
+
open YourApp.xcworkspace
|
|
143
|
+
```
|
|
90
144
|
|
|
91
|
-
|
|
145
|
+
The SDK will automatically include the necessary Zixflow iOS modules:
|
|
146
|
+
- `ZixflowCommon`
|
|
147
|
+
- `ZixflowDataPipelines`
|
|
148
|
+
- `ZixflowMessagingPush`
|
|
149
|
+
- `ZixflowMessagingPushAPN` (for APNs)
|
|
150
|
+
- `ZixflowMessagingInApp`
|
|
92
151
|
|
|
93
|
-
###
|
|
152
|
+
### Swift Package Manager Integration
|
|
94
153
|
|
|
95
|
-
|
|
154
|
+
If you prefer **Swift Package Manager (SPM)**, you can configure your project to use the Zixflow iOS SDK directly:
|
|
96
155
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
156
|
+
1. **Open your project in Xcode**
|
|
157
|
+
2. **Go to File > Add Package Dependencies**
|
|
158
|
+
3. **Enter the repository URL**:
|
|
159
|
+
```
|
|
160
|
+
https://github.com/zixflow/zixflow-ios.git
|
|
161
|
+
```
|
|
162
|
+
4. **Select the version**: Use `1.0.0` or higher
|
|
163
|
+
5. **Add the following modules** to your app target:
|
|
164
|
+
- `Zixflow` (umbrella module)
|
|
165
|
+
- `ZixflowDataPipelines`
|
|
166
|
+
- `ZixflowMessagingPushAPN`
|
|
167
|
+
- `ZixflowMessagingInApp`
|
|
108
168
|
|
|
109
|
-
|
|
169
|
+
> **Note**: The example app uses SPM for the native iOS SDK integration. See `example/ios/Podfile` for reference.
|
|
110
170
|
|
|
111
|
-
|
|
171
|
+
### Push Notification Setup (APNs)
|
|
112
172
|
|
|
113
|
-
|
|
114
|
-
Zixflow.track('Product Viewed', {
|
|
115
|
-
productId: '12345',
|
|
116
|
-
productName: 'Awesome Product',
|
|
117
|
-
price: 49.99,
|
|
118
|
-
category: 'Electronics',
|
|
119
|
-
});
|
|
120
|
-
```
|
|
173
|
+
To enable **Apple Push Notifications (APNs)**:
|
|
121
174
|
|
|
122
|
-
|
|
175
|
+
1. **Enable Push Notifications capability** in Xcode:
|
|
176
|
+
- Select your app target
|
|
177
|
+
- Go to **Signing & Capabilities**
|
|
178
|
+
- Click **+ Capability** and add **Push Notifications**
|
|
123
179
|
|
|
124
|
-
|
|
180
|
+
2. **Enable Background Modes**:
|
|
181
|
+
- Add **Background Modes** capability
|
|
182
|
+
- Enable **Remote notifications**
|
|
125
183
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
184
|
+
3. **Configure APNs certificates** in your Apple Developer account and upload them to Zixflow dashboard.
|
|
185
|
+
|
|
186
|
+
### Notification Service Extension
|
|
187
|
+
|
|
188
|
+
To support **rich push notifications** (images, videos, action buttons), you need to add a **Notification Service Extension**:
|
|
189
|
+
|
|
190
|
+
1. **Create a Notification Service Extension** in Xcode:
|
|
191
|
+
- File > New > Target > Notification Service Extension
|
|
192
|
+
- Name it `NotificationServiceExtension`
|
|
193
|
+
|
|
194
|
+
2. **Add Zixflow modules to the extension** in your `Podfile`:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
target 'NotificationServiceExtension' do
|
|
198
|
+
pod "ZixflowMessagingPushAPN", "~> 1.0"
|
|
199
|
+
pod "ZixflowMessagingPush", "~> 1.0"
|
|
200
|
+
pod "ZixflowDataPipelines", "~> 1.0"
|
|
201
|
+
pod "ZixflowCommon", "~> 1.0"
|
|
202
|
+
pod "ZixflowTrackingMigration", "~> 1.0"
|
|
203
|
+
pod "AnalyticsSwiftZixflow", "1.7.3+zixflow.1"
|
|
204
|
+
end
|
|
131
205
|
```
|
|
132
206
|
|
|
133
|
-
|
|
207
|
+
3. **Update `NotificationService.swift`**:
|
|
134
208
|
|
|
135
|
-
|
|
209
|
+
```swift
|
|
210
|
+
import UserNotifications
|
|
211
|
+
import ZixflowMessagingPushAPN
|
|
136
212
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
213
|
+
class NotificationService: UNNotificationServiceExtension {
|
|
214
|
+
var contentHandler: ((UNNotificationContent) -> Void)?
|
|
215
|
+
var bestAttemptContent: UNMutableNotificationContent?
|
|
216
|
+
|
|
217
|
+
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
|
218
|
+
self.contentHandler = contentHandler
|
|
219
|
+
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
|
220
|
+
|
|
221
|
+
// Use Zixflow to handle rich push
|
|
222
|
+
MessagingPushAPN.didReceive(request, withContentHandler: contentHandler)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override func serviceExtensionTimeWillExpire() {
|
|
226
|
+
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
|
227
|
+
contentHandler(bestAttemptContent)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
146
231
|
```
|
|
147
232
|
|
|
233
|
+
4. **Run `pod install`** again to install extension dependencies.
|
|
234
|
+
|
|
148
235
|
---
|
|
149
236
|
|
|
150
|
-
##
|
|
237
|
+
## Android Setup
|
|
238
|
+
|
|
239
|
+
### Gradle Configuration
|
|
240
|
+
|
|
241
|
+
The React Native auto-linking will handle most of the Android setup. However, you need to ensure the following:
|
|
242
|
+
|
|
243
|
+
1. **Set minimum SDK version** in `android/build.gradle`:
|
|
151
244
|
|
|
152
|
-
|
|
245
|
+
```gradle
|
|
246
|
+
buildscript {
|
|
247
|
+
ext {
|
|
248
|
+
minSdkVersion = 24
|
|
249
|
+
compileSdkVersion = 34
|
|
250
|
+
targetSdkVersion = 34
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
153
254
|
|
|
154
|
-
|
|
255
|
+
2. **Add Maven repositories** in `android/build.gradle`:
|
|
155
256
|
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
|
|
257
|
+
```gradle
|
|
258
|
+
allprojects {
|
|
259
|
+
repositories {
|
|
260
|
+
google()
|
|
261
|
+
mavenCentral()
|
|
262
|
+
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
159
265
|
```
|
|
160
266
|
|
|
161
|
-
|
|
267
|
+
The Zixflow Android SDK will be automatically included via the React Native module.
|
|
162
268
|
|
|
163
|
-
|
|
164
|
-
// Track when user receives a notification
|
|
165
|
-
Zixflow.pushMessaging.onMessageReceived((message) => {
|
|
166
|
-
console.log('Notification received:', message);
|
|
167
|
-
});
|
|
269
|
+
### Firebase Cloud Messaging Setup
|
|
168
270
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
271
|
+
To enable **Firebase Cloud Messaging (FCM)** for push notifications on Android:
|
|
272
|
+
|
|
273
|
+
1. **Add Firebase to your project**:
|
|
274
|
+
- Go to [Firebase Console](https://console.firebase.google.com/)
|
|
275
|
+
- Add your Android app
|
|
276
|
+
- Download `google-services.json` and place it in `android/app/`
|
|
277
|
+
|
|
278
|
+
2. **Add Google Services plugin** in `android/build.gradle`:
|
|
279
|
+
|
|
280
|
+
```gradle
|
|
281
|
+
buildscript {
|
|
282
|
+
dependencies {
|
|
283
|
+
classpath 'com.google.gms:google-services:4.4.2'
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
3. **Apply the plugin** in `android/app/build.gradle`:
|
|
289
|
+
|
|
290
|
+
```gradle
|
|
291
|
+
apply plugin: 'com.google.gms.google-services'
|
|
173
292
|
```
|
|
174
293
|
|
|
175
|
-
|
|
294
|
+
4. **Configure FCM in the SDK** (shown in the initialization section below).
|
|
176
295
|
|
|
177
296
|
---
|
|
178
297
|
|
|
179
|
-
##
|
|
298
|
+
## Quick Start
|
|
299
|
+
|
|
300
|
+
### Basic Configuration
|
|
180
301
|
|
|
181
|
-
|
|
302
|
+
The SDK is configured using a `ZixflowConfig` object with several options:
|
|
182
303
|
|
|
183
|
-
```
|
|
184
|
-
import {
|
|
304
|
+
```typescript
|
|
305
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
185
306
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
case InAppMessageEventType.MessageDismissed:
|
|
196
|
-
console.log('In-app message dismissed:', event.message);
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
});
|
|
307
|
+
const config: ZixflowConfig = {
|
|
308
|
+
apiKey: 'YOUR_API_KEY',
|
|
309
|
+
logLevel: ZixflowLogLevel.debug,
|
|
310
|
+
inApp: {
|
|
311
|
+
},
|
|
312
|
+
autoTrackDeviceAttributes: true,
|
|
313
|
+
trackApplicationLifecycleEvents: true,
|
|
314
|
+
};
|
|
315
|
+
```
|
|
200
316
|
|
|
201
|
-
|
|
202
|
-
|
|
317
|
+
**Configuration Options**:
|
|
318
|
+
|
|
319
|
+
| Option | Type | Required | Description |
|
|
320
|
+
|--------|------|----------|-------------|
|
|
321
|
+
| `apiKey` | string | Yes | Your Zixflow API key |
|
|
322
|
+
| `logLevel` | `ZixflowLogLevel` | No | Logging level (debug, info, error, none) |
|
|
323
|
+
| `inApp` | object | No | Enable in-app messaging (use empty object: {}) |
|
|
324
|
+
| `autoTrackDeviceAttributes` | boolean | No | Automatically track device info |
|
|
325
|
+
| `trackApplicationLifecycleEvents` | boolean | No | Automatically track app lifecycle |
|
|
326
|
+
|
|
327
|
+
### SDK Initialization
|
|
328
|
+
|
|
329
|
+
Initialize the SDK in your `App.tsx` or main component using `useEffect`:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
import React, { useEffect } from 'react';
|
|
333
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
334
|
+
|
|
335
|
+
export default function App() {
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
// Configure the SDK
|
|
338
|
+
const config: ZixflowConfig = {
|
|
339
|
+
apiKey: 'YOUR_API_KEY',
|
|
340
|
+
logLevel: ZixflowLogLevel.debug,
|
|
341
|
+
inApp: {
|
|
342
|
+
},
|
|
343
|
+
autoTrackDeviceAttributes: true,
|
|
344
|
+
trackApplicationLifecycleEvents: true,
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// Initialize the SDK
|
|
348
|
+
Zixflow.initialize(config);
|
|
349
|
+
|
|
350
|
+
console.log('Zixflow SDK initialized');
|
|
351
|
+
}, []);
|
|
352
|
+
|
|
353
|
+
return (
|
|
354
|
+
// Your app UI
|
|
355
|
+
);
|
|
356
|
+
}
|
|
203
357
|
```
|
|
204
358
|
|
|
205
|
-
|
|
359
|
+
> **Important**: Initialize the SDK as early as possible in your app's lifecycle, ideally in the root component's `useEffect`.
|
|
360
|
+
|
|
361
|
+
---
|
|
206
362
|
|
|
207
|
-
|
|
363
|
+
## Core Features
|
|
208
364
|
|
|
209
|
-
|
|
210
|
-
const inbox = Zixflow.inAppMessaging.inbox();
|
|
365
|
+
### User Identification
|
|
211
366
|
|
|
212
|
-
|
|
213
|
-
const messages = await inbox.getMessages();
|
|
367
|
+
Identify users to track their behavior across sessions and devices:
|
|
214
368
|
|
|
215
|
-
|
|
216
|
-
|
|
369
|
+
```typescript
|
|
370
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
217
371
|
|
|
218
|
-
//
|
|
219
|
-
|
|
372
|
+
// Identify user with ID only
|
|
373
|
+
Zixflow.identify({
|
|
374
|
+
userId: 'user-123'
|
|
375
|
+
});
|
|
220
376
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
377
|
+
// Identify user with traits
|
|
378
|
+
Zixflow.identify({
|
|
379
|
+
userId: 'user-123',
|
|
380
|
+
traits: {
|
|
381
|
+
email: 'user@example.com',
|
|
382
|
+
firstName: 'John',
|
|
383
|
+
lastName: 'Doe',
|
|
384
|
+
plan: 'premium'
|
|
385
|
+
}
|
|
224
386
|
});
|
|
225
387
|
```
|
|
226
388
|
|
|
227
|
-
|
|
389
|
+
**When to identify users**:
|
|
390
|
+
- After successful login
|
|
391
|
+
- When user information becomes available
|
|
392
|
+
- After account creation
|
|
393
|
+
|
|
394
|
+
### Event Tracking
|
|
395
|
+
|
|
396
|
+
Track custom events to understand user behavior:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
228
400
|
|
|
229
|
-
|
|
401
|
+
// Track event without properties
|
|
402
|
+
Zixflow.track('button_clicked');
|
|
230
403
|
|
|
231
|
-
Track
|
|
404
|
+
// Track event with properties
|
|
405
|
+
Zixflow.track('product_viewed', {
|
|
406
|
+
product_id: '12345',
|
|
407
|
+
product_name: 'Premium Plan',
|
|
408
|
+
category: 'subscription',
|
|
409
|
+
price: 29.99
|
|
410
|
+
});
|
|
232
411
|
|
|
233
|
-
|
|
234
|
-
|
|
412
|
+
// Track with Map (alternative syntax)
|
|
413
|
+
const properties = new Map<string, any>();
|
|
414
|
+
properties.set('item_count', 3);
|
|
415
|
+
properties.set('total_amount', 89.97);
|
|
416
|
+
Zixflow.track('checkout_completed', properties);
|
|
235
417
|
```
|
|
236
418
|
|
|
237
|
-
|
|
419
|
+
**Common events to track**:
|
|
420
|
+
- User actions (button clicks, form submissions)
|
|
421
|
+
- E-commerce events (product views, purchases)
|
|
422
|
+
- Content interactions (article reads, video plays)
|
|
423
|
+
- Feature usage
|
|
238
424
|
|
|
239
|
-
|
|
425
|
+
### Screen Tracking
|
|
240
426
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
427
|
+
Track screen views to understand user navigation:
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
431
|
+
|
|
432
|
+
// Track screen view
|
|
433
|
+
Zixflow.screen('HomeScreen');
|
|
434
|
+
|
|
435
|
+
// Track screen with properties
|
|
436
|
+
Zixflow.screen('ProductDetailScreen', {
|
|
437
|
+
product_id: '12345',
|
|
438
|
+
category: 'electronics'
|
|
439
|
+
});
|
|
246
440
|
```
|
|
247
441
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
442
|
+
**Automatic screen tracking** with React Navigation:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { NavigationContainer, NavigationContainerRef } from '@react-navigation/native';
|
|
446
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
447
|
+
import React, { useRef } from 'react';
|
|
448
|
+
|
|
449
|
+
export default function App() {
|
|
450
|
+
const navigationRef = useRef<NavigationContainerRef>(null);
|
|
451
|
+
const routeNameRef = useRef<string>();
|
|
452
|
+
|
|
453
|
+
return (
|
|
454
|
+
<NavigationContainer
|
|
455
|
+
ref={navigationRef}
|
|
456
|
+
onReady={() => {
|
|
457
|
+
routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name;
|
|
458
|
+
}}
|
|
459
|
+
onStateChange={async () => {
|
|
460
|
+
const previousRouteName = routeNameRef.current;
|
|
461
|
+
const currentRouteName = navigationRef.current?.getCurrentRoute()?.name;
|
|
462
|
+
|
|
463
|
+
if (previousRouteName !== currentRouteName && currentRouteName) {
|
|
464
|
+
// Track screen change
|
|
465
|
+
Zixflow.screen(currentRouteName);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Save current route name
|
|
469
|
+
routeNameRef.current = currentRouteName;
|
|
470
|
+
}}
|
|
471
|
+
>
|
|
472
|
+
{/* Your navigation setup */}
|
|
473
|
+
</NavigationContainer>
|
|
474
|
+
);
|
|
475
|
+
}
|
|
251
476
|
```
|
|
252
477
|
|
|
253
|
-
###
|
|
478
|
+
### User Profile Attributes
|
|
254
479
|
|
|
255
|
-
|
|
256
|
-
```properties
|
|
257
|
-
zixflow_location_enabled=true
|
|
258
|
-
```
|
|
480
|
+
Set custom attributes on user profiles:
|
|
259
481
|
|
|
260
|
-
|
|
482
|
+
```typescript
|
|
483
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
261
484
|
|
|
262
|
-
|
|
485
|
+
// Set profile attributes
|
|
486
|
+
Zixflow.setProfileAttributes({
|
|
487
|
+
plan: 'premium',
|
|
488
|
+
subscription_status: 'active',
|
|
489
|
+
last_login: new Date().toISOString(),
|
|
490
|
+
preferences: {
|
|
491
|
+
newsletter: true,
|
|
492
|
+
notifications: true
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
```
|
|
263
496
|
|
|
264
497
|
### Device Attributes
|
|
265
498
|
|
|
266
|
-
Set custom device
|
|
499
|
+
Set custom attributes on the current device:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
267
503
|
|
|
268
|
-
|
|
504
|
+
// Set device attributes
|
|
269
505
|
Zixflow.setDeviceAttributes({
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
506
|
+
app_version: '2.1.0',
|
|
507
|
+
build_number: '421',
|
|
508
|
+
theme: 'dark',
|
|
509
|
+
language_preference: 'en-US'
|
|
273
510
|
});
|
|
274
511
|
```
|
|
275
512
|
|
|
276
|
-
###
|
|
513
|
+
### Clearing User Identity
|
|
514
|
+
|
|
515
|
+
Clear user identity when users log out:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
277
519
|
|
|
278
|
-
|
|
520
|
+
// Clear identify on logout
|
|
521
|
+
const handleLogout = async () => {
|
|
522
|
+
// Clear Zixflow identity
|
|
523
|
+
Zixflow.clearIdentify();
|
|
279
524
|
|
|
280
|
-
|
|
281
|
-
|
|
525
|
+
// Perform other logout actions
|
|
526
|
+
// ...
|
|
527
|
+
};
|
|
282
528
|
```
|
|
283
529
|
|
|
284
|
-
|
|
530
|
+
---
|
|
285
531
|
|
|
286
|
-
|
|
532
|
+
## Push Notifications
|
|
287
533
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
534
|
+
Complete guide to implementing push notifications in React Native with Zixflow using Apple Push Notifications (APNs) or Firebase Cloud Messaging (FCM).
|
|
535
|
+
|
|
536
|
+
### Prerequisites
|
|
537
|
+
|
|
538
|
+
Before implementing push notifications:
|
|
539
|
+
|
|
540
|
+
1. **Configure push credentials in Zixflow dashboard** - Add APNs certificates or FCM Server Key
|
|
541
|
+
2. **Complete iOS/Android native setup** - Ensure native dependencies are installed
|
|
542
|
+
3. **Device tokens must be associated with users** - Call `identify()` before sending notifications
|
|
543
|
+
|
|
544
|
+
**Important Limitation**: The Zixflow React Native SDK currently supports deep links and images in push notifications. Custom action buttons require additional native code.
|
|
291
545
|
|
|
292
546
|
---
|
|
293
547
|
|
|
294
|
-
|
|
548
|
+
### Platform-Specific Requirements
|
|
549
|
+
|
|
550
|
+
#### iOS Requirements
|
|
551
|
+
|
|
552
|
+
- **APNs or FCM**: Choose either Apple Push Notification service or Firebase Cloud Messaging
|
|
553
|
+
- **Xcode Capabilities**: Push Notifications and Background Modes
|
|
554
|
+
- **Notification Service Extension**: Required for rich push (images, videos)
|
|
555
|
+
- **Physical Device**: iOS Simulator cannot receive push notifications
|
|
556
|
+
|
|
557
|
+
#### Android Requirements
|
|
558
|
+
|
|
559
|
+
- **Firebase Project**: Required for FCM integration
|
|
560
|
+
- **google-services.json**: Must be in `android/app/` directory
|
|
561
|
+
- **Minimum API Level 24**: Android 7.0 or higher
|
|
562
|
+
- **POST_NOTIFICATIONS Permission**: Required for Android 13+ (API 33+)
|
|
563
|
+
|
|
564
|
+
---
|
|
295
565
|
|
|
296
566
|
### iOS Setup
|
|
297
567
|
|
|
298
|
-
|
|
568
|
+
You can use either **APNs (Apple Push Notification service)** or **FCM (Firebase Cloud Messaging)** on iOS.
|
|
569
|
+
|
|
570
|
+
#### Step 1: Enable Push Capabilities in Xcode
|
|
571
|
+
|
|
572
|
+
1. Open your project's `.xcworkspace` file in Xcode
|
|
573
|
+
2. Select your app target
|
|
574
|
+
3. Go to **Signing & Capabilities** tab
|
|
575
|
+
4. Click **+ Capability** → Add **Push Notifications**
|
|
576
|
+
5. Click **+ Capability** → Add **Background Modes**
|
|
577
|
+
6. Enable **Remote notifications** under Background Modes
|
|
578
|
+
|
|
579
|
+
#### Step 2: Choose APNs or FCM
|
|
580
|
+
|
|
581
|
+
**Option A: APNs (Recommended for iOS-only apps)**
|
|
582
|
+
|
|
583
|
+
Update your `ios/Podfile`:
|
|
299
584
|
|
|
300
585
|
```ruby
|
|
301
|
-
|
|
586
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
587
|
+
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
588
|
+
|
|
589
|
+
platform :ios, '13.0'
|
|
590
|
+
|
|
591
|
+
target 'YourApp' do
|
|
592
|
+
config = use_native_modules!
|
|
302
593
|
|
|
303
|
-
|
|
304
|
-
pod 'zixflow-reactnative/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
594
|
+
use_react_native!(:path => config[:reactNativePath])
|
|
305
595
|
|
|
306
|
-
#
|
|
307
|
-
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
596
|
+
# Add Zixflow with APNs support
|
|
597
|
+
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
308
598
|
|
|
309
|
-
#
|
|
310
|
-
|
|
599
|
+
# Your other dependencies...
|
|
600
|
+
end
|
|
311
601
|
```
|
|
312
602
|
|
|
313
|
-
|
|
603
|
+
**Option B: FCM (For cross-platform Firebase apps)**
|
|
314
604
|
|
|
315
|
-
|
|
605
|
+
Update your `ios/Podfile` with static linkage:
|
|
316
606
|
|
|
317
|
-
|
|
607
|
+
```ruby
|
|
608
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
609
|
+
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
318
610
|
|
|
319
|
-
|
|
611
|
+
platform :ios, '13.0'
|
|
320
612
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
- **Gradle**: 8.11.1 or higher
|
|
324
|
-
- **minSdkVersion**: 21 or higher
|
|
325
|
-
- **Kotlin**: 1.9.25 or higher
|
|
613
|
+
# Required for FCM
|
|
614
|
+
use_frameworks! :linkage => :static
|
|
326
615
|
|
|
327
|
-
|
|
616
|
+
target 'YourApp' do
|
|
617
|
+
config = use_native_modules!
|
|
328
618
|
|
|
329
|
-
|
|
619
|
+
use_react_native!(:path => config[:reactNativePath])
|
|
330
620
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
minSdkVersion = 21
|
|
337
|
-
targetSdkVersion = 36
|
|
338
|
-
}
|
|
339
|
-
dependencies {
|
|
340
|
-
classpath("com.android.tools.build:gradle:8.9.1")
|
|
341
|
-
}
|
|
342
|
-
}
|
|
621
|
+
# Add Zixflow with FCM support
|
|
622
|
+
pod 'zixflow-reactnative/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
623
|
+
|
|
624
|
+
# Your other dependencies...
|
|
625
|
+
end
|
|
343
626
|
```
|
|
344
627
|
|
|
345
|
-
|
|
628
|
+
**Install dependencies:**
|
|
346
629
|
|
|
347
|
-
```
|
|
348
|
-
|
|
630
|
+
```bash
|
|
631
|
+
cd ios
|
|
632
|
+
pod install
|
|
633
|
+
cd ..
|
|
349
634
|
```
|
|
350
635
|
|
|
351
|
-
3
|
|
636
|
+
#### Step 3: Configure AppDelegate (Swift - Recommended)
|
|
352
637
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
638
|
+
For modern Swift-based React Native apps with APNs:
|
|
639
|
+
|
|
640
|
+
**AppDelegate.swift:**
|
|
641
|
+
|
|
642
|
+
```swift
|
|
643
|
+
import UIKit
|
|
644
|
+
import ZixflowMessagingPushAPN
|
|
645
|
+
|
|
646
|
+
@main
|
|
647
|
+
class AppDelegateWithZixflowIntegration: ZixflowAppDelegateWrapper<AppDelegate> {}
|
|
648
|
+
|
|
649
|
+
class AppDelegate: NSObject, UIApplicationDelegate {
|
|
650
|
+
|
|
651
|
+
func application(
|
|
652
|
+
_ application: UIApplication,
|
|
653
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
654
|
+
) -> Bool {
|
|
655
|
+
// Set notification delegate
|
|
656
|
+
UNUserNotificationCenter.current().delegate = self
|
|
657
|
+
|
|
658
|
+
// Initialize Zixflow push messaging (APNs)
|
|
659
|
+
MessagingPushAPN.initialize(
|
|
660
|
+
withConfig: MessagingPushConfigBuilder()
|
|
661
|
+
.build()
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
return true
|
|
665
|
+
}
|
|
356
666
|
}
|
|
357
667
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
668
|
+
extension AppDelegate: UNUserNotificationCenterDelegate {
|
|
669
|
+
// Show notifications when app is in foreground
|
|
670
|
+
func userNotificationCenter(
|
|
671
|
+
_ center: UNUserNotificationCenter,
|
|
672
|
+
willPresent notification: UNNotification,
|
|
673
|
+
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
|
674
|
+
) {
|
|
675
|
+
completionHandler([.banner, .list, .badge, .sound])
|
|
676
|
+
}
|
|
362
677
|
}
|
|
363
678
|
```
|
|
364
679
|
|
|
365
|
-
|
|
680
|
+
**For FCM**, import `ZixflowMessagingPushFCM` instead:
|
|
366
681
|
|
|
367
|
-
|
|
682
|
+
```swift
|
|
683
|
+
import ZixflowMessagingPushFCM
|
|
368
684
|
|
|
369
|
-
|
|
370
|
-
|
|
685
|
+
// Initialize with FCM
|
|
686
|
+
MessagingPushFCM.initialize(
|
|
687
|
+
withConfig: MessagingPushConfigBuilder()
|
|
688
|
+
.build()
|
|
689
|
+
)
|
|
371
690
|
```
|
|
372
691
|
|
|
373
|
-
|
|
692
|
+
#### Step 4: Configure AppDelegate (Objective-C)
|
|
374
693
|
|
|
375
|
-
|
|
694
|
+
If your React Native app uses Objective-C, create a Swift bridge:
|
|
376
695
|
|
|
377
|
-
|
|
696
|
+
**Create `MyAppPushNotificationsHandler.swift`:**
|
|
378
697
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
| `migrationSiteId` | `string` | ❌ | Site ID for migration from older SDKs |
|
|
383
|
-
| `logLevel` | `ZixflowLogLevel` | ❌ | Logging verbosity (default: error) |
|
|
384
|
-
| `trackApplicationLifecycleEvents` | `boolean` | ❌ | Auto-track app lifecycle events |
|
|
385
|
-
| `inApp` | `object` | ❌ | In-app messaging configuration |
|
|
386
|
-
| `push` | `object` | ❌ | Push notification configuration |
|
|
698
|
+
```swift
|
|
699
|
+
import Foundation
|
|
700
|
+
import ZixflowMessagingPushAPN
|
|
387
701
|
|
|
388
|
-
|
|
702
|
+
@objc
|
|
703
|
+
public class MyAppPushNotificationsHandler: NSObject {
|
|
389
704
|
|
|
390
|
-
|
|
705
|
+
@objc(setupZixflowClickHandling)
|
|
706
|
+
public func setupZixflowClickHandling() {
|
|
707
|
+
MessagingPushAPN.initialize(
|
|
708
|
+
withConfig: MessagingPushConfigBuilder().build()
|
|
709
|
+
)
|
|
710
|
+
}
|
|
391
711
|
|
|
392
|
-
|
|
712
|
+
@objc(application:deviceToken:)
|
|
713
|
+
public func application(
|
|
714
|
+
_ application: UIApplication,
|
|
715
|
+
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
|
716
|
+
) {
|
|
717
|
+
MessagingPush.shared.application(
|
|
718
|
+
application,
|
|
719
|
+
didRegisterForRemoteNotificationsWithDeviceToken: deviceToken
|
|
720
|
+
)
|
|
721
|
+
}
|
|
393
722
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
} from 'zixflow-reactnative';
|
|
723
|
+
@objc(application:error:)
|
|
724
|
+
public func application(
|
|
725
|
+
_ application: UIApplication,
|
|
726
|
+
didFailToRegisterForRemoteNotificationsWithError error: Error
|
|
727
|
+
) {
|
|
728
|
+
MessagingPush.shared.application(
|
|
729
|
+
application,
|
|
730
|
+
didFailToRegisterForRemoteNotificationsWithError: error
|
|
731
|
+
)
|
|
732
|
+
}
|
|
733
|
+
}
|
|
406
734
|
```
|
|
407
735
|
|
|
408
|
-
|
|
736
|
+
**Update `AppDelegate.mm`:**
|
|
737
|
+
|
|
738
|
+
```objc
|
|
739
|
+
#import "YourApp-Swift.h"
|
|
740
|
+
|
|
741
|
+
@implementation AppDelegate
|
|
409
742
|
|
|
410
|
-
|
|
743
|
+
MyAppPushNotificationsHandler* pnHandlerObj;
|
|
411
744
|
|
|
412
|
-
|
|
745
|
+
- (BOOL)application:(UIApplication *)application
|
|
746
|
+
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
|
747
|
+
// ... existing initialization code ...
|
|
413
748
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
Zixflow.inAppMessaging.registerEventsListener(listener);
|
|
749
|
+
// Register for remote notifications
|
|
750
|
+
[application registerForRemoteNotifications];
|
|
417
751
|
|
|
418
|
-
//
|
|
419
|
-
|
|
752
|
+
// Initialize push handling
|
|
753
|
+
pnHandlerObj = [[MyAppPushNotificationsHandler alloc] init];
|
|
754
|
+
[pnHandlerObj setupZixflowClickHandling];
|
|
420
755
|
|
|
421
|
-
|
|
422
|
-
|
|
756
|
+
return YES;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
- (void)application:(UIApplication *)application
|
|
760
|
+
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
|
|
761
|
+
[pnHandlerObj application:application deviceToken:deviceToken];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
- (void)application:(UIApplication *)application
|
|
765
|
+
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
|
766
|
+
[pnHandlerObj application:application error:error];
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
@end
|
|
423
770
|
```
|
|
424
771
|
|
|
425
|
-
|
|
772
|
+
#### Step 5: Rich Push with Notification Service Extension
|
|
426
773
|
|
|
427
|
-
|
|
774
|
+
To support rich push notifications (images, videos, GIFs), add a Notification Service Extension:
|
|
428
775
|
|
|
429
|
-
|
|
776
|
+
**1. Create Notification Service Extension:**
|
|
430
777
|
|
|
431
|
-
|
|
778
|
+
1. In Xcode: **File** → **New** → **Target**
|
|
779
|
+
2. Select **Notification Service Extension**
|
|
780
|
+
3. Name it `NotificationServiceExtension`
|
|
781
|
+
4. Click **Finish** (activate scheme when prompted)
|
|
432
782
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
783
|
+
**2. Add Zixflow to Extension:**
|
|
784
|
+
|
|
785
|
+
Update your `ios/Podfile` to include the extension:
|
|
786
|
+
|
|
787
|
+
```ruby
|
|
788
|
+
# Main app target
|
|
789
|
+
target 'YourApp' do
|
|
790
|
+
# ... existing configuration ...
|
|
791
|
+
pod 'zixflow-reactnative/apn', :path => '../node_modules/zixflow-reactnative'
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
# Notification Service Extension target
|
|
795
|
+
target 'NotificationServiceExtension' do
|
|
796
|
+
pod 'zixflow-reactnative-richpush/apn', :path => '../node_modules/zixflow-reactnative'
|
|
797
|
+
end
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
For FCM:
|
|
801
|
+
|
|
802
|
+
```ruby
|
|
803
|
+
target 'NotificationServiceExtension' do
|
|
804
|
+
pod 'zixflow-reactnative-richpush/fcm', :path => '../node_modules/zixflow-reactnative'
|
|
805
|
+
end
|
|
806
|
+
```
|
|
440
807
|
|
|
441
|
-
|
|
808
|
+
**3. Install dependencies:**
|
|
442
809
|
|
|
443
810
|
```bash
|
|
444
|
-
cd
|
|
445
|
-
|
|
811
|
+
cd ios
|
|
812
|
+
pod install
|
|
813
|
+
cd ..
|
|
814
|
+
```
|
|
446
815
|
|
|
447
|
-
|
|
448
|
-
cd ios && pod install && cd ..
|
|
449
|
-
npx react-native run-ios
|
|
816
|
+
**4. Update `NotificationService.swift`:**
|
|
450
817
|
|
|
451
|
-
|
|
452
|
-
|
|
818
|
+
```swift
|
|
819
|
+
import UserNotifications
|
|
820
|
+
import ZixflowMessagingPushAPN
|
|
821
|
+
|
|
822
|
+
class NotificationService: UNNotificationServiceExtension {
|
|
823
|
+
var contentHandler: ((UNNotificationContent) -> Void)?
|
|
824
|
+
var bestAttemptContent: UNMutableNotificationContent?
|
|
825
|
+
|
|
826
|
+
override func didReceive(
|
|
827
|
+
_ request: UNNotificationRequest,
|
|
828
|
+
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
|
829
|
+
) {
|
|
830
|
+
self.contentHandler = contentHandler
|
|
831
|
+
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
|
832
|
+
|
|
833
|
+
// Initialize SDK for extension
|
|
834
|
+
MessagingPushAPN.initializeForExtension(
|
|
835
|
+
withConfig: MessagingPushConfigBuilder(apiKey: "YOUR_API_KEY")
|
|
836
|
+
.build()
|
|
837
|
+
)
|
|
838
|
+
|
|
839
|
+
if let bestAttemptContent = bestAttemptContent {
|
|
840
|
+
// Let Zixflow handle rich push and track delivery
|
|
841
|
+
MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
override func serviceExtensionTimeWillExpire() {
|
|
846
|
+
// Called when extension is about to be terminated
|
|
847
|
+
MessagingPush.shared.serviceExtensionTimeWillExpire()
|
|
848
|
+
|
|
849
|
+
if let contentHandler = contentHandler,
|
|
850
|
+
let bestAttemptContent = bestAttemptContent {
|
|
851
|
+
contentHandler(bestAttemptContent)
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
453
855
|
```
|
|
454
856
|
|
|
857
|
+
**Important:** Replace `"YOUR_API_KEY"` with your actual API key.
|
|
858
|
+
|
|
455
859
|
---
|
|
456
860
|
|
|
457
|
-
|
|
861
|
+
### Android Setup
|
|
458
862
|
|
|
459
|
-
|
|
863
|
+
Android push notifications use Firebase Cloud Messaging (FCM).
|
|
460
864
|
|
|
461
|
-
|
|
462
|
-
- Run `pod install` in your iOS directory
|
|
463
|
-
- Make sure you're using the correct pod name: `zixflow-reactnative`
|
|
865
|
+
#### Step 1: Add Firebase to Your Project
|
|
464
866
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
867
|
+
1. Go to [Firebase Console](https://console.firebase.google.com/)
|
|
868
|
+
2. Add your Android app to Firebase project
|
|
869
|
+
3. Download `google-services.json`
|
|
870
|
+
4. Place `google-services.json` in `android/app/` directory
|
|
469
871
|
|
|
470
|
-
|
|
471
|
-
- Verify you've configured `inApp.siteId` in the config
|
|
472
|
-
- Check that you've registered an events listener
|
|
473
|
-
- Ensure messages are targeted correctly in your Zixflow dashboard
|
|
872
|
+
#### Step 2: Configure Gradle
|
|
474
873
|
|
|
475
|
-
|
|
874
|
+
**Project-level `android/build.gradle`:**
|
|
476
875
|
|
|
477
|
-
|
|
876
|
+
```gradle
|
|
877
|
+
buildscript {
|
|
878
|
+
ext {
|
|
879
|
+
minSdkVersion = 24
|
|
880
|
+
compileSdkVersion = 34
|
|
881
|
+
targetSdkVersion = 34
|
|
882
|
+
}
|
|
478
883
|
|
|
479
|
-
|
|
884
|
+
dependencies {
|
|
885
|
+
classpath 'com.google.gms:google-services:4.4.2'
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
allprojects {
|
|
890
|
+
repositories {
|
|
891
|
+
google()
|
|
892
|
+
mavenCentral()
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
```
|
|
480
896
|
|
|
481
|
-
-
|
|
482
|
-
- iOS 13+
|
|
483
|
-
- Android API 21+ (Android 5.0 Lollipop)
|
|
484
|
-
- Swift 5.3+
|
|
485
|
-
- Kotlin 1.8+
|
|
897
|
+
**App-level `android/app/build.gradle`:**
|
|
486
898
|
|
|
487
|
-
|
|
899
|
+
```gradle
|
|
900
|
+
apply plugin: 'com.android.application'
|
|
901
|
+
apply plugin: 'com.google.gms.google-services' // Add this line
|
|
488
902
|
|
|
489
|
-
|
|
903
|
+
android {
|
|
904
|
+
// ... existing configuration ...
|
|
905
|
+
}
|
|
490
906
|
|
|
491
|
-
|
|
907
|
+
dependencies {
|
|
908
|
+
// React Native auto-linking handles Zixflow dependencies
|
|
909
|
+
// ... your other dependencies ...
|
|
910
|
+
}
|
|
911
|
+
```
|
|
492
912
|
|
|
493
|
-
|
|
494
|
-
2. Follow our [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
495
|
-
3. Check out [DEVELOPMENT.md](DEVELOPMENT.md) for development guidelines
|
|
496
|
-
4. Open issues or pull requests on [GitHub](https://github.com/zixflow/zixflow-reactnative)
|
|
913
|
+
#### Step 3: Add Permissions
|
|
497
914
|
|
|
498
|
-
|
|
915
|
+
Add to `android/app/src/main/AndroidManifest.xml`:
|
|
499
916
|
|
|
500
|
-
|
|
917
|
+
```xml
|
|
918
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
501
919
|
|
|
502
|
-
|
|
503
|
-
-
|
|
504
|
-
- 🐛 [Issue Tracker](https://github.com/zixflow/zixflow-reactnative/issues)
|
|
505
|
-
- 📧 Email: apps@zixflow.com
|
|
920
|
+
<!-- Required for push notifications -->
|
|
921
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
506
922
|
|
|
507
|
-
|
|
923
|
+
<!-- Required for Android 13+ (API 33+) -->
|
|
924
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
508
925
|
|
|
509
|
-
|
|
926
|
+
<application>
|
|
927
|
+
<!-- Your app configuration -->
|
|
928
|
+
</application>
|
|
929
|
+
</manifest>
|
|
930
|
+
```
|
|
510
931
|
|
|
511
|
-
|
|
932
|
+
#### Step 4: Configure Notification Icon and Color (Optional)
|
|
512
933
|
|
|
513
|
-
|
|
934
|
+
Add to `android/app/src/main/AndroidManifest.xml` inside `<application>` tag:
|
|
514
935
|
|
|
515
|
-
|
|
936
|
+
```xml
|
|
937
|
+
<application>
|
|
938
|
+
<!-- Default notification icon (white, transparent background) -->
|
|
939
|
+
<meta-data
|
|
940
|
+
android:name="com.google.firebase.messaging.default_notification_icon"
|
|
941
|
+
android:resource="@drawable/ic_notification" />
|
|
942
|
+
|
|
943
|
+
<!-- Default notification color (accent color) -->
|
|
944
|
+
<meta-data
|
|
945
|
+
android:name="com.google.firebase.messaging.default_notification_color"
|
|
946
|
+
android:resource="@color/notification_color" />
|
|
947
|
+
</application>
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
---
|
|
951
|
+
|
|
952
|
+
### React Native Integration
|
|
953
|
+
|
|
954
|
+
#### Step 1: Initialize SDK
|
|
955
|
+
|
|
956
|
+
Initialize the Zixflow SDK in your `App.tsx`:
|
|
957
|
+
|
|
958
|
+
```typescript
|
|
959
|
+
import React, { useEffect } from 'react';
|
|
960
|
+
import { Zixflow, ZixflowConfig, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
961
|
+
|
|
962
|
+
export default function App() {
|
|
963
|
+
useEffect(() => {
|
|
964
|
+
// Configure the SDK
|
|
965
|
+
const config: ZixflowConfig = {
|
|
966
|
+
apiKey: 'YOUR_API_KEY',
|
|
967
|
+
logLevel: ZixflowLogLevel.debug,
|
|
968
|
+
inApp: {
|
|
969
|
+
},
|
|
970
|
+
autoTrackDeviceAttributes: true,
|
|
971
|
+
trackApplicationLifecycleEvents: true,
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
// Initialize the SDK
|
|
975
|
+
Zixflow.initialize(config);
|
|
976
|
+
|
|
977
|
+
console.log('Zixflow SDK initialized');
|
|
978
|
+
}, []);
|
|
979
|
+
|
|
980
|
+
return (
|
|
981
|
+
// Your app UI
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
#### Step 2: Request Push Permission
|
|
987
|
+
|
|
988
|
+
Request permission to send push notifications:
|
|
989
|
+
|
|
990
|
+
```typescript
|
|
991
|
+
import React, { useState } from 'react';
|
|
992
|
+
import { Button, Alert } from 'react-native';
|
|
993
|
+
import { Zixflow, ZixflowPushPermissionStatus } from 'zixflow-reactnative';
|
|
994
|
+
|
|
995
|
+
export default function PushPermissionButton() {
|
|
996
|
+
const [permissionStatus, setPermissionStatus] = useState<ZixflowPushPermissionStatus | null>(null);
|
|
997
|
+
|
|
998
|
+
const requestPushPermission = async () => {
|
|
999
|
+
try {
|
|
1000
|
+
const permission = await Zixflow.pushMessaging.showPromptForPushNotifications({
|
|
1001
|
+
ios: {
|
|
1002
|
+
sound: true,
|
|
1003
|
+
badge: true,
|
|
1004
|
+
alert: true,
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
setPermissionStatus(permission);
|
|
1009
|
+
|
|
1010
|
+
switch (permission) {
|
|
1011
|
+
case ZixflowPushPermissionStatus.Granted:
|
|
1012
|
+
Alert.alert('Success', 'Push notifications enabled!');
|
|
1013
|
+
console.log('Push notifications enabled');
|
|
1014
|
+
break;
|
|
1015
|
+
|
|
1016
|
+
case ZixflowPushPermissionStatus.Denied:
|
|
1017
|
+
Alert.alert('Denied', 'Push notification permission was denied');
|
|
1018
|
+
console.log('Push notifications denied');
|
|
1019
|
+
break;
|
|
1020
|
+
|
|
1021
|
+
case ZixflowPushPermissionStatus.NotDetermined:
|
|
1022
|
+
// iOS only: permission not yet asked
|
|
1023
|
+
console.log('Push notification permission not determined');
|
|
1024
|
+
break;
|
|
1025
|
+
}
|
|
1026
|
+
} catch (error) {
|
|
1027
|
+
console.error('Failed to request push permission:', error);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
|
|
1031
|
+
return (
|
|
1032
|
+
<Button
|
|
1033
|
+
title="Enable Push Notifications"
|
|
1034
|
+
onPress={requestPushPermission}
|
|
1035
|
+
/>
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
**Permission Options (iOS)**:
|
|
1041
|
+
|
|
1042
|
+
| Option | Type | Description |
|
|
1043
|
+
|--------|------|-------------|
|
|
1044
|
+
| `sound` | boolean | Enable notification sounds |
|
|
1045
|
+
| `badge` | boolean | Enable app badge updates |
|
|
1046
|
+
| `alert` | boolean | Show notification alerts |
|
|
1047
|
+
|
|
1048
|
+
#### Step 3: Check Permission Status
|
|
1049
|
+
|
|
1050
|
+
Check current push permission status:
|
|
1051
|
+
|
|
1052
|
+
```typescript
|
|
1053
|
+
import { Zixflow, ZixflowPushPermissionStatus } from 'zixflow-reactnative';
|
|
1054
|
+
|
|
1055
|
+
const checkPushPermission = async () => {
|
|
1056
|
+
try {
|
|
1057
|
+
const status = await Zixflow.pushMessaging.getPushPermissionStatus();
|
|
1058
|
+
|
|
1059
|
+
console.log('Push permission status:', status);
|
|
1060
|
+
|
|
1061
|
+
if (status === ZixflowPushPermissionStatus.Granted) {
|
|
1062
|
+
console.log('Push notifications are enabled');
|
|
1063
|
+
} else if (status === ZixflowPushPermissionStatus.Denied) {
|
|
1064
|
+
console.log('Push notifications are disabled');
|
|
1065
|
+
} else {
|
|
1066
|
+
console.log('Push permission not determined');
|
|
1067
|
+
}
|
|
1068
|
+
} catch (error) {
|
|
1069
|
+
console.error('Failed to get push permission status:', error);
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
#### Step 4: Identify Users
|
|
1075
|
+
|
|
1076
|
+
**Critical**: Device tokens must be associated with a user before push notifications can be delivered.
|
|
1077
|
+
|
|
1078
|
+
```typescript
|
|
1079
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1080
|
+
|
|
1081
|
+
// Identify user when they log in
|
|
1082
|
+
const handleLogin = async (userId: string, userEmail: string) => {
|
|
1083
|
+
try {
|
|
1084
|
+
// Identify user with Zixflow
|
|
1085
|
+
Zixflow.identify({
|
|
1086
|
+
userId: userId,
|
|
1087
|
+
traits: {
|
|
1088
|
+
email: userEmail,
|
|
1089
|
+
firstName: 'John',
|
|
1090
|
+
lastName: 'Doe',
|
|
1091
|
+
plan: 'premium',
|
|
1092
|
+
},
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
console.log('User identified:', userId);
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
console.error('Failed to identify user:', error);
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
**Important Notes:**
|
|
1103
|
+
- When users start the app, they automatically generate a device token
|
|
1104
|
+
- This token links to their Zixflow profile when you call `identify()`
|
|
1105
|
+
- Device tokens are automatically removed from previous profiles when identifying new users
|
|
1106
|
+
- This prevents duplicate notifications when users switch accounts
|
|
1107
|
+
|
|
1108
|
+
#### Step 5: Get Device Token
|
|
1109
|
+
|
|
1110
|
+
Retrieve the registered device token:
|
|
1111
|
+
|
|
1112
|
+
```typescript
|
|
1113
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1114
|
+
|
|
1115
|
+
const getDeviceToken = async () => {
|
|
1116
|
+
try {
|
|
1117
|
+
const token = await Zixflow.pushMessaging.getRegisteredDeviceToken();
|
|
1118
|
+
console.log('Device token:', token);
|
|
1119
|
+
return token;
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
console.error('Failed to get device token:', error);
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
---
|
|
1128
|
+
|
|
1129
|
+
### Deep Links and Navigation
|
|
1130
|
+
|
|
1131
|
+
Handle deep links from push notifications:
|
|
1132
|
+
|
|
1133
|
+
#### Setup Deep Linking
|
|
1134
|
+
|
|
1135
|
+
**1. Configure Deep Links (iOS):**
|
|
1136
|
+
|
|
1137
|
+
Add to `ios/YourApp/Info.plist`:
|
|
1138
|
+
|
|
1139
|
+
```xml
|
|
1140
|
+
<key>CFBundleURLTypes</key>
|
|
1141
|
+
<array>
|
|
1142
|
+
<dict>
|
|
1143
|
+
<key>CFBundleURLSchemes</key>
|
|
1144
|
+
<array>
|
|
1145
|
+
<string>yourapp</string>
|
|
1146
|
+
</array>
|
|
1147
|
+
</dict>
|
|
1148
|
+
</array>
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
**2. Configure Deep Links (Android):**
|
|
1152
|
+
|
|
1153
|
+
Add to `android/app/src/main/AndroidManifest.xml`:
|
|
1154
|
+
|
|
1155
|
+
```xml
|
|
1156
|
+
<activity android:name=".MainActivity">
|
|
1157
|
+
<!-- Existing intent filter -->
|
|
1158
|
+
|
|
1159
|
+
<!-- Deep link intent filter -->
|
|
1160
|
+
<intent-filter>
|
|
1161
|
+
<action android:name="android.intent.action.VIEW" />
|
|
1162
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
1163
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
1164
|
+
|
|
1165
|
+
<data
|
|
1166
|
+
android:scheme="yourapp"
|
|
1167
|
+
android:host="*" />
|
|
1168
|
+
</intent-filter>
|
|
1169
|
+
|
|
1170
|
+
<!-- Universal Links (optional) -->
|
|
1171
|
+
<intent-filter android:autoVerify="true">
|
|
1172
|
+
<action android:name="android.intent.action.VIEW" />
|
|
1173
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
1174
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
1175
|
+
|
|
1176
|
+
<data
|
|
1177
|
+
android:scheme="https"
|
|
1178
|
+
android:host="yourapp.com" />
|
|
1179
|
+
</intent-filter>
|
|
1180
|
+
</activity>
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
#### Handle Deep Links in React Native
|
|
1184
|
+
|
|
1185
|
+
Use React Navigation's linking configuration:
|
|
1186
|
+
|
|
1187
|
+
```typescript
|
|
1188
|
+
import React from 'react';
|
|
1189
|
+
import { NavigationContainer } from '@react-navigation/native';
|
|
1190
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
1191
|
+
import { Linking } from 'react-native';
|
|
1192
|
+
|
|
1193
|
+
const Stack = createNativeStackNavigator();
|
|
1194
|
+
|
|
1195
|
+
const linking = {
|
|
1196
|
+
prefixes: ['yourapp://', 'https://yourapp.com'],
|
|
1197
|
+
config: {
|
|
1198
|
+
screens: {
|
|
1199
|
+
Home: 'home',
|
|
1200
|
+
Product: 'product/:id',
|
|
1201
|
+
Profile: 'profile',
|
|
1202
|
+
},
|
|
1203
|
+
},
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
export default function App() {
|
|
1207
|
+
return (
|
|
1208
|
+
<NavigationContainer linking={linking}>
|
|
1209
|
+
<Stack.Navigator>
|
|
1210
|
+
<Stack.Screen name="Home" component={HomeScreen} />
|
|
1211
|
+
<Stack.Screen name="Product" component={ProductScreen} />
|
|
1212
|
+
<Stack.Screen name="Profile" component={ProfileScreen} />
|
|
1213
|
+
</Stack.Navigator>
|
|
1214
|
+
</NavigationContainer>
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
---
|
|
1220
|
+
|
|
1221
|
+
### Rich Push Notification Payloads
|
|
1222
|
+
|
|
1223
|
+
The Zixflow SDK automatically handles rich push notifications. Here's how to structure payloads:
|
|
1224
|
+
|
|
1225
|
+
#### iOS APNs Payload
|
|
1226
|
+
|
|
1227
|
+
```json
|
|
1228
|
+
{
|
|
1229
|
+
"aps": {
|
|
1230
|
+
"mutable-content": 1,
|
|
1231
|
+
"alert": {
|
|
1232
|
+
"title": "New Product Available",
|
|
1233
|
+
"body": "Check out our latest premium features"
|
|
1234
|
+
},
|
|
1235
|
+
"badge": 1,
|
|
1236
|
+
"sound": "default"
|
|
1237
|
+
},
|
|
1238
|
+
"Zixflow": {
|
|
1239
|
+
"push": {
|
|
1240
|
+
"link": "yourapp://product/123",
|
|
1241
|
+
"image": "https://example.com/product-image.jpg"
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
#### iOS FCM Payload
|
|
1248
|
+
|
|
1249
|
+
```json
|
|
1250
|
+
{
|
|
1251
|
+
"message": {
|
|
1252
|
+
"apns": {
|
|
1253
|
+
"payload": {
|
|
1254
|
+
"aps": {
|
|
1255
|
+
"mutable-content": 1,
|
|
1256
|
+
"alert": {
|
|
1257
|
+
"title": "Special Offer",
|
|
1258
|
+
"body": "Limited time discount!"
|
|
1259
|
+
}
|
|
1260
|
+
},
|
|
1261
|
+
"Zixflow": {
|
|
1262
|
+
"push": {
|
|
1263
|
+
"link": "https://yourapp.com/offers",
|
|
1264
|
+
"image": "https://example.com/offer.png"
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
"headers": {
|
|
1269
|
+
"apns-priority": 10
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
#### Android FCM Payload
|
|
1277
|
+
|
|
1278
|
+
```json
|
|
1279
|
+
{
|
|
1280
|
+
"message": {
|
|
1281
|
+
"data": {
|
|
1282
|
+
"title": "Order Shipped",
|
|
1283
|
+
"body": "Your order is on the way!",
|
|
1284
|
+
"image": "https://example.com/shipping.jpg",
|
|
1285
|
+
"link": "yourapp://orders/456"
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
```
|
|
1290
|
+
|
|
1291
|
+
---
|
|
1292
|
+
|
|
1293
|
+
### Testing Push Notifications
|
|
1294
|
+
|
|
1295
|
+
#### 1. Verify Device Token Registration
|
|
1296
|
+
|
|
1297
|
+
Check if device token is registered:
|
|
1298
|
+
|
|
1299
|
+
```typescript
|
|
1300
|
+
const verifyPushSetup = async () => {
|
|
1301
|
+
try {
|
|
1302
|
+
const token = await Zixflow.pushMessaging.getRegisteredDeviceToken();
|
|
1303
|
+
const status = await Zixflow.pushMessaging.getPushPermissionStatus();
|
|
1304
|
+
|
|
1305
|
+
console.log('Device token:', token);
|
|
1306
|
+
console.log('Permission status:', status);
|
|
1307
|
+
|
|
1308
|
+
if (token && status === ZixflowPushPermissionStatus.Granted) {
|
|
1309
|
+
console.log('✓ Push notifications ready');
|
|
1310
|
+
} else {
|
|
1311
|
+
console.log('✗ Push setup incomplete');
|
|
1312
|
+
}
|
|
1313
|
+
} catch (error) {
|
|
1314
|
+
console.error('Push verification failed:', error);
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
#### 2. Enable Debug Logging
|
|
1320
|
+
|
|
1321
|
+
Set log level to debug during development:
|
|
1322
|
+
|
|
1323
|
+
```typescript
|
|
1324
|
+
const config: ZixflowConfig = {
|
|
1325
|
+
apiKey: 'YOUR_API_KEY',
|
|
1326
|
+
logLevel: ZixflowLogLevel.debug, // Verbose logging
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
Zixflow.initialize(config);
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
#### 3. Test on Physical Devices
|
|
1333
|
+
|
|
1334
|
+
**iOS:**
|
|
1335
|
+
- Push notifications **do not work** on iOS Simulator
|
|
1336
|
+
- Must use physical iOS device
|
|
1337
|
+
- Ensure APNs certificate is configured in Zixflow dashboard
|
|
1338
|
+
|
|
1339
|
+
**Android:**
|
|
1340
|
+
- Emulator works if Google Play Services installed
|
|
1341
|
+
- Physical device always recommended
|
|
1342
|
+
- Ensure FCM Server Key is configured in Zixflow dashboard
|
|
1343
|
+
|
|
1344
|
+
#### 4. Send Test Push from Zixflow
|
|
1345
|
+
|
|
1346
|
+
1. Log into Zixflow dashboard
|
|
1347
|
+
2. Navigate to **Messaging** → **Push Notifications**
|
|
1348
|
+
3. Create test push notification
|
|
1349
|
+
4. Send to specific user (using `userId` from `identify()`)
|
|
1350
|
+
|
|
1351
|
+
---
|
|
1352
|
+
|
|
1353
|
+
### Troubleshooting
|
|
1354
|
+
|
|
1355
|
+
#### iOS Push Not Received
|
|
1356
|
+
|
|
1357
|
+
**Symptoms:** Push sent but not delivered on iOS
|
|
1358
|
+
|
|
1359
|
+
**Solutions:**
|
|
1360
|
+
1. Verify Push Notifications capability enabled in Xcode
|
|
1361
|
+
2. Check APNs certificate uploaded to Zixflow dashboard
|
|
1362
|
+
3. Ensure testing on physical device (not simulator)
|
|
1363
|
+
4. Verify user identified: `Zixflow.identify({ userId: ... })`
|
|
1364
|
+
5. Check permission granted: `getPushPermissionStatus()`
|
|
1365
|
+
6. Review logs for errors
|
|
1366
|
+
|
|
1367
|
+
#### Android Push Not Received
|
|
1368
|
+
|
|
1369
|
+
**Symptoms:** Push sent but not delivered on Android
|
|
1370
|
+
|
|
1371
|
+
**Solutions:**
|
|
1372
|
+
1. Verify `google-services.json` in `android/app/` directory
|
|
1373
|
+
2. Check FCM Server Key in Zixflow dashboard
|
|
1374
|
+
3. Ensure POST_NOTIFICATIONS permission granted (Android 13+)
|
|
1375
|
+
4. Verify Google Services plugin applied
|
|
1376
|
+
5. Check device token registered
|
|
1377
|
+
6. Review logs for errors
|
|
1378
|
+
|
|
1379
|
+
#### Rich Push Not Working (Images)
|
|
1380
|
+
|
|
1381
|
+
**Symptoms:** Images not loading in notifications
|
|
1382
|
+
|
|
1383
|
+
**iOS Solutions:**
|
|
1384
|
+
1. Ensure Notification Service Extension properly configured
|
|
1385
|
+
2. Verify extension has correct dependencies in Podfile
|
|
1386
|
+
3. Check App Groups configuration (if using)
|
|
1387
|
+
4. Verify image URL is accessible
|
|
1388
|
+
5. Check extension logs for errors
|
|
1389
|
+
|
|
1390
|
+
**Android Solutions:**
|
|
1391
|
+
1. Verify image URL is accessible from device
|
|
1392
|
+
2. Check internet connectivity
|
|
1393
|
+
3. Ensure image format is supported (JPEG, PNG, GIF)
|
|
1394
|
+
|
|
1395
|
+
#### Permission Denied
|
|
1396
|
+
|
|
1397
|
+
**Symptoms:** User denied push permission
|
|
1398
|
+
|
|
1399
|
+
**Solutions:**
|
|
1400
|
+
1. Explain value before requesting permission
|
|
1401
|
+
2. Guide users to Settings to enable manually
|
|
1402
|
+
3. Show in-app message explaining benefits
|
|
1403
|
+
4. Request permission at appropriate time (after user engagement)
|
|
1404
|
+
|
|
1405
|
+
#### Device Token Not Registered
|
|
1406
|
+
|
|
1407
|
+
**Symptoms:** `getRegisteredDeviceToken()` returns empty or fails
|
|
1408
|
+
|
|
1409
|
+
**Solutions:**
|
|
1410
|
+
1. Verify SDK initialized before calling
|
|
1411
|
+
2. Check permission granted
|
|
1412
|
+
3. Ensure identify() called to associate token
|
|
1413
|
+
4. Review native logs for errors
|
|
1414
|
+
5. Rebuild app and retry
|
|
1415
|
+
|
|
1416
|
+
---
|
|
1417
|
+
|
|
1418
|
+
### Best Practices
|
|
1419
|
+
|
|
1420
|
+
1. **Request permission thoughtfully** - Explain value before asking
|
|
1421
|
+
2. **Identify users immediately** after authentication
|
|
1422
|
+
3. **Test on physical devices** - Simulators have limitations
|
|
1423
|
+
4. **Use rich push** - Images increase engagement
|
|
1424
|
+
5. **Handle deep links** - Provide seamless navigation
|
|
1425
|
+
6. **Monitor metrics** - Track delivery and open rates
|
|
1426
|
+
7. **Enable debug logging** - During development only
|
|
1427
|
+
8. **Test both platforms** - iOS and Android behave differently
|
|
1428
|
+
9. **Clear identity on logout** - Call `clearIdentify()`
|
|
1429
|
+
10. **Keep credentials secure** - Never commit API keys to git
|
|
1430
|
+
|
|
1431
|
+
---
|
|
1432
|
+
|
|
1433
|
+
### Next Steps
|
|
1434
|
+
|
|
1435
|
+
- Learn about [In-App Messaging](#in-app-messaging)
|
|
1436
|
+
- Explore [Deep Link Handling](#deep-links-and-navigation)
|
|
1437
|
+
- See [Example Applications](#example-applications) for complete implementations
|
|
1438
|
+
|
|
1439
|
+
---
|
|
1440
|
+
|
|
1441
|
+
## In-App Messaging
|
|
1442
|
+
|
|
1443
|
+
### Event Listeners
|
|
1444
|
+
|
|
1445
|
+
Register event listeners to respond to in-app message events:
|
|
1446
|
+
|
|
1447
|
+
```typescript
|
|
1448
|
+
import { Zixflow, InAppMessageEvent, InAppMessageEventType } from 'zixflow-reactnative';
|
|
1449
|
+
import { useEffect } from 'react';
|
|
1450
|
+
|
|
1451
|
+
export default function App() {
|
|
1452
|
+
useEffect(() => {
|
|
1453
|
+
const inAppMessaging = Zixflow.inAppMessaging;
|
|
1454
|
+
|
|
1455
|
+
const eventListener = inAppMessaging.registerEventsListener((event: InAppMessageEvent) => {
|
|
1456
|
+
switch (event.eventType) {
|
|
1457
|
+
case InAppMessageEventType.messageShown:
|
|
1458
|
+
console.log('In-app message shown', event);
|
|
1459
|
+
break;
|
|
1460
|
+
|
|
1461
|
+
case InAppMessageEventType.messageDismissed:
|
|
1462
|
+
console.log('In-app message dismissed', event);
|
|
1463
|
+
break;
|
|
1464
|
+
|
|
1465
|
+
case InAppMessageEventType.messageActionTaken:
|
|
1466
|
+
console.log('Action taken on in-app message', event);
|
|
1467
|
+
handleMessageAction(event);
|
|
1468
|
+
break;
|
|
1469
|
+
|
|
1470
|
+
case InAppMessageEventType.errorWithMessage:
|
|
1471
|
+
console.error('Error with in-app message', event);
|
|
1472
|
+
break;
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
// Cleanup listener on unmount
|
|
1477
|
+
return () => {
|
|
1478
|
+
eventListener.remove();
|
|
1479
|
+
};
|
|
1480
|
+
}, []);
|
|
1481
|
+
|
|
1482
|
+
return (
|
|
1483
|
+
// Your app UI
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
### Message Events
|
|
1489
|
+
|
|
1490
|
+
The SDK provides the following in-app message event types:
|
|
1491
|
+
|
|
1492
|
+
| Event Type | Description |
|
|
1493
|
+
|------------|-------------|
|
|
1494
|
+
| `messageShown` | Message was displayed to the user |
|
|
1495
|
+
| `messageDismissed` | Message was dismissed by the user |
|
|
1496
|
+
| `messageActionTaken` | User took an action on the message (clicked button, link, etc.) |
|
|
1497
|
+
| `errorWithMessage` | Error occurred while displaying the message |
|
|
1498
|
+
|
|
1499
|
+
**Event properties**:
|
|
1500
|
+
- `eventType`: The type of event
|
|
1501
|
+
- `deliveryId`: Unique delivery identifier
|
|
1502
|
+
- `messageId`: Message template identifier
|
|
1503
|
+
- `actionName`: Name of the action taken (for `messageActionTaken`)
|
|
1504
|
+
- `actionValue`: Value of the action (for `messageActionTaken`)
|
|
1505
|
+
|
|
1506
|
+
### Dismissing Messages
|
|
1507
|
+
|
|
1508
|
+
Programmatically dismiss the current in-app message:
|
|
1509
|
+
|
|
1510
|
+
```typescript
|
|
1511
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1512
|
+
|
|
1513
|
+
const handleMessageAction = (event: InAppMessageEvent) => {
|
|
1514
|
+
if (event.actionValue === 'dismiss' || event.actionValue === 'close') {
|
|
1515
|
+
// Dismiss the message
|
|
1516
|
+
Zixflow.inAppMessaging.dismissMessage();
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
```
|
|
1520
|
+
|
|
1521
|
+
---
|
|
1522
|
+
|
|
1523
|
+
## Location Tracking
|
|
1524
|
+
|
|
1525
|
+
Enable location tracking to send location-based messages:
|
|
1526
|
+
|
|
1527
|
+
```typescript
|
|
1528
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1529
|
+
|
|
1530
|
+
// Location tracking is configured via the native SDK
|
|
1531
|
+
// Make sure to request location permissions in your app
|
|
1532
|
+
|
|
1533
|
+
// iOS: Add location permission keys to Info.plist
|
|
1534
|
+
// - NSLocationWhenInUseUsageDescription
|
|
1535
|
+
// - NSLocationAlwaysAndWhenInUseUsageDescription
|
|
1536
|
+
|
|
1537
|
+
// Android: Add location permissions to AndroidManifest.xml
|
|
1538
|
+
// - ACCESS_FINE_LOCATION
|
|
1539
|
+
// - ACCESS_COARSE_LOCATION
|
|
1540
|
+
```
|
|
1541
|
+
|
|
1542
|
+
Request location permissions using a library like `react-native-permissions`:
|
|
1543
|
+
|
|
1544
|
+
```typescript
|
|
1545
|
+
import { request, PERMISSIONS, RESULTS } from 'react-native-permissions';
|
|
1546
|
+
import { Platform } from 'react-native';
|
|
1547
|
+
|
|
1548
|
+
const requestLocationPermission = async () => {
|
|
1549
|
+
const permission = Platform.select({
|
|
1550
|
+
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
|
|
1551
|
+
android: PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
|
|
1552
|
+
});
|
|
1553
|
+
|
|
1554
|
+
if (!permission) return;
|
|
1555
|
+
|
|
1556
|
+
const result = await request(permission);
|
|
1557
|
+
|
|
1558
|
+
if (result === RESULTS.GRANTED) {
|
|
1559
|
+
console.log('Location permission granted');
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
```
|
|
1563
|
+
|
|
1564
|
+
---
|
|
1565
|
+
|
|
1566
|
+
## Advanced Configuration
|
|
1567
|
+
|
|
1568
|
+
### Region Settings
|
|
1569
|
+
|
|
1570
|
+
Configure the data center region for data residency:
|
|
1571
|
+
|
|
1572
|
+
```typescript
|
|
1573
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1574
|
+
|
|
1575
|
+
const config = {
|
|
1576
|
+
apiKey: 'YOUR_API_KEY',
|
|
1577
|
+
// or
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1580
|
+
Zixflow.initialize(config);
|
|
1581
|
+
```
|
|
1582
|
+
|
|
1583
|
+
**Available regions**:
|
|
1584
|
+
- `` - United States data center
|
|
1585
|
+
- `` - European Union data center
|
|
1586
|
+
|
|
1587
|
+
### Log Levels
|
|
1588
|
+
|
|
1589
|
+
Control SDK logging for debugging:
|
|
1590
|
+
|
|
1591
|
+
```typescript
|
|
1592
|
+
import { Zixflow, ZixflowLogLevel } from 'zixflow-reactnative';
|
|
1593
|
+
|
|
1594
|
+
const config = {
|
|
1595
|
+
apiKey: 'YOUR_API_KEY',
|
|
1596
|
+
logLevel: ZixflowLogLevel.debug, // debug, info, error, none
|
|
1597
|
+
};
|
|
1598
|
+
|
|
1599
|
+
Zixflow.initialize(config);
|
|
1600
|
+
```
|
|
1601
|
+
|
|
1602
|
+
**Log levels**:
|
|
1603
|
+
- `ZixflowLogLevel.debug` - Verbose logging (development)
|
|
1604
|
+
- `ZixflowLogLevel.info` - Informational messages
|
|
1605
|
+
- `ZixflowLogLevel.error` - Errors only
|
|
1606
|
+
- `ZixflowLogLevel.none` - No logging (production)
|
|
1607
|
+
|
|
1608
|
+
### Auto-Tracking Options
|
|
1609
|
+
|
|
1610
|
+
Configure automatic tracking features:
|
|
1611
|
+
|
|
1612
|
+
```typescript
|
|
1613
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1614
|
+
|
|
1615
|
+
const config = {
|
|
1616
|
+
apiKey: 'YOUR_API_KEY',
|
|
1617
|
+
|
|
1618
|
+
// Automatically track device attributes (OS, model, app version)
|
|
1619
|
+
autoTrackDeviceAttributes: true,
|
|
1620
|
+
|
|
1621
|
+
// Automatically track app lifecycle events (open, close, background)
|
|
1622
|
+
trackApplicationLifecycleEvents: true,
|
|
1623
|
+
|
|
1624
|
+
// Automatically track screens (requires integration)
|
|
1625
|
+
autoTrackScreenViews: true,
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1628
|
+
Zixflow.initialize(config);
|
|
1629
|
+
```
|
|
1630
|
+
|
|
1631
|
+
### Custom API Hosts
|
|
1632
|
+
|
|
1633
|
+
Override API endpoints for testing or custom infrastructure:
|
|
1634
|
+
|
|
1635
|
+
```typescript
|
|
1636
|
+
import { Zixflow } from 'zixflow-reactnative';
|
|
1637
|
+
|
|
1638
|
+
const config = {
|
|
1639
|
+
apiKey: 'YOUR_API_KEY',
|
|
1640
|
+
|
|
1641
|
+
// Custom tracking API host
|
|
1642
|
+
trackingApiUrl: 'https://custom-track.zixflow.com',
|
|
1643
|
+
|
|
1644
|
+
// Custom in-app messaging API host
|
|
1645
|
+
inApp: {
|
|
1646
|
+
// Override in-app messaging API endpoint if needed
|
|
1647
|
+
},
|
|
1648
|
+
};
|
|
1649
|
+
|
|
1650
|
+
Zixflow.initialize(config);
|
|
1651
|
+
```
|
|
1652
|
+
|
|
1653
|
+
---
|
|
1654
|
+
|
|
1655
|
+
## Troubleshooting
|
|
1656
|
+
|
|
1657
|
+
### Installation Issues
|
|
1658
|
+
|
|
1659
|
+
**Issue**: `npm install` fails with dependency conflicts
|
|
1660
|
+
|
|
1661
|
+
**Solution**: Use `--legacy-peer-deps` flag:
|
|
1662
|
+
```bash
|
|
1663
|
+
npm install zixflow-reactnative --legacy-peer-deps
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
Or with Yarn:
|
|
1667
|
+
```bash
|
|
1668
|
+
yarn add zixflow-reactnative --legacy-peer-deps
|
|
1669
|
+
```
|
|
1670
|
+
|
|
1671
|
+
---
|
|
1672
|
+
|
|
1673
|
+
**Issue**: Auto-linking fails after installation
|
|
1674
|
+
|
|
1675
|
+
**Solution**: Try manual linking:
|
|
1676
|
+
|
|
1677
|
+
1. Clean the build:
|
|
1678
|
+
```bash
|
|
1679
|
+
cd android && ./gradlew clean && cd ..
|
|
1680
|
+
cd ios && rm -rf Pods && pod install && cd ..
|
|
1681
|
+
```
|
|
1682
|
+
|
|
1683
|
+
2. Rebuild the app:
|
|
1684
|
+
```bash
|
|
1685
|
+
npx react-native run-ios
|
|
1686
|
+
npx react-native run-android
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
### iOS Build Errors
|
|
1690
|
+
|
|
1691
|
+
**Issue**: `Module 'Zixflow' not found`
|
|
1692
|
+
|
|
1693
|
+
**Solution**:
|
|
1694
|
+
1. Ensure you've run `pod install` in the `ios` directory
|
|
1695
|
+
2. Clean build folder in Xcode: Product > Clean Build Folder
|
|
1696
|
+
3. Rebuild the project
|
|
1697
|
+
|
|
1698
|
+
---
|
|
1699
|
+
|
|
1700
|
+
**Issue**: Swift compiler errors in native modules
|
|
1701
|
+
|
|
1702
|
+
**Solution**:
|
|
1703
|
+
1. Check Xcode version (14.0+ required)
|
|
1704
|
+
2. Update CocoaPods: `sudo gem install cocoapods`
|
|
1705
|
+
3. Update pod dependencies: `cd ios && pod update && cd ..`
|
|
1706
|
+
|
|
1707
|
+
---
|
|
1708
|
+
|
|
1709
|
+
**Issue**: Notification Service Extension not working
|
|
1710
|
+
|
|
1711
|
+
**Solution**:
|
|
1712
|
+
1. Ensure the extension target has the correct dependencies in Podfile
|
|
1713
|
+
2. Run `pod install` after adding the extension
|
|
1714
|
+
3. Check that the extension's deployment target is iOS 13.0+
|
|
1715
|
+
4. Verify the extension is added to your app's target dependencies
|
|
1716
|
+
|
|
1717
|
+
### Android Build Errors
|
|
1718
|
+
|
|
1719
|
+
**Issue**: `Cannot find symbol class Zixflow`
|
|
1720
|
+
|
|
1721
|
+
**Solution**:
|
|
1722
|
+
1. Clean Gradle cache:
|
|
1723
|
+
```bash
|
|
1724
|
+
cd android && ./gradlew clean && cd ..
|
|
1725
|
+
```
|
|
1726
|
+
|
|
1727
|
+
2. Rebuild the app:
|
|
1728
|
+
```bash
|
|
1729
|
+
npx react-native run-android
|
|
1730
|
+
```
|
|
1731
|
+
|
|
1732
|
+
---
|
|
1733
|
+
|
|
1734
|
+
**Issue**: Duplicate class errors with Firebase
|
|
1735
|
+
|
|
1736
|
+
**Solution**:
|
|
1737
|
+
1. Check that you're not including Firebase dependencies manually if using FCM
|
|
1738
|
+
2. Ensure all Firebase dependencies use the same version
|
|
1739
|
+
3. Add to `android/gradle.properties`:
|
|
1740
|
+
```properties
|
|
1741
|
+
android.enableJetifier=true
|
|
1742
|
+
```
|
|
1743
|
+
|
|
1744
|
+
---
|
|
1745
|
+
|
|
1746
|
+
**Issue**: Minimum SDK version error
|
|
1747
|
+
|
|
1748
|
+
**Solution**: Update `android/build.gradle`:
|
|
1749
|
+
```gradle
|
|
1750
|
+
ext {
|
|
1751
|
+
minSdkVersion = 24
|
|
1752
|
+
}
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
### Push Notification Issues
|
|
1756
|
+
|
|
1757
|
+
**Issue**: Push notifications not received on iOS
|
|
1758
|
+
|
|
1759
|
+
**Checklist**:
|
|
1760
|
+
- [ ] Push Notifications capability enabled in Xcode
|
|
1761
|
+
- [ ] APNs certificate uploaded to Zixflow dashboard
|
|
1762
|
+
- [ ] Device token registered (check logs)
|
|
1763
|
+
- [ ] Permission granted by user
|
|
1764
|
+
- [ ] App not in foreground (notifications shown in background/killed state)
|
|
1765
|
+
|
|
1766
|
+
---
|
|
1767
|
+
|
|
1768
|
+
**Issue**: Push notifications not received on Android
|
|
1769
|
+
|
|
1770
|
+
**Checklist**:
|
|
1771
|
+
- [ ] `google-services.json` file added to `android/app/`
|
|
1772
|
+
- [ ] Google Services plugin applied in `android/app/build.gradle`
|
|
1773
|
+
- [ ] FCM server key uploaded to Zixflow dashboard
|
|
1774
|
+
- [ ] Device registered for push (check logs)
|
|
1775
|
+
- [ ] Notification permissions granted (Android 13+)
|
|
1776
|
+
|
|
1777
|
+
---
|
|
1778
|
+
|
|
1779
|
+
**Issue**: Rich push notifications (images) not working
|
|
1780
|
+
|
|
1781
|
+
**Solution**: Ensure Notification Service Extension is properly configured on iOS (see [Notification Service Extension](#notification-service-extension))
|
|
1782
|
+
|
|
1783
|
+
### In-App Message Issues
|
|
1784
|
+
|
|
1785
|
+
**Issue**: In-app messages not displaying
|
|
1786
|
+
|
|
1787
|
+
**Checklist**:
|
|
1788
|
+
- [ ] In-app messaging module initialized
|
|
1789
|
+
- [ ] Event listener registered
|
|
1790
|
+
- [ ] User identified before triggering message
|
|
1791
|
+
- [ ] Message created and published in Zixflow dashboard
|
|
1792
|
+
- [ ] Check logs for error events
|
|
1793
|
+
|
|
1794
|
+
---
|
|
1795
|
+
|
|
1796
|
+
**Issue**: In-app message events not firing
|
|
1797
|
+
|
|
1798
|
+
**Solution**: Ensure event listener is registered before messages are triggered:
|
|
1799
|
+
```typescript
|
|
1800
|
+
useEffect(() => {
|
|
1801
|
+
const listener = Zixflow.inAppMessaging.registerEventsListener((event) => {
|
|
1802
|
+
console.log('In-app event:', event);
|
|
1803
|
+
});
|
|
1804
|
+
|
|
1805
|
+
return () => listener.remove();
|
|
1806
|
+
}, []);
|
|
1807
|
+
```
|
|
1808
|
+
|
|
1809
|
+
---
|
|
1810
|
+
|
|
1811
|
+
## Example Applications
|
|
1812
|
+
|
|
1813
|
+
The Zixflow React Native SDK includes example applications demonstrating best practices:
|
|
1814
|
+
|
|
1815
|
+
### Sample App (APNs)
|
|
1816
|
+
|
|
1817
|
+
Location: `example/`
|
|
1818
|
+
|
|
1819
|
+
**Features**:
|
|
1820
|
+
- User identification and logout
|
|
1821
|
+
- Event tracking
|
|
1822
|
+
- Screen tracking with React Navigation
|
|
1823
|
+
- Push notifications with APNs
|
|
1824
|
+
- In-app messaging with event listeners
|
|
1825
|
+
- Profile and device attributes
|
|
1826
|
+
|
|
1827
|
+
**Running the example**:
|
|
1828
|
+
|
|
1829
|
+
```bash
|
|
1830
|
+
# Install dependencies
|
|
1831
|
+
cd example
|
|
1832
|
+
npm install
|
|
1833
|
+
|
|
1834
|
+
# iOS
|
|
1835
|
+
cd ios && pod install && cd ..
|
|
1836
|
+
npx react-native run-ios
|
|
1837
|
+
|
|
1838
|
+
# Android
|
|
1839
|
+
npx react-native run-android
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
---
|
|
1843
|
+
|
|
1844
|
+
## API Reference
|
|
1845
|
+
|
|
1846
|
+
### Core SDK
|
|
1847
|
+
|
|
1848
|
+
#### `Zixflow.initialize(config: ZixflowConfig): void`
|
|
1849
|
+
|
|
1850
|
+
Initialize the SDK with configuration.
|
|
1851
|
+
|
|
1852
|
+
```typescript
|
|
1853
|
+
Zixflow.initialize({
|
|
1854
|
+
apiKey: 'YOUR_API_KEY',
|
|
1855
|
+
});
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
#### `Zixflow.identify(params: { userId: string; traits?: object }): void`
|
|
1859
|
+
|
|
1860
|
+
Identify a user with optional traits.
|
|
1861
|
+
|
|
1862
|
+
```typescript
|
|
1863
|
+
Zixflow.identify({
|
|
1864
|
+
userId: 'user-123',
|
|
1865
|
+
traits: { email: 'user@example.com' }
|
|
1866
|
+
});
|
|
1867
|
+
```
|
|
1868
|
+
|
|
1869
|
+
#### `Zixflow.clearIdentify(): void`
|
|
1870
|
+
|
|
1871
|
+
Clear the current user's identity.
|
|
1872
|
+
|
|
1873
|
+
```typescript
|
|
1874
|
+
Zixflow.clearIdentify();
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
#### `Zixflow.track(name: string, properties?: object | Map<string, any>): void`
|
|
1878
|
+
|
|
1879
|
+
Track a custom event.
|
|
1880
|
+
|
|
1881
|
+
```typescript
|
|
1882
|
+
Zixflow.track('button_clicked', { button_name: 'signup' });
|
|
1883
|
+
```
|
|
1884
|
+
|
|
1885
|
+
#### `Zixflow.screen(name: string, properties?: object): void`
|
|
1886
|
+
|
|
1887
|
+
Track a screen view.
|
|
1888
|
+
|
|
1889
|
+
```typescript
|
|
1890
|
+
Zixflow.screen('HomeScreen');
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
#### `Zixflow.setProfileAttributes(attributes: object): void`
|
|
1894
|
+
|
|
1895
|
+
Set attributes on the user profile.
|
|
1896
|
+
|
|
1897
|
+
```typescript
|
|
1898
|
+
Zixflow.setProfileAttributes({ plan: 'premium' });
|
|
1899
|
+
```
|
|
1900
|
+
|
|
1901
|
+
#### `Zixflow.setDeviceAttributes(attributes: object): void`
|
|
1902
|
+
|
|
1903
|
+
Set attributes on the current device.
|
|
1904
|
+
|
|
1905
|
+
```typescript
|
|
1906
|
+
Zixflow.setDeviceAttributes({ app_version: '2.0.0' });
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
### Push Messaging
|
|
1910
|
+
|
|
1911
|
+
#### `Zixflow.pushMessaging.showPromptForPushNotifications(options): Promise<ZixflowPushPermissionStatus>`
|
|
1912
|
+
|
|
1913
|
+
Request push notification permission.
|
|
1914
|
+
|
|
1915
|
+
```typescript
|
|
1916
|
+
const status = await Zixflow.pushMessaging.showPromptForPushNotifications({
|
|
1917
|
+
ios: { sound: true, badge: true }
|
|
1918
|
+
});
|
|
1919
|
+
```
|
|
1920
|
+
|
|
1921
|
+
### In-App Messaging
|
|
1922
|
+
|
|
1923
|
+
#### `Zixflow.inAppMessaging.registerEventsListener(callback): EventSubscription`
|
|
1924
|
+
|
|
1925
|
+
Register a listener for in-app message events.
|
|
1926
|
+
|
|
1927
|
+
```typescript
|
|
1928
|
+
const listener = Zixflow.inAppMessaging.registerEventsListener((event) => {
|
|
1929
|
+
console.log('In-app event:', event);
|
|
1930
|
+
});
|
|
1931
|
+
|
|
1932
|
+
// Remove listener
|
|
1933
|
+
listener.remove();
|
|
1934
|
+
```
|
|
1935
|
+
|
|
1936
|
+
#### `Zixflow.inAppMessaging.dismissMessage(): void`
|
|
1937
|
+
|
|
1938
|
+
Dismiss the currently displayed in-app message.
|
|
1939
|
+
|
|
1940
|
+
```typescript
|
|
1941
|
+
Zixflow.inAppMessaging.dismissMessage();
|
|
1942
|
+
```
|
|
1943
|
+
|
|
1944
|
+
### Types
|
|
1945
|
+
|
|
1946
|
+
#### `ZixflowConfig`
|
|
1947
|
+
|
|
1948
|
+
Configuration object for SDK initialization.
|
|
1949
|
+
|
|
1950
|
+
```typescript
|
|
1951
|
+
interface ZixflowConfig {
|
|
1952
|
+
apiKey: string;
|
|
1953
|
+
region?: Region;
|
|
1954
|
+
logLevel?: ZixflowLogLevel;
|
|
1955
|
+
inApp?: {
|
|
1956
|
+
};
|
|
1957
|
+
autoTrackDeviceAttributes?: boolean;
|
|
1958
|
+
trackApplicationLifecycleEvents?: boolean;
|
|
1959
|
+
autoTrackScreenViews?: boolean;
|
|
1960
|
+
trackingApiUrl?: string;
|
|
1961
|
+
}
|
|
1962
|
+
```
|
|
1963
|
+
|
|
1964
|
+
#### `Region`
|
|
1965
|
+
|
|
1966
|
+
Data center region enum.
|
|
1967
|
+
|
|
1968
|
+
```typescript
|
|
1969
|
+
enum Region {
|
|
1970
|
+
US = 'US',
|
|
1971
|
+
EU = 'EU'
|
|
1972
|
+
}
|
|
1973
|
+
```
|
|
1974
|
+
|
|
1975
|
+
#### `ZixflowLogLevel`
|
|
1976
|
+
|
|
1977
|
+
Log level enum.
|
|
1978
|
+
|
|
1979
|
+
```typescript
|
|
1980
|
+
enum ZixflowLogLevel {
|
|
1981
|
+
none = 'none',
|
|
1982
|
+
error = 'error',
|
|
1983
|
+
info = 'info',
|
|
1984
|
+
debug = 'debug'
|
|
1985
|
+
}
|
|
1986
|
+
```
|
|
1987
|
+
|
|
1988
|
+
#### `ZixflowPushPermissionStatus`
|
|
1989
|
+
|
|
1990
|
+
Push notification permission status.
|
|
1991
|
+
|
|
1992
|
+
```typescript
|
|
1993
|
+
enum ZixflowPushPermissionStatus {
|
|
1994
|
+
Granted = 'granted',
|
|
1995
|
+
Denied = 'denied',
|
|
1996
|
+
NotDetermined = 'notDetermined'
|
|
1997
|
+
}
|
|
1998
|
+
```
|
|
1999
|
+
|
|
2000
|
+
#### `InAppMessageEventType`
|
|
2001
|
+
|
|
2002
|
+
In-app message event types.
|
|
2003
|
+
|
|
2004
|
+
```typescript
|
|
2005
|
+
enum InAppMessageEventType {
|
|
2006
|
+
messageShown = 'messageShown',
|
|
2007
|
+
messageDismissed = 'messageDismissed',
|
|
2008
|
+
messageActionTaken = 'messageActionTaken',
|
|
2009
|
+
errorWithMessage = 'errorWithMessage'
|
|
2010
|
+
}
|
|
2011
|
+
```
|
|
2012
|
+
|
|
2013
|
+
#### `InAppMessageEvent`
|
|
2014
|
+
|
|
2015
|
+
In-app message event object.
|
|
2016
|
+
|
|
2017
|
+
```typescript
|
|
2018
|
+
interface InAppMessageEvent {
|
|
2019
|
+
eventType: InAppMessageEventType;
|
|
2020
|
+
deliveryId?: string;
|
|
2021
|
+
messageId?: string;
|
|
2022
|
+
actionName?: string;
|
|
2023
|
+
actionValue?: string;
|
|
2024
|
+
}
|
|
2025
|
+
```
|
|
2026
|
+
|
|
2027
|
+
---
|
|
2028
|
+
|
|
2029
|
+
## Support & Resources
|
|
2030
|
+
|
|
2031
|
+
### Documentation
|
|
2032
|
+
|
|
2033
|
+
- **GitHub Repository**: https://github.com/zixflow/zixflow-reactnative
|
|
2034
|
+
- **iOS SDK Documentation**: https://github.com/zixflow/zixflow-ios
|
|
2035
|
+
- **Android SDK Documentation**: https://github.com/zixflow/zixflow-android
|
|
2036
|
+
- **API Reference**: See [API Reference](#api-reference) section above
|
|
2037
|
+
|
|
2038
|
+
### Getting Help
|
|
2039
|
+
|
|
2040
|
+
- **GitHub Issues**: https://github.com/zixflow/zixflow-reactnative/issues
|
|
2041
|
+
- **Support Email**: support@zixflow.com
|
|
2042
|
+
|
|
2043
|
+
### Changelog
|
|
2044
|
+
|
|
2045
|
+
See [CHANGELOG.md](../CHANGELOG.md) for version history and release notes.
|
|
2046
|
+
|
|
2047
|
+
---
|
|
516
2048
|
|
|
517
|
-
|
|
2049
|
+
**Need help?** Contact our support team at support@zixflow.com or open an issue on GitHub.
|