cordova-plugin-reteno 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +2 -4
  2. package/docs/Cordova/Action Buttons/README.md +62 -0
  3. package/docs/Cordova/AppInbox/README.md +55 -0
  4. package/docs/Cordova/AppLifeCycleEvents/README.md +80 -0
  5. package/docs/Cordova/Ecommerce/README.md +144 -0
  6. package/docs/Cordova/InAppMessages/README.md +72 -0
  7. package/docs/Cordova/Push notification/README.md +129 -0
  8. package/docs/Cordova/Recommendations/README.md +62 -0
  9. package/docs/Cordova/SetupGuide/Android.md +135 -0
  10. package/docs/Cordova/SetupGuide/IOS.md +325 -0
  11. package/docs/Cordova/SetupGuide/README.md +91 -0
  12. package/docs/Cordova/Tracking user behaviour/README.md +52 -0
  13. package/docs/Cordova/Tracking user information/README.md +112 -0
  14. package/docs/Ionic/Action Buttons/README.md +66 -0
  15. package/docs/Ionic/AppInbox/README.md +61 -0
  16. package/docs/Ionic/AppLifeCycleEvents/README.md +77 -0
  17. package/docs/Ionic/Ecommerce/README.md +139 -0
  18. package/docs/Ionic/InAppMessages/README.md +65 -0
  19. package/docs/Ionic/Push notification/README.md +133 -0
  20. package/docs/Ionic/Recommendations/README.md +46 -0
  21. package/docs/Ionic/SetupGuide/Android.md +173 -0
  22. package/docs/Ionic/SetupGuide/IOS.md +354 -0
  23. package/docs/Ionic/SetupGuide/README.md +167 -0
  24. package/docs/Ionic/Tracking user behaviour/README.md +31 -0
  25. package/docs/Ionic/Tracking user information/README.md +98 -0
  26. package/package.json +1 -1
  27. package/plugin.xml +20 -2
  28. package/scripts/ios-podfile-use-modular-headers.js +109 -0
  29. package/scripts/validate-install.js +37 -9
  30. package/src/android/app/build.gradle +1 -1
  31. package/src/android/app/src/main/java/com/reteno/plugin/RetenoPlugin.java +29 -9
  32. package/src/android/reteno.gradle +19 -9
  33. package/src/ios/RetenoPlugin.swift +37 -5
  34. package/src/ios/RetenoPluginBootstrap.m +117 -0
  35. package/types/index.ts +1 -1
  36. package/docs/android.md +0 -264
  37. package/docs/api.md +0 -734
  38. package/docs/ios.md +0 -495
package/docs/ios.md DELETED
@@ -1,495 +0,0 @@
1
- ## iOS Setup (app-side steps)
2
-
3
- This section lists everything that must be done in the **app project** that consumes this plugin.
4
-
5
- Official guide: https://docs.reteno.com/reference/ios
6
-
7
- ## Minimum SDK Requirements
8
-
9
- - iOS: 15.0+
10
- - Xcode: 15.0+
11
- - Swift: 5.7+
12
-
13
- ## Add the plugin and configure preferences
14
-
15
- In `config.xml` add/verify:
16
-
17
- ```xml
18
- <!-- Required: Reteno iOS SDK supports iOS 15.0+ -->
19
- <preference name="deployment-target" value="15.0" />
20
-
21
- <!-- Reteno SDK access key (required) -->
22
- <preference name="SDK_ACCESS_KEY" value="YOUR_RETENO_ACCESS_KEY" />
23
- ```
24
-
25
- The plugin reads `SDK_ACCESS_KEY` during initialization.
26
-
27
- If `pod install` fails with "required a higher minimum deployment target", raise your iOS deployment target to `15.0` or higher and run install again.
28
-
29
- ## Add Notification Service Extension (NSE)
30
-
31
- NSE is required for rich push (images, attachments) and correct push payload handling.
32
-
33
- 1. In Xcode, add a new target: `Notification Service Extension`.
34
- 2. Replace `NotificationService.swift` with:
35
-
36
- ```swift
37
- import UserNotifications
38
- import Reteno
39
-
40
- class NotificationService: RetenoNotificationServiceExtension {}
41
- ```
42
-
43
- ## App Groups
44
-
45
- Enable App Groups for the main target and the NSE target.
46
-
47
- Group name format:
48
-
49
- ```
50
- group.{bundle_id}.reteno-local-storage
51
- ```
52
-
53
- Example:
54
-
55
- ```
56
- group.com.example.app.reteno-local-storage
57
- ```
58
-
59
- ## Podfile for extension targets
60
-
61
- The plugin wires `Reteno` pod into the **main** iOS target automatically.
62
- For extension targets you must add the pod manually in `platforms/ios/Podfile`.
63
- Both extension targets must be **nested inside** the main app target block:
64
-
65
- ```ruby
66
- target 'App' do
67
- # ... existing pods ...
68
-
69
- target 'NotificationServiceExtension' do
70
- inherit! :search_paths
71
- pod 'Reteno', '2.7.3'
72
- end
73
-
74
- target 'NotificationContentExtension' do
75
- inherit! :search_paths
76
- pod 'Reteno', '2.7.3'
77
- end
78
- end
79
- ```
80
-
81
- ## Add Notification Content Extension (NCE) — Images Carousel
82
-
83
- The Notification Content Extension is required for rich push notifications with an **Images Carousel**.
84
- It provides the `UNNotificationContentExtension` entry point that renders a custom carousel UI.
85
-
86
- Official guide: https://docs.reteno.com/reference/ios-images-carousel
87
-
88
- ### Create the extension target _(manual Xcode step)_
89
-
90
- In Xcode: **File → New → Target → Notification Content Extension**. Name it `NotificationContentExtension`.
91
-
92
- See the official guide for screenshots: https://docs.reteno.com/reference/ios-images-carousel
93
-
94
- ### Replace extension files
95
-
96
- 1. **Delete** the generated `MainInterface.storyboard` (it is not used with `RetenoCarouselNotificationViewController`).
97
- 2. Replace the contents of `NotificationViewController.swift` with:
98
-
99
- ```swift
100
- import Reteno
101
-
102
- final class NotificationViewController: RetenoCarouselNotificationViewController {}
103
- ```
104
-
105
- ### Update `Info.plist` of the NCE
106
-
107
- Open `NotificationContentExtension/Info.plist` as source code and replace the `NSExtension` dict with:
108
-
109
- ```xml
110
- <key>NSExtension</key>
111
- <dict>
112
- <key>NSExtensionAttributes</key>
113
- <dict>
114
- <key>UNNotificationExtensionCategory</key>
115
- <string>ImageCarousel</string>
116
- <key>UNNotificationExtensionInitialContentSizeRatio</key>
117
- <real>0.5</real>
118
- <key>UNNotificationExtensionUserInteractionEnabled</key>
119
- <true/>
120
- </dict>
121
- <key>NSExtensionPointIdentifier</key>
122
- <string>com.apple.usernotifications.content-extension</string>
123
- <key>NSExtensionPrincipalClass</key>
124
- <string>$(PRODUCT_MODULE_NAME).NotificationViewController</string>
125
- </dict>
126
- ```
127
-
128
- ### Deployment target
129
-
130
- Make sure the NCE **Deployment Target** in Xcode matches the main app target (iOS 15.0+). A mismatch is the most common reason carousel images fail to display.
131
-
132
- ### Embed App Extensions — Copy only when installing _(manual Xcode step)_
133
-
134
- > **This step must be done manually in Xcode** — it cannot be automated.
135
- > Official guide (Troubleshooting → "Turn off Copy Only when Installing"): https://docs.reteno.com/reference/ios-images-carousel
136
-
137
- In Xcode: **Main target → Build Phases → Embed App Extensions**. For **both** `NotificationServiceExtension` and `NotificationContentExtension` ensure **"Copy only when installing"** is **unchecked**.
138
-
139
- If this checkbox is left on, the extensions will not be embedded during Debug builds and carousel images will not appear.
140
-
141
- ## Capacitor setup (iOS)
142
-
143
- Capacitor uses Cordova plugins through a compatibility layer, but **does not execute Cordova plugin hooks**. This means some automatic steps that work in Cordova must be done manually.
144
-
145
- ### 1. Install the plugin
146
-
147
- ```sh
148
- npm install cordova-plugin-reteno
149
- npx cap sync ios
150
- ```
151
-
152
- ### 2. Configure `SDK_ACCESS_KEY`
153
-
154
- In `capacitor.config.ts`, pass the access key through `cordova.preferences`:
155
-
156
- ```ts
157
- import { CapacitorConfig } from '@capacitor/cli';
158
-
159
- const config: CapacitorConfig = {
160
- // ...
161
- cordova: {
162
- preferences: {
163
- SDK_ACCESS_KEY: 'YOUR_RETENO_ACCESS_KEY',
164
- // Plugin default is 'manual'. Set explicitly only if you need to override.
165
- IOS_DEVICE_TOKEN_HANDLING_MODE: 'manual',
166
- },
167
- },
168
- };
169
- ```
170
-
171
- You can also pass the key explicitly in JS:
172
-
173
- ```js
174
- await RetenoPlugin.init({ accessKey: 'YOUR_RETENO_ACCESS_KEY' });
175
- ```
176
-
177
- ### 3. Podfile path
178
-
179
- In Capacitor projects the Podfile is located at `ios/App/Podfile` (not `platforms/ios/Podfile` as in Cordova).
180
-
181
- The plugin wires the `Reteno` pod into the main target automatically via `npx cap sync`. For extension targets (NSE, NCE), add the pods manually inside the main target block in `ios/App/Podfile`:
182
-
183
- ```ruby
184
- target 'App' do
185
- # ... existing pods (added by Capacitor) ...
186
-
187
- target 'NotificationServiceExtension' do
188
- inherit! :search_paths
189
- pod 'Reteno', '2.7.3'
190
- end
191
-
192
- target 'NotificationContentExtension' do
193
- inherit! :search_paths
194
- pod 'Reteno', '2.7.3'
195
- end
196
- end
197
- ```
198
-
199
- Then run:
200
-
201
- ```sh
202
- cd ios/App && pod install
203
- ```
204
-
205
- ### 4. Xcode project setup
206
-
207
- Open `ios/App/App.xcworkspace` in Xcode. The following steps are the same as for Cordova (see sections above):
208
-
209
- - Add Notification Service Extension (NSE) target
210
- - Add Notification Content Extension (NCE) target (if you need image carousel)
211
- - Enable App Groups for all targets
212
- - Uncheck "Copy only when installing" in Embed App Extensions
213
-
214
- ### 5. Firebase setup (if using FCM)
215
-
216
- For Firebase push delivery, add `GoogleService-Info.plist` to the **main app target** in Xcode:
217
-
218
- 1. Download `GoogleService-Info.plist` from [Firebase Console](https://console.firebase.google.com/).
219
- 2. Open `ios/App/App.xcworkspace` in Xcode.
220
- 3. Drag `GoogleService-Info.plist` into the App target.
221
- 4. Add `pod 'FirebaseMessaging'` to `ios/App/Podfile` inside the main target, then run `pod install`.
222
-
223
- No `AppDelegate.swift` changes are required — the plugin auto-configures Firebase when `IOS_DEVICE_TOKEN_HANDLING_MODE` is `manual` (default).
224
-
225
- ### 6. Initialize and request permission
226
-
227
- ```js
228
- await RetenoPlugin.init();
229
- await RetenoPlugin.requestNotificationPermission();
230
- ```
231
-
232
- ## Initialize the SDK in JS
233
-
234
- Call initialization once on app startup:
235
-
236
- ```js
237
- await RetenoPlugin.init();
238
- ```
239
-
240
- **Cordova**: `SDK_ACCESS_KEY` is read from `config.xml` automatically. You can also pass it explicitly:
241
-
242
- ```js
243
- await RetenoPlugin.init({ accessKey: 'YOUR_RETENO_ACCESS_KEY' });
244
- ```
245
-
246
- **Capacitor**: see [Capacitor setup (iOS)](#capacitor-setup-ios) above.
247
-
248
- ## Request Notification Permission
249
-
250
- iOS requires an explicit permission prompt before the app can receive push notifications.
251
- Call the plugin helper when it makes sense in your UX flow (usually after a user action):
252
-
253
- ```js
254
- await RetenoPlugin.requestNotificationPermission();
255
- ```
256
-
257
- ## Provide Device Tokens to the SDK
258
-
259
- If another SDK/plugin obtains the device token (typically APNs on iOS), pass it to Reteno so it can register the device:
260
-
261
- ```js
262
- await RetenoPlugin.setDeviceToken(token);
263
- ```
264
-
265
- If your app retrieves tokens natively, here are the two common options and how they map to the plugin:
266
-
267
- - APNs: get `deviceToken` in `didRegisterForRemoteNotificationsWithDeviceToken`, convert to hex string, then forward it to JS and call `RetenoPlugin.setDeviceToken(tokenString)`.
268
- - FCM (Firebase Messaging): use the dedicated iOS Firebase flow below. `IOS_DEVICE_TOKEN_HANDLING_MODE` defaults to `manual`, so the plugin can forward FCM tokens automatically after `init()`.
269
-
270
- ## Using FCM (Firebase Cloud Messaging) on iOS
271
-
272
- If your app uses Firebase for push delivery on iOS, follow the steps below to integrate FCM token handling with Reteno.
273
-
274
- ### 1. Add `FirebaseMessaging` pod to your Podfile
275
-
276
- The plugin does **not** add `FirebaseMessaging` automatically — it is an optional dependency.
277
- Add it manually to your Podfile (`platforms/ios/Podfile` for Cordova, `ios/App/Podfile` for Capacitor) inside the main app target:
278
-
279
- ```ruby
280
- target 'App' do
281
- # ... existing pods ...
282
- pod 'FirebaseMessaging'
283
- end
284
- ```
285
-
286
- Then run:
287
-
288
- ```sh
289
- cd platforms/ios && pod install
290
- ```
291
-
292
- > If `FirebaseMessaging` is not installed, `init()` will log a warning instead of crashing.
293
-
294
- ### 2. Add `GoogleService-Info.plist`
295
-
296
- Download `GoogleService-Info.plist` from the [Firebase Console](https://console.firebase.google.com/) and add it to your **iOS app target** in Xcode:
297
-
298
- - Open `platforms/ios/<AppName>.xcworkspace` in Xcode.
299
- - Drag `GoogleService-Info.plist` into the project navigator under the main app target.
300
- - Make sure **"Copy items if needed"** is checked and the file is added to the **main app target** (not only the extension targets).
301
-
302
- If your app calls `FirebaseApp.configure()` without this file, Firebase will crash at runtime. The plugin avoids auto-configuring Firebase when the file is missing and logs a warning in manual mode.
303
-
304
- ### 3. Configure AppDelegate
305
-
306
- Nothing to do. Firebase iOS SDK uses **method swizzling** by default — it automatically intercepts `didRegisterForRemoteNotificationsWithDeviceToken` and forwards the APNS token to Firebase without any AppDelegate code.
307
-
308
- When `IOS_DEVICE_TOKEN_HANDLING_MODE` is set to `manual`, the plugin:
309
-
310
- 1. Calls `FirebaseApp.configure()` automatically on `init()` if not already called and `GoogleService-Info.plist` is present.
311
- 2. Subscribes to FCM token updates and forwards them to Reteno once Firebase is configured.
312
-
313
- No AppDelegate changes are required for either Cordova or Capacitor.
314
-
315
- ### 4. `IOS_DEVICE_TOKEN_HANDLING_MODE` defaults to `manual`
316
-
317
- `IOS_DEVICE_TOKEN_HANDLING_MODE` now defaults to `manual` in the plugin, so no extra config is required for the Firebase flow in most cases.
318
-
319
- If you previously overrode it to `automatic`, switch it back to `manual` to use FCM token forwarding.
320
-
321
- Only set `automatic` when you intentionally want APNS-only token handling by the native Reteno SDK.
322
-
323
- When `IOS_DEVICE_TOKEN_HANDLING_MODE` is `manual` **and** Firebase is configured (either already configured by the app or auto-configured because `GoogleService-Info.plist` is present), the plugin automatically:
324
-
325
- 1. Subscribes to Firebase Messaging delegate token updates — every future FCM token rotation is forwarded to Reteno immediately.
326
- 2. Tries to forward the already-cached FCM token on warm starts.
327
-
328
- ## In-App Status Handler (iOS)
329
-
330
- Official reference: https://docs.reteno.com/reference/ios-sdk-in-app-status-handler
331
-
332
- The plugin now bridges Reteno iOS `addInAppStatusHandler(...)` into JS through `reteno-in-app-lifecycle` events.
333
-
334
- Use:
335
-
336
- ```js
337
- function onInAppStatus(event) {
338
- const detail = event.detail || event;
339
- console.log('In-app status:', detail.event, detail.data);
340
- }
341
-
342
- await RetenoPlugin.setOnInAppLifecycleCallback(onInAppStatus);
343
- ```
344
-
345
- To unsubscribe:
346
-
347
- ```js
348
- await RetenoPlugin.setOnInAppLifecycleCallback(null);
349
- ```
350
-
351
- Status mapping used by the plugin:
352
-
353
- - `inAppShouldBeDisplayed` -> `beforeDisplay`
354
- - `inAppIsDisplayed` -> `onDisplay`
355
- - `inAppShouldBeClosed(action)` -> `beforeClose`
356
- - `inAppIsClosed(action)` -> `afterClose`
357
- - `inAppReceivedError(error)` -> `onError`
358
-
359
- Payload notes for iOS:
360
-
361
- - Display events (`beforeDisplay`, `onDisplay`) include an empty `data` object (iOS SDK does not provide an in-app message ID, unlike Android).
362
- - Close events (`beforeClose`, `afterClose`) include:
363
- - `data.closeAction` — one of: `"closeButtonClicked"`, `"buttonClicked"`, `"openUrlClicked"`, `"unknown"`
364
- - `data.action` — object with boolean flags:
365
- - `isCloseButtonClicked`
366
- - `isButtonClicked`
367
- - `isOpenUrlClicked`
368
- - Error events (`onError`) include `data.errorMessage` (string).
369
-
370
- ## In-Apps Pause (iOS)
371
-
372
- Official reference: https://docs.reteno.com/reference/ios-sdk-in-apps-pause
373
-
374
- The plugin supports both initialization-time and runtime in-app pause controls on iOS:
375
-
376
- ```js
377
- // Start SDK with in-apps paused and configure pause behaviour
378
- await RetenoPlugin.init({
379
- pauseInAppMessages: true,
380
- inAppMessagesPauseBehaviour: 'SKIP_IN_APPS', // or 'POSTPONE_IN_APPS'
381
- });
382
-
383
- // Runtime pause/resume
384
- await RetenoPlugin.pauseInAppMessages(true); // pause
385
- await RetenoPlugin.pauseInAppMessages(false); // resume
386
- ```
387
-
388
- Pause behavior can also be configured at runtime:
389
-
390
- ```js
391
- await RetenoPlugin.setInAppMessagesPauseBehaviour('SKIP_IN_APPS');
392
- // or
393
- await RetenoPlugin.setInAppMessagesPauseBehaviour('POSTPONE_IN_APPS');
394
- ```
395
-
396
- ## Custom Notification Behavior (optional)
397
-
398
- If you need custom behavior without editing native AppDelegate, the plugin provides optional helpers.
399
- Configure them **after** SDK initialization.
400
-
401
- Set presentation options for foreground notifications:
402
-
403
- ```js
404
- await RetenoPlugin.setWillPresentNotificationOptions({
405
- options: ['badge', 'sound', 'banner'],
406
- emitEvent: true,
407
- });
408
- ```
409
-
410
- If `emitEvent` is `true`, the plugin will emit `reteno-push-received` with the notification payload.
411
-
412
- Enable a response handler for notification taps:
413
-
414
- ```js
415
- await RetenoPlugin.setDidReceiveNotificationResponseHandler({
416
- enabled: true,
417
- emitEvent: true,
418
- });
419
- ```
420
-
421
- If `emitEvent` is `true`, the plugin will emit `reteno-notification-clicked` with the payload.
422
-
423
- ### Deeplinks in push payloads
424
-
425
- Reteno push notifications on iOS can include a link. By default, the native Reteno iOS SDK opens that link via the system URL opener.
426
-
427
- In a fully native iOS app, you can override this behavior with `Reteno.addLinkHandler(...)` and route links yourself:
428
- https://docs.reteno.com/reference/ios-links-handler
429
-
430
- For Cordova/Ionic/Capacitor apps, deeplink routing usually requires a separate app-level solution. This plugin does not expose `Reteno.addLinkHandler(...)` directly to JavaScript, so if you need custom routing for push links, use a dedicated deeplink/universal link integration in your hybrid app, for example:
431
-
432
- - Branch.io
433
- - a custom URL scheme plugin
434
- - a Universal Links / App Links plugin
435
-
436
- Typical setup for hybrid apps:
437
-
438
- 1. Configure your app to support the required link type (custom URL scheme or Universal Links / Associated Domains).
439
- 2. Install and configure your deeplink provider/router (for example, Branch.io) in the app project.
440
- 3. Route the tapped push link into that provider/router instead of relying only on the default native open behavior.
441
-
442
- If you use Universal Links on iOS, you must also configure the Apple-side association for your domain. In practice, Reteno can deliver the link in the push payload, but opening the correct screen inside a hybrid app is still handled by your deeplink integration layer.
443
-
444
- ## User Information and User Behaviour methods
445
-
446
- The plugin supports the main iOS methods described in Reteno docs:
447
-
448
- - `setUserAttributes(...)`
449
- - `setAnonymousUserAttributes(...)` (without `phone`/`email`)
450
- - `setMultiAccountUserAttributes(...)`
451
- - `logEvent(...)`
452
- - `logEcommerceEvent(...)` — tracks ecommerce activity (product views, cart updates, orders, search requests). See [API docs](./api.md#logecommerceevent-examples).
453
- - `logScreenView(...)`
454
- - `forcePushData(...)`
455
-
456
- Lifecycle tracking note for iOS:
457
-
458
- - iOS lifecycle tracking is configured during SDK initialization (`RetenoPlugin.init({ lifecycleTrackingOptions: ... })`).
459
- - Calling `setLifecycleTrackingOptions(...)` after initialization is not supported on iOS.
460
- - `lifecycleTrackingOptions` accepts:
461
- - `'ALL'` -> enables app lifecycle, foreground lifecycle (`ApplicationOpened`/`ApplicationBackgrounded`), push subscription, and session start/end tracking.
462
- - `'NONE'` -> disables these automatic events.
463
- - object:
464
- - `appLifecycleEnabled`
465
- - `foregroundLifecycleEnabled`
466
- - `pushSubscriptionEnabled`
467
- - `sessionStartEventsEnabled`
468
- - `sessionEndEventsEnabled`
469
- - `sessionEventsEnabled` (legacy alias; deprecated)
470
- - Session duration can be configured during `init(...)` via:
471
- - `sessionDurationSeconds`
472
-
473
- ## App Lifecycle Events (iOS)
474
-
475
- Official reference: https://docs.reteno.com/reference/ios-app-lifecycle-events
476
-
477
- When automatic tracking is enabled, the native iOS SDK can report these events:
478
-
479
- - `ApplicationInstalled`
480
- - `ApplicationUpdated`
481
- - `ApplicationOpened`
482
- - `ApplicationBackgrounded`
483
-
484
- Related automatic events controlled by the same init options:
485
-
486
- - Push subscription status events (`pushSubscriptionEnabled`)
487
- - Session events (`sessionStartEventsEnabled` / `sessionEndEventsEnabled`)
488
- - Foreground lifecycle events (`foregroundLifecycleEnabled`)
489
-
490
- Screen view tracking:
491
-
492
- - **Manual (recommended for Cordova/Ionic)** — call `RetenoPlugin.logScreenView(screenName)` on each navigation event (for example, by subscribing to your router's navigation events). This works on both iOS and Android and tracks the actual JS screens your users see.
493
- - **Automatic** — pass `isAutomaticScreenReportingEnabled: true` to `RetenoPlugin.init(...)`. The native iOS SDK will track `UIViewController` transitions automatically. Defaults to `false`.
494
-
495
- > **Note on automatic screen tracking in hybrid apps:** In Cordova/Ionic the entire UI runs inside a single WebView, so automatic tracking only captures native controller transitions (e.g. `CDVViewController`), not your JS screen navigations. The same applies to Android, where the native SDK's `autoScreenTracking` monitors `Fragment` transitions. For meaningful screen analytics in a hybrid app, always use `logScreenView()` manually.