Ενσωμάτωση React Native SDK
React Native wrapper που γεφυρώνει τα εγγενή iOS και Android SDK, προσφέροντας πλήρεις δυνατότητες πλατφόρμας με ένα μόνο TypeScript API.
Το native SDK απαιτεί iOS 14.0, ενώ το React Native 0.75 εξακολουθεί να έχει προεπιλογή το 13.4. Το CocoaPods απορρίπτει την ασυμφωνία με ένα παραπλανητικό σφάλμα - "Specs satisfying the dependency were found, but they required a higher minimum deployment target" - που μοιάζει με πρόβλημα επίλυσης εκδόσεων και όχι πλατφόρμας.
Αυξήστε το στο ios/Podfile:
platform :ios, [min_ios_version_supported, '14.0'].max
Παίρνοντας τη μεγαλύτερη από τις δύο τιμές, η ρύθμιση συνεχίζει να λειτουργεί όταν μια μελλοντική έκδοση του React Native ανεβάσει το δικό της ελάχιστο πάνω από το δικό μας.
Στη συνέχεια αυξήστε και τον στόχο ανάπτυξης (deployment target) της ίδιας της εφαρμογής σε 14.0 ή υψηλότερα: στο Xcode επιλέξτε το target της εφαρμογής και μετά General → Minimum Deployments → iOS (η ρύθμιση build IPHONEOS_DEPLOYMENT_TARGET στο ios/<YourApp>.xcodeproj). Μια νέα εφαρμογή React Native 0.75 μένει εκεί στο 13.4 ακόμη και μετά την αλλαγή στο Podfile, και ο linker προειδοποιεί τότε ότι τα αντικείμενα της Joryio έχουν γίνει build για νεότερη έκδοση iOS από την εφαρμογή.
Δυνατότητες
- Native Bridge - Τυλίγει τα εγγενή iOS (Swift) και Android (Kotlin) SDK
- Παρακολούθηση συμβάντων - Παρακολούθηση προσαρμοσμένων συμβάντων και προβολών οθόνης
- Ταυτότητα χρήστη - Αναγνώριση, aliases με ετικέτα και διαχείριση γνωρισμάτων χρήστη
- Push Notifications - Καταχώριση tokens, παρακολούθηση clicks (FCM + APNs)
- Μηνύματα εντός εφαρμογής - Λήψη και εμφάνιση μηνυμάτων εντός εφαρμογής
- E-Commerce - Παρακολούθηση αγορών, συμβάντων καλαθιού και checkout
- Υποστήριξη εκτός σύνδεσης - Τα συμβάντα μπαίνουν τοπικά σε ουρά και συγχρονίζονται όταν υπάρχει σύνδεση
- Αυτόματη επανάληψη - Exponential backoff σε αποτυχίες δικτύου
Απαιτήσεις
- React Native 0.75+. Στο iOS το native SDK συνδέεται ως Swift package μέσω του
spm_dependencyτου React Native, που προστέθηκε στην 0.75. Με Expo, SDK 52 ή νεότερο. - Παλιά και Νέα Αρχιτεκτονική. Στη Νέα Αρχιτεκτονική το module τρέχει μέσω του interop layer του React Native για παλαιότερα modules, που είναι ενεργό από προεπιλογή.
- iOS 14.0+ / Android API 23+ (Android 6.0)
- TypeScript 5.0+ (συνιστάται)
Εγκατάσταση
npm install @joryio/react-native-sdk
Ρύθμιση iOS
cd ios && pod install
Το pod install προσθέτει το Joryio iOS SDK στο Pods project ως Swift package
(https://github.com/joryio/joryio-ios-sdk, products Joryio και JoryioUI, ακριβώς
στην έκδοση αυτού του πακέτου), και το Xcode το κατεβάζει την πρώτη φορά που κάνει
build την εφαρμογή - άρα εκείνο το build χρειάζεται πρόσβαση δικτύου στο github.com.
Τίποτα δεν έρχεται από το CocoaPods trunk, που σταματά να δέχεται νέες εκδόσεις
στις 2 Δεκεμβρίου 2026.
Το React Native τυπώνει κατά το pod install δύο γραμμές [SPM] WARNING για κάθε
βιβλιοθήκη που χρησιμοποιεί Swift packages: η μία ζητά να ξανανοίξετε το workspace
αν χρησιμοποιείτε Xcode 15 ή παλαιότερο, η άλλη σημειώνει ότι το πακέτο συνδέεται
στατικά. Αν η εφαρμογή αποτύχει στο link, κάντε εγκατάσταση με δυναμικά frameworks:
USE_FRAMEWORKS=dynamic pod install.
Οι προηγούμενες εκδόσεις έπαιρναν το iOS SDK από το CocoaPods (το pod Joryio/UI).
Αν προσθέσατε μόνοι σας μια γραμμή pod 'Joryio...' στο Podfile - για παράδειγμα
ένα pod με :path προς ένα τοπικό αντίγραφο - διαγράψτε την και τρέξτε ξανά
pod install.
Ρύθμιση Android
Δεν χρειάζεται να προσθέσετε τίποτα. Το package συνδέεται αυτόματα (autolinking -
περιλαμβάνει react-native.config.js), οπότε το PackageList ήδη καταχωρεί το
JoryioPackage - μην το προσθέσετε και χειροκίνητα στο MainApplication, γιατί
έτσι το module καταχωρείται δύο φορές. Η γέφυρα εξαρτάται από το
io.joryio:joryio-android-ui από το Maven Central, στην ίδια έκδοση με το package.
Expo
Το SDK είναι native module, οπότε δεν τρέχει στο Expo Go - χρησιμοποιήστε development build (npx expo prebuild ή EAS Build) σε Expo SDK 52 ή νεότερο. Το προεπιλεγμένο iOS deployment target του Expo μπορεί να είναι χαμηλότερο από το 14.0 που χρειάζεται το SDK· αυξήστε το με το expo-build-properties στο app.json:
{
"expo": {
"plugins": [["expo-build-properties", { "ios": { "deploymentTarget": "14.0" } }]]
}
}
Γρήγορη εκκίνηση
import { Platform } from 'react-native';
import Joryio from '@joryio/react-native-sdk';
// Αρχικοποίηση μία φορά στο App.tsx
await Joryio.initialize(
Platform.select({
ios: 'jry_sdk_ios_YOUR_IOS_KEY', // κλειδί iOS από το dashboard
android: 'jry_sdk_android_YOUR_ANDROID_KEY', // κλειδί Android από το dashboard
})!,
'api-eu1.joryio.com', // API host (σκέτο hostname, χωρίς scheme)
{
enableDebug: __DEV__,
trackSessionStart: true,
}
);
Κάθε πλατφόρμα έχει το δικό της κλειδί SDK: τα κλειδιά iOS ξεκινούν με jry_sdk_ios_ και τα κλειδιά Android με jry_sdk_android_. Με ένα κλειδί που η πλατφόρμα απορρίπτει, το initialize() καταγράφει προειδοποίηση και το SDK μένει ανενεργό μέχρι να το καλέσετε ξανά με το σωστό κλειδί.
Παρακολούθηση συμβάντων
Παρακολούθηση προσαρμοσμένων συμβάντων
// Basic event
Joryio.track('Button Clicked');
// Event with properties
Joryio.track('Product Added', {
productId: 'SKU-123',
productName: 'Blue T-Shirt',
price: 29.99,
currency: 'USD',
});
// E-commerce: χρησιμοποιήστε το Joryio.ecommerce (δείτε E-Commerce παρακάτω) - στέλνει τα ονόματα και τα κλειδιά που διαβάζουν οι αναφορές εσόδων
Παρακολούθηση προβολών οθόνης
// In your screen components
Joryio.trackScreen('ProductDetail', { productId: 'SKU-123' });
Joryio.trackScreen('Cart');
Joryio.trackScreen('Checkout');
Ενσωμάτωση React Navigation
import { useRef } from 'react';
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
function App() {
const navigationRef = useNavigationContainerRef();
const routeNameRef = useRef<string>();
return (
<NavigationContainer
ref={navigationRef}
onStateChange={() => {
const currentRouteName = navigationRef.current?.getCurrentRoute()?.name;
if (currentRouteName && currentRouteName !== routeNameRef.current) {
Joryio.trackScreen(currentRouteName);
routeNameRef.current = currentRouteName;
}
}}
>
{/* ... */}
</NavigationContainer>
);
}
Ταυτότητα χρήστη
Αναγνώριση χρηστών
Στέλνετε πάντα τους αριθμούς τηλεφώνου σε πλήρη διεθνή μορφή (E.164): +, ο κωδικός χώρας και μετά ο αριθμός - για παράδειγμα +972501234567. Ένας αριθμός χωρίς + διαβάζεται με την προεπιλεγμένη χώρα για αριθμούς τηλεφώνου του χώρου εργασίας· αν δεν έχει οριστεί, ή αν τα ψηφία διαβάζονται με δύο τρόπους, αποθηκεύεται ως μη επαληθευμένος και δεν χρησιμοποιείται για μηνύματα. Πώς χειρίζονται οι αριθμοί τηλεφώνου
Καλέστε το identify μετά τη σύνδεση ή όταν γνωρίζετε ποιος είναι ο χρήστης:
// After login
Joryio.identify('user-123');
// With attributes
Joryio.identify('user-123');
Joryio.setAttributes({
firstName: 'John',
plan: 'premium',
});
Aliases
Συνδέστε ένα αναγνωριστικό από άλλο σύστημα - ένα id του CRM, έναν αριθμό κάρτας πιστότητας - με το τρέχον άτομο. Λειτουργεί και για ανώνυμους επισκέπτες: το alias αποθηκεύεται στο ανώνυμο id και μένει με το άτομο όταν αυτό αναγνωριστεί.
Joryio.addAlias('crm_id', 'C-1042');
Δεν υπάρχει alias(userId) χωρίς ετικέτα. Για να ονομάσετε το τρέχον άτομο, καλέστε identify(userId).
Reset (αποσύνδεση)
Εκκαθαρίστε την ταυτότητα χρήστη και ξεκινήστε νέα ανώνυμη συνεδρία:
Joryio.reset();
Γνωρίσματα χρήστη
// Set multiple attributes
Joryio.setAttributes({
firstName: 'John',
lastName: 'Doe',
plan: 'premium',
age: 28,
isVIP: true,
});
// Set a single attribute
Joryio.setAttribute('favoriteColor', 'blue');
// Increment a numeric attribute
Joryio.incrementAttribute('loginCount', 1);
Joryio.incrementAttribute('totalSpent', 29.99);
// Remove an attribute
Joryio.unsetAttribute('temporaryFlag');
Μια τιμή null αφαιρεί το γνώρισμα και στις δύο πλατφόρμες: τα setAttribute('nickname', null) και setAttributes({ nickname: null }) κάνουν ό,τι και το unsetAttribute('nickname').
E-Commerce
Παρακολουθήστε αγορές και τα βήματα πριν από αυτές με το Joryio.ecommerce. Στέλνει τα τυπικά ονόματα συμβάντων και κλειδιά ιδιοτήτων που διαβάζουν οι αναφορές εσόδων του Joryio, ώστε να μην πληκτρολογείτε κανένα από τα δύο με το χέρι:
Joryio.ecommerce.viewProduct({ productId: 'SKU-123', name: 'Blue T-Shirt', price: 29.99 });
Joryio.ecommerce.addToCart({ productId: 'SKU-123', name: 'Blue T-Shirt', price: 29.99, quantity: 2 });
Joryio.ecommerce.startCheckout(
[{ productId: 'SKU-123', name: 'Blue T-Shirt', price: 29.99, quantity: 2 }],
59.98, // αξία καλαθιού
);
// αποστέλλεται ως "Order Completed" με orderId και total - τα κλειδιά που διαβάζουν οι αναφορές εσόδων
Joryio.ecommerce.purchase({
orderId: 'ORD-789',
items: [{ productId: 'SKU-123', name: 'Blue T-Shirt', price: 29.99, quantity: 2 }],
value: 59.98,
currency: 'USD',
});
Το purchase στέλνει ένα συμβάν Order Completed με orderId και total (το value της παραγγελίας) - τα δύο κλειδιά που διαβάζουν τα έσοδα και η απόδοση. Ένα χειρόγραφο track('Order Completed', { order_id, value }) αποθηκεύεται όπως γράφτηκε και μετράει ως παραγγελία 0 χωρίς αναγνωριστικό παραγγελίας: σκόπιμα δεν υπάρχει επίπεδο ψευδωνύμων που να αντιστοιχίζει άλλες γραφές. Αν παρακολουθείτε μια αγορά μόνοι σας, χρησιμοποιήστε orderId και total.
Οι υπόλοιπες κλήσεις: viewCategory(categoryId, categoryName), search(query, resultCount?), removeFromCart(product, quantity?), cartViewed(items, cartValue), updateCart(items, cartValue), addPaymentInfo(paymentMethod), orderFulfilled(orderId, trackingNumber?, carrier?), orderDelivered(orderId), orderCancelled(orderId, reason?), orderRefunded(orderId, refundAmount?, reason?), addToWishlist(product), removeFromWishlist(product), shareProduct(product, shareMethod), applyCoupon(couponCode, discountAmount?, discountType?), removeCoupon(couponCode), submitReview(productId, rating, reviewText?). Το ecommerce είναι επίσης named export: import { ecommerce } from '@joryio/react-native-sdk'.
Μια κλήση χωρίς υποχρεωτικό όρισμα - ένα purchase χωρίς orderId, items ή αριθμητικό value, ένα προϊόν χωρίς productId, ένα καλάθι χωρίς items - καταγράφει προειδοποίηση και δεν στέλνει τίποτα, ώστε να μην καταγράφεται ποτέ ως παραγγελία αξίας 0.
Push Notifications
Ζητήστε την άδεια όταν ο χρήστης έχει λόγο να πει ναι. Μια προτροπή στα πρώτα δευτερόλεπτα μιας συνεδρίας είναι αυτή που απορρίπτεται συχνότερα, και μια άρνηση είναι πολύ δυσκολότερο να αντιστραφεί από μια καθυστέρηση - η προτροπή του συστήματος είναι εφάπαξ, οπότε ένα "όχι" εκεί είναι ουσιαστικά μόνιμο, ενώ μια μεταγενέστερη ερώτηση δεν σας κοστίζει τίποτα.
Ισχύει όποιος μηχανισμός κι αν ζητά την άδεια. Αν το Firebase Messaging
εμφανίζει την προτροπή, όπως παρακάτω, ο χρονισμός είναι δικός σας· αν την
εμφανίζει το SDK του Joryio, δεν ρωτά για λογαριασμό σας εκτός αν ορίσετε το
requestPushPermissionAtLaunch, που είναι απενεργοποιημένο εξ ορισμού και όχι
απόν.
Ρύθμιση με Firebase (React Native Firebase)
import { Platform } from 'react-native';
import messaging from '@react-native-firebase/messaging';
// Request permission
const authStatus = await messaging().requestPermission();
// Get and register token
// Το Joryio στέλνει push στο iOS μέσω APNs, οπότε στο iOS καταχωρήστε το APNs token, όχι το FCM.
const token = Platform.OS === 'ios'
? await messaging().getAPNSToken()
: await messaging().getToken();
if (token) {
const result = await Joryio.registerPushToken(token);
if (!result.success && result.isRetryable) {
// παροδικό (εκτός σύνδεσης, DNS, 5xx): καταχωρίστε ξανά όταν επανέλθει το δίκτυο
}
}
// Listen for token refresh
messaging().onTokenRefresh((newToken) => {
// Το onTokenRefresh παραδίδει το token FCM - και στο iOS, σε κάθε εκκίνηση της εφαρμογής.
// Καταχωρίστε το μόνο στο Android· στο iOS ισχύει το token APNs παραπάνω.
if (Platform.OS === 'android') Joryio.registerPushToken(newToken);
});
Στο iOS καταχωρίστε μόνο το token συσκευής APNs. Το onTokenRefresh του React Native Firebase παραδίδει και στο iOS το token FCM, σε κάθε εκκίνηση της εφαρμογής, και αν καταχωριστεί αντικαθιστά το έγκυρο token APNs της συσκευής με ένα που το APNs απορρίπτει - γι' αυτό καταχωρίστε το μόνο στο Android, όπως παραπάνω. Στο iOS το registerPushToken απορρίπτει ένα token που δεν είναι token APNs (δεκαεξαδικό) με success: false και isRetryable: false.
Αν ο χρήστης έχει απενεργοποιήσει το push και καλέσατε unregisterPush(), μην καταχωρίζετε tokens από αυτόματα callbacks (onTokenRefresh, ένα getToken() στην εκκίνηση) μέχρι να το ενεργοποιήσει ξανά: το registerPushToken() είναι το ρητό "push ενεργό" και αναιρεί το unregister. Ελέγξτε τη δική σας ρύθμιση push πριν την καταχώριση.
Το registerPushToken επιστρέφει Promise με το αποτέλεσμα (success, message, isUnauthorized, isRetryable). Δεν απορρίπτεται ποτέ, οπότε η αγνόηση του Promise κρατά την παλιά συμπεριφορά - αλλά μια παροδική αποτυχία αφήνει τη συσκευή χωρίς εγγραφή μέχρι την επόμενη εκκίνηση, γι' αυτό ελέγξτε το isRetryable και καταχωρίστε ξανά. Το getDiagnostics().lastError φέρει την ίδια σημαία isRetryable.
Χειρισμός clicks Push Notification
import messaging from '@react-native-firebase/messaging';
// When app is in background and notification is tapped
messaging().onNotificationOpenedApp((remoteMessage) => {
const trackingId = remoteMessage.data?.trackingId;
if (trackingId) {
Joryio.trackPushClick(trackingId);
}
});
// When app was killed and opened via notification
messaging()
.getInitialNotification()
.then((remoteMessage) => {
if (remoteMessage?.data?.trackingId) {
Joryio.trackPushClick(remoteMessage.data.trackingId);
}
});
Αποδεικτικά παράδοσης
Όταν η δική σας βιβλιοθήκη μηνυμάτων λαμβάνει το push (React Native Firebase, Expo notifications), το native SDK δεν το βλέπει ποτέ, οπότε αναφέρετε την παράδοση μόνοι σας με το trackingId από τα data του μηνύματος:
messaging().onMessage(async (msg) => {
if (msg.data?.trackingId) Joryio.reportPushDelivered(String(msg.data.trackingId));
});
messaging().setBackgroundMessageHandler(async (msg) => {
if (msg.data?.trackingId) Joryio.reportPushDelivered(String(msg.data.trackingId));
});
Κατάργηση εγγραφής
Joryio.unregisterPush();
Το unregisterPush() σταματά τα push προς αυτή τη συσκευή. Ισχύει και μετά από επανεκκίνηση, μέχρι να καλέσετε ξανά το registerPushToken().
Έλεγχος κατάστασης Push
const enabled = await Joryio.isPushEnabled();
console.log('Push enabled:', enabled);
Αίτημα άδειας
if ((await Joryio.getPushPermissionStatus()) === 'notDetermined') {
// δείξτε πρώτα τη δική σας εξήγηση και μετά:
const status = await Joryio.requestPushPermission(); // 'granted' | 'denied' | 'notDetermined' | 'unavailable'
}
Το requestPushPermission() συμπεριφέρεται ίδια σε iOS και Android:
- Ολοκληρώνεται πάντα. Στο Android, αν το Activity αναδημιουργηθεί όσο εμφανίζεται το παράθυρο (περιστροφή, αλλαγή θέματος), επιστρέφει την τρέχουσα κατάσταση μόλις η εφαρμογή επανέλθει στο προσκήνιο.
- Όταν ο χρήστης έχει εξαιρεθεί από την παρακολούθηση, το παράθυρο εμφανίζεται κανονικά και επιστρέφεται το αποτέλεσμα - το αν η εφαρμογή μπορεί να στέλνει ειδοποιήσεις είναι επιλογή του χρήστη στο λειτουργικό σύστημα - αλλά τίποτα δεν καταχωρείται ούτε αναφέρεται στο Joryio όσο παραμένει εξαιρεμένος.
Μηνύματα εντός εφαρμογής
Τα μηνύματα εμφανίζονται από μόνα τους. Εγκαταστήστε το SDK, στείλτε μια καμπάνια, και εμφανίζεται - σχεδιασμένο από τα native views, με τις γραμματοσειρές, τα χρώματα και τη σκοτεινή λειτουργία της εφαρμογής σας. Δεν χρειάζεται καμία σύνδεση.
Χρειάζεστε την υπόλοιπη ενότητα μόνο αν θέλετε να αποδίδετε τα μηνύματα σε React
Tokens παράδοσης (delivery tokens)
Όταν ο διακομιστής σερβίρει μια επιλέξιμη καμπάνια, εκδίδει επίσης ένα υπογεγραμμένο token παράδοσης μικρής διάρκειας. Το SDK το επιστρέφει όταν αναφέρει εμφάνιση, κλικ ή απόρριψη, και ο διακομιστής επαληθεύει την υπογραφή πριν καταγράψει οτιδήποτε.
Δεν χρειάζεται να κάνετε τίποτα - το SDK το χειρίζεται για εσάς. Τεκμηριώνεται επειδή ο διακομιστής μπορεί να ρυθμιστεί ώστε να το απαιτεί. Από προεπιλογή, μια αναφορά χωρίς token γίνεται ακόμη δεκτή - ο διακομιστής την καταγράφει ως client παλαιότερης έκδοσης - και μόνο όταν το backend τρέχει με IN_APP_REQUIRE_DELIVERY_TOKEN=true απορρίπτεται η ίδια αναφορά:
POST /v1/in-app/track (no deliveryToken)
{ "success": false, "error": "A delivery token is required" }
Ένα token που υπάρχει αλλά δεν επαληθεύεται - πλαστό, αλλοιωμένο ή ληγμένο - απορρίπτεται πάντα, ανεξάρτητα από τη ρύθμιση.
Το token είναι αυτό που κάνει μια εμφάνιση αξιόπιστη: χωρίς αυτό, οποιοσδήποτε κατέχει το SDK key - το οποίο περιλαμβάνεται σε κάθε εφαρμογή και σελίδα - θα μπορούσε να αναφέρει εμφανίσεις και κλικ για μια καμπάνια που δεν εμφανίστηκε ποτέ, και τα δεδομένα σας θα τα μετρούσαν.
Αν οι εμφανίσεις in-app σταματήσουν να καταγράφονται σε backend που επιβάλλει tokens, ελέγξτε ότι η εφαρμογή έχει χτιστεί με τρέχουσα έκδοση του SDK: μια έκδοση από πριν υπάρξουν τα tokens παράδοσης δεν στέλνει token.
Δύο είδη περιεχομένου
Κάθε μήνυμα φέρει ένα kind που δηλώνει τη μορφή του. Διακλαδώστε σε αυτό:
kind | Τι φέρει | Πώς να το αποδώσετε |
|---|---|---|
'native' | title, body, imageUrl, buttons | Στοιχεία React Native - <Text>, <Image>, <Pressable> |
'html' | html, css | Ένα WebView |
Αναλαμβάνοντας εσείς την απόδοση
Η εγγραφή με onInAppMessage σταματά την απόδοση από το SDK και παραδίδει
κάθε μήνυμα στον κώδικά σας, ώστε να το σχεδιάσετε με στοιχεία React Native. Δεν
θα λάβετε δύο αντίγραφα.
Δηλώστε τι μπορεί να σχεδιάσει ο renderer σας:
Joryio.onInAppMessage(handleMessage, {
capabilities: ['content.native'], // προσθέστε 'content.html' μόνο αν έχετε web view
});
Οι καμπάνιες στοχεύονται με βάση ό,τι αναφέρει η συσκευή, και μια μη δηλωμένη δυνατότητα διαβάζεται ως "δεν μπορεί", όχι ως "άγνωστο". Αν παραλείψετε την επιλογή, διατηρείται η προηγούμενη συμπεριφορά, όπου η τιμή προερχόταν από μια native ρύθμιση που περιγράφει τα views του ίδιου του native SDK - τα οποία δεν εκτελούνται καθόλου μόλις εγγραφείτε.
Κάντε το αν θέλετε τα in-app μηνύματα να ταιριάζουν με το υπόλοιπο UI σας. Η ίδια
η γέφυρα εξαρτάται από τα native UI artifacts (io.joryio:joryio-android-ui στο
Android, το product JoryioUI του Swift package στο iOS), οπότε παραμένουν συνδεδεμένα· η εγγραφή απλώς
σταματά τη σχεδίασή τους.
Η αφαίρεση της τελευταίας εγγραφής επιστρέφει την απόδοση στο native SDK, οπότε τα μηνύματα που φτάνουν μετά εμφανίζονται natively αντί να χάνονται. Μια κενή λίστα capabilities σημαίνει το ίδιο με την παράλειψή της (δεν δηλώθηκε) και στις δύο πλατφόρμες.
Οι ενέργειες κουμπιών είναι dismiss, url, deep_link και request_push_permission - το «ναι» ενός μηνύματος προετοιμασίας για push: κλείστε το μήνυμα και καλέστε Joryio.requestPushPermission().
Πότε να εγγραφείτε
Από την έκδοση 1.3.2. Εγγραφείτε πριν ολοκληρωθεί το initialize() - σε επίπεδο module ή σε ένα effect που τρέχει κατά την εκκίνηση - και κανένα μήνυμα δεν σχεδιάζεται ποτέ από το native SDK, ούτε καν το πρώτο: το SDK κρατά τα in-app μηνύματα μέχρι να ολοκληρωθεί το initialize() και η εγγραφή σας να φτάσει στο native SDK, δίνει το μήνυμα που κράτησε στον listener σας και επιστρέφει την απόδοση στο native SDK μόνο αν δεν εγγράφηκε κανείς.
Αν εγγράφεστε αργότερα - σε μια οθόνη που φορτώνει αφού έχει ολοκληρωθεί το initialize() - περάστε holdInAppMessagesForHandler: true στο initialize(). Τα μηνύματα που είναι έτοιμα πριν εγγραφείτε τότε κρατούνται (δεν σχεδιάζονται, δεν αναφέρονται, δεν μετρούν σε κανένα όριο συχνότητας) και δίνονται στον listener σας όταν εγγραφεί. Αν αντί γι' αυτό καλέσετε disableInAppMessages(), η αναμονή τελειώνει και το native SDK σχεδιάζει το μήνυμα που κρατήθηκε.
Στο Android η γέφυρα δίνει στο native SDK το τρέχον Activity στο initialize(), ώστε τα μηνύματα εντός εφαρμογής να εμφανίζονται ήδη από την πρώτη συνεδρία.
Ακρόαση μηνυμάτων
import { useEffect, useState } from 'react';
import Joryio, { type InAppMessage } from '@joryio/react-native-sdk';
function App() {
const [message, setMessage] = useState<InAppMessage | null>(null);
useEffect(() => Joryio.onInAppMessage(setMessage), []);
return <>{message && <InAppMessageHost message={message} onClose={() => setMessage(null)} />}</>;
}
Απόδοση native μηνύματος
Το native περιεχόμενο είναι κείμενο, όχι markup. Βάλτε το σε ένα <Text> - περνώντας το σε WebView ή σε dangerouslySetInnerHTML θα επαναφέρατε ακριβώς τον κίνδυνο injection που το native αποφεύγει.
function InAppMessageHost({ message, onClose }: { message: InAppMessage; onClose: () => void }) {
// Αναφέρετε 'displayed' μία φορά, όταν εμφανίζεται το μήνυμα.
useEffect(() => {
Joryio.trackInAppImpression(message.id, 'displayed');
}, [message.id]);
// Αναφέρετε 'dismissed' κάθε φορά που το μήνυμα φεύγει από την οθόνη - και μετά από click.
const close = () => {
Joryio.trackInAppImpression(message.id, 'dismissed');
onClose();
};
if (message.kind === 'native') {
return (
<View>
{message.imageUrl && <Image source={{ uri: message.imageUrl }} />}
{message.title && <Text style={styles.title}>{message.title}</Text>}
<Text>{message.body}</Text>
{message.buttons.map((button) => (
<Pressable
key={button.id}
onPress={() => {
Joryio.trackInAppImpression(message.id, 'clicked', button.id);
if (button.action === 'url' && button.url) Linking.openURL(button.url);
if (button.action === 'request_push_permission') void Joryio.requestPushPermission();
close();
}}
>
<Text>{button.text}</Text>
</Pressable>
))}
</View>
);
}
// Escape του `</`, ώστε το CSS της καμπάνιας να μην μπορεί να κλείσει την ετικέτα <style>.
const css = message.css.replace(/<\//g, '<\\/');
return <WebView source={{ html: `<style>${css}</style>${message.html}` }} />;
}
Εφαρμόστε το στυλ της καμπάνιας
Το message.style φέρει τις παρακάμψεις που όρισε ο συντάκτης. Κάθε πεδίο είναι
προαιρετικό και ένα πεδίο που λείπει σημαίνει κληρονόμηση της εμφάνισης της
εφαρμογής σας - εφαρμόστε μόνο όσα υπάρχουν:
const st = message.style;
const text = {
// 'auto': στοίχιση κατά τη γλώσσα του ΜΗΝΥΜΑΤΟΣ, όχι της συσκευής.
writingDirection: 'auto' as const,
textAlign: st?.textAlign === 'center' ? 'center' : 'auto',
...(st?.fontFamily ? { fontFamily: st.fontFamily } : {}),
};
Εφαρμόστε το fontFamily μόνο αν η εφαρμογή σας περιλαμβάνει τη γραμματοσειρά.
Αν η καμπάνια ορίζει χρώμα κουμπιού χωρίς χρώμα ετικέτας, επιλέξτε μαύρο ή λευκό
κατά αντίθεση - το προεπιλεγμένο λευκό εξαφανίζει ένα ανοιχτόχρωμο γέμισμα.
Ενεργοποίηση μηνυμάτων HTML
Τα μηνύματα HTML είναι απενεργοποιημένα από προεπιλογή. Το εγγενές SDK εμφανίζει ένα μήνυμα HTML σε web view μέσα στην εφαρμογή σας. Τα scripts που γράφονται στο μήνυμα δεν εκτελούνται εκεί - εκτελείται μόνο η γέφυρα του SDK, που χειρίζεται κουμπιά και φόρμες - αλλά η ενεργοποίηση ενός web view παραμένει απόφαση της ομάδας της εφαρμογής:
await Joryio.initialize(sdkKey, apiHost, {
allowHtmlJsInAppMessages: true, // προεπιλογή: false
});
Αφήνοντάς το απενεργοποιημένο δεν απενεργοποιείτε τα in-app μηνύματα - τα native μηνύματα συνεχίζουν να φτάνουν. Μόνο οι καμπάνιες HTML παραλείπονται.
Αυτό ισχύει όσο σχεδιάζει το ίδιο το SDK. Μόλις καλέσετε enableInAppMessages(['content.native', 'content.html']), ο δικός σας κώδικας JS αποδίδει κάθε μήνυμα και η ρύθμιση δεν φράζει πλέον το HTML - η δήλωση σε εκείνη την κλήση είναι η συγκατάθεση.
Παρακολούθηση εμφανίσεων
// When message is displayed
Joryio.trackInAppImpression(message.id, 'displayed');
// When user clicks
Joryio.trackInAppImpression(message.id, 'clicked', button.id);
// When user dismisses
Joryio.trackInAppImpression(message.id, 'dismissed');
Αναφέρετε 'displayed' μία φορά, όταν εμφανίζεται το μήνυμα. Αυτή η μία αναφορά καταγράφει την εμφάνιση και είναι αυτή που μετράει στα όρια συχνότητας της καμπάνιας - η παράδοση του μηνύματος στον κώδικά σας δεν κάνει τίποτα από τα δύο, και το SDK δεν το αναφέρει για εσάς. Για ένα click, περάστε το id του κουμπιού ή του συνδέσμου ως τρίτο όρισμα, elementId, ώστε οι αναφορές να λένε ποιο κουμπί πατήθηκε· παραλείψτε το για displayed και dismissed.
Αναφέρετε 'dismissed' κάθε φορά που το μήνυμα φεύγει από την οθόνη, και μετά από click. Μέχρι τότε το μήνυμα κρατά τη θέση εμφάνισης: στο iOS δεν εμφανίζεται κανένα άλλο μήνυμα εντός εφαρμογής, και στο Android η ίδια καμπάνια δεν εμφανίζεται ξανά. Αν το 'dismissed' δεν έρθει ποτέ, το SDK ελευθερώνει τη θέση μετά από 5 λεπτά.
Φόρμες σε μηνύματα HTML
Όταν αποδίδετε μόνοι σας ένα μήνυμα HTML, υποβάλετε μια <form data-jry-form> που περιέχει μέσω του SDK, ώστε οι τιμές να σταλούν με την τρέχουσα ταυτότητα και να ελεγχθούν έναντι της φόρμας που φέρει η καμπάνια:
// { ok, message?, redirect?, errors? } - δεν απορρίπτεται ποτέ· αποτυχία σημαίνει ok: false
Συγχρονισμός και δοκιμές
Joryio.syncInAppCampaigns(); // λήψη καμπανιών τώρα και εμφάνιση όσων είναι κατάλληλες
Joryio.resetDisplayedCampaigns(); // μόνο για δοκιμές: ξεχνά τι έχει ήδη εμφανίσει η συσκευή
Το SDK ήδη συγχρονίζει στην αρχή κάθε συνεδρίας και όταν η εφαρμογή έρχεται στο προσκήνιο· καλέστε το syncInAppCampaigns() για τις στιγμές ενδιάμεσα. Το resetDisplayedCampaigns() εκτελείται μόνο όταν είναι ενεργό το enableDebug.
Τα enableInAppMessages(capabilities?) και disableInAppMessages() είναι το ζεύγος χαμηλού επιπέδου που καλεί για εσάς το onInAppMessage· χρησιμοποιήστε τα μόνο αν ακούτε το συμβάν JoryioInAppMessage με άλλο τρόπο. Όταν η JavaScript φορτώνεται ξανά, η γέφυρα επιστρέφει την απόδοση στο native SDK μέχρι ο κώδικάς σας να εγγραφεί ξανά.
Πότε ένα μήνυμα μετρά ως εμφανισμένο
Ένα μήνυμα μετρά ως εμφανισμένο - αναφέρεται το in_app.displayed και καταναλώνεται το όριο συχνότητας της καμπάνιας - μόνο όταν το άτομο μπορούσε πράγματι να το δει. Ο χρόνος που πρέπει να μείνει στην οθόνη είναι το IN_APP_DISPLAY_DWELL_MS (1000 ms), η ίδια σταθερά σε κάθε Joryio SDK.
- Τα μηνύματα που σχεδιάζει το native SDK ακολουθούν τον κανόνα των iOS και Android: εμφανίζονται μόνο σε σταθερή οθόνη στο προσκήνιο και μετρούν μετά από 1 δευτερόλεπτο στην οθόνη με την εφαρμογή στο προσκήνιο. Ένα πάτημα ή κλείσιμο νωρίτερα μετρά ως προβολή· ένα μήνυμα που φεύγει από την οθόνη νωρίτερα δεν μετρά και παραμένει επιλέξιμο.
- Αν σχεδιάζετε μόνοι σας τα μηνύματα (
onInAppMessage), αναφέρετε το'displayed'με τον ίδιο κανόνα - τοIN_APP_DISPLAY_DWELL_MSεξάγεται: αφού το μήνυμα είναι ορατό τόσο χρόνο, ή αμέσως πριν από ένα κλικ ή κλείσιμο που έρχεται νωρίτερα. Μην το αναφέρετε για μήνυμα που έφυγε πρώτα από την οθόνη.
Επιλογές ρυθμίσεων
| Επιλογή | Τύπος | Προεπιλογή | Περιγραφή |
|---|---|---|---|
enableDebug | boolean | false | Ενεργοποιεί debug logging |
logLevel | string | προκύπτει από το enableDebug | Επίπεδο log: debug, info, warn, error. Αν δεν οριστεί, και οι δύο εγγενείς γέφυρες χρησιμοποιούν 'debug' όταν το enableDebug είναι true και 'error' αλλιώς - δεν υπάρχει σταθερή προεπιλογή. Ορίστε το μόνο για να το παρακάμψετε. |
batchSize | number | 50 | Συμβάντα ανά παρτίδα πριν από αυτόματη αποστολή (εγγενής προεπιλογή) |
flushInterval | number | 5000 | Διάστημα αυτόματης αποστολής σε ms (εγγενής προεπιλογή) |
sendImmediately | boolean | false | Αποστολή κάθε συμβάντος αμέσως μόλις καταγραφεί, χωρίς παρτίδες (δεν συνιστάται για παραγωγή) |
maxQueueSize | number | 1000 | Μέγιστος αριθμός συμβάντων που κρατά η τοπική ουρά όσο οι αποστολές αποτυγχάνουν· πέρα από αυτόν τα παλαιότερα απορρίπτονται (εγγενής προεπιλογή) |
requestTimeout | number | 10000 | Χρονικό όριο HTTP ανά αίτημα σε ms (εγγενής προεπιλογή) |
sessionTimeout | number | 1800000 | Λήξη συνεδρίας σε ms (εγγενής προεπιλογή: 30 λεπτά) |
trackSessionStart | boolean | true | Αυτόματη παρακολούθηση συμβάντων έναρξης συνεδρίας |
userId | string | null | Προκαθορισμένο ID χρήστη κατά την αρχικοποίηση |
anonymousId | string | δημιουργείται | Το δικό σας ανώνυμο id για αυτή τη συσκευή. Χρησιμοποιείται για αυτή την εκτέλεση και αποθηκεύεται μόνο όταν δεν υπάρχει ήδη κάτι αποθηκευμένο, ώστε ένα id που ορίστηκε μία φορά να επιβιώνει αν η εφαρμογή πάψει να περνά την επιλογή |
requestPushPermissionAtLaunch | boolean | false | Ζητά την άδεια ειδοποιήσεων κατά το initialize. Προτιμήστε να ρωτάτε τη στιγμή που ο χρήστης καταλαβαίνει γιατί |
allowHtmlJsInAppMessages | boolean | false | Επιτρέπει στο native SDK να σχεδιάζει in-app μηνύματα HTML (δείτε Ενεργοποίηση μηνυμάτων HTML) |
holdInAppMessagesForHandler | boolean | false | Από την έκδοση 1.3.2. Η εφαρμογή σας σχεδιάζει τα in-app μηνύματα και εγγράφεται αφού ολοκληρωθεί το initialize(): τα μηνύματα κρατούνται μέχρι τότε (δείτε Πότε να εγγραφείτε) |
enableSdkAuthentication | boolean | false | Επισυνάπτει ένα JWT που εκδίδετε εσείς σε κάθε αίτημα αποστολής δεδομένων |
sdkAuthenticationToken | string | - | Το αρχικό JWT όταν το enableSdkAuthentication είναι ενεργό |
trackingConsent | 'granted' | 'denied' | 'pending' | χωρίς τιμή | Συναίνεση παρακολούθησης κατά την εκκίνηση. Αφήστε το χωρίς τιμή, εκτός αν έχετε απάντηση από το banner συναίνεσης - βλ. Συναίνεση κατά την εκκίνηση |
optOut | boolean | false | Έναρξη με εξαίρεση από την παρακολούθηση |
notificationChannelName | string | "Notifications" | Μόνο Android: το όνομα του καναλιού ειδοποιήσεων που βλέπουν οι χρήστες στις ρυθμίσεις συστήματος (Android 8+). Δώστε το μεταφρασμένο. Αγνοείται στο iOS |
Εργαλεία
// Flush events immediately (before app close, logout, etc.)
Joryio.flush();
// Get IDs
const anonymousId = await Joryio.getAnonymousId();
const userId = await Joryio.getUserId(); // null if not identified
const sessionId = await Joryio.getSessionId();
Υποστήριξη TypeScript
Το SDK είναι πλήρως τυποποιημένο. Εισαγάγετε types όπως χρειάζεται:
import Joryio, {
type JoryioConfig,
type UserAttributes,
type InAppMessage,
} from '@joryio/react-native-sdk';
Συναίνεση παρακολούθησης
Δύο ξεχωριστοί διακόπτες αποφασίζουν αν το SDK συλλέγει οτιδήποτε, και κάθε "όχι" υπερισχύει:
- Συναίνεση - η απάντηση από το banner συναίνεσης:
'granted','denied'ή'pending'. Ορίζεται με τοtrackingConsentστοinitialize()ή με τοupdateConsent(). - Εξαίρεση (opt-out) - η επιλογή του ίδιου του ατόμου. Ορίζεται με το
optOut()και αίρεται μόνο με τοoptIn().
Το SDK συλλέγει μόνο όσο η συναίνεση είναι granted και το άτομο δεν έχει εξαιρεθεί. Η παροχή συναίνεσης δεν ακυρώνει ποτέ μια εξαίρεση, και η εξαίρεση δεν αλλάζει ποτέ την αποθηκευμένη συναίνεση.
Διακοπή και επανέναρξη της συλλογής. Πρόκειται για συναίνεση παρακολούθησης, όχι για συνδρομή μάρκετινγκ - το optOut() δεν διαγράφει κανέναν από το email ή το SMS. Αυτά ζουν στην κατάσταση συνδρομής της επαφής.
// Ο χρήστης αρνήθηκε την παρακολούθηση
Joryio.optOut();
// ...και αργότερα αποδέχτηκε
Joryio.optIn();
const optedOut = await Joryio.isUserOptedOut(); // μόνο ο διακόπτης εξαίρεσης
const consent = await Joryio.getTrackingConsent(); // 'granted' | 'denied' | 'pending'
Το wipeData() διαγράφει ό,τι κρατά η συσκευή για το τρέχον άτομο - ταυτότητα, συμβάντα στην ουρά, εκκρεμείς εγγραφές, κατάσταση μηνυμάτων εντός εφαρμογής, συνεδρία, αναγνωριστικό συσκευής και token push - και καταργεί την εγγραφή του token στον διακομιστή. Η εξαίρεση (opt-out) διατηρείται. Το push μένει ανενεργό μέχρι το registerPushToken() ή τη χορήγηση άδειας.
Το optOut() καταγράφει την απόφαση στο προφίλ ως tracking_opted_out πριν σταματήσει να στέλνει, ώστε ένα κοινό να μπορεί να εξαιρέσει όσους αρνήθηκαν. Το optIn() την καθαρίζει. Είναι σήμα για στόχευση, όχι επιβολή.
Τα συμβάντα που είναι ήδη στην ουρά απορρίπτονται από το optOut(), δεν κρατούνται για αργότερα.
Συναίνεση κατά την εκκίνηση
Για να αποφασίσετε πριν σταλεί οτιδήποτε, περάστε τη συναίνεση στο initialize() και ενημερώστε την από το παράθυρο συναίνεσης:
await Joryio.initialize(sdkKey, apiHost, { trackingConsent: 'pending' });
// αργότερα
Joryio.updateConsent('granted'); // 'granted' | 'denied' | 'pending'
- Αφήστε το
trackingConsentχωρίς τιμή, εκτός αν το banner σας έχει απάντηση για αυτή την εκκίνηση. Χωρίς τιμή και χωρίς τίποτα αποθηκευμένο, η συμπεριφορά είναι όπως μεgranted· έναdeniedαποθηκευμένο από προηγούμενη εκκίνηση παραμένει σε ισχύ. - Το
deniedαποθηκεύεται στη συσκευή και διατηρείται μετά από επανεκκίνηση. Μόνο τοupdateConsent('granted')ή ένα ρητόtrackingConsent: 'granted'το αίρει. - Το
pendingισχύει μόνο για την τρέχουσα εκκίνηση και δεν αντικαθιστά ποτέ ένα αποθηκευμένοdenied. Όσο η συναίνεση είναιpendingδεν στέλνεται τίποτα: τα συμβάντα και οι αλλαγές γνωρισμάτων περιμένουν στη συσκευή (έωςmaxQueueSize), και δεν γίνεται έναρξη συνεδρίας, συγχρονισμός μηνυμάτων εντός εφαρμογής ή εγγραφή για push. ΤοupdateConsent('granted')στέλνει ό,τι περίμενε, ενώ τοupdateConsent('denied')το απορρίπτει. - Περάστε
optOut: trueγια να ξεκινήσετε εξαιρεμένοι. Η εξαίρεση αποθηκεύεται στη συσκευή και διατηρείται μετά από επανεκκίνηση· τοoptOut: falseδεν αναιρεί ένα προηγούμενοoptOut()- καλέστε τοoptIn(). - Αν η εφαρμογή σας γνωρίζει ήδη την απάντηση κατά την εκκίνηση - για παράδειγμα μια επιλογή banner που αποθήκευσε η ίδια - περάστε την ως
trackingConsentστοinitialize()αντί να καλέσετε τοupdateConsent()μετά, ώστε το SDK να ξεκινήσει με αυτή την απάντηση σε ισχύ. Τα κεφαλαία και τα πεζά δεν έχουν σημασία (το'Denied'διαβάζεται ως'denied')· μια άγνωστη τιμή αγνοείται με προειδοποίηση και η συναίνεση μένει χωρίς τιμή.
Αποφάσεις πριν από το initialize()
Τα optOut(), optIn(), updateConsent() και wipeData() μπορούν να κληθούν πριν από το initialize() και εφαρμόζονται πρώτα: καμία έναρξη συνεδρίας, συγχρονισμός μηνυμάτων εντός εφαρμογής ή εγγραφή για push δεν φεύγει πριν από αυτά. Οι προηγούμενες κλήσεις που συλλέγουν δεδομένα - συμβάντα, γνωρίσματα, aliases, αλλαγές συνδρομών - απορρίπτονται από ένα optOut(), updateConsent('denied') ή wipeData() που ακολουθεί, αντί να σταλούν όταν ξεκινήσει το SDK. Απορρίπτονται επίσης τέτοιες κλήσεις που γίνονται ενώ ισχύει opt-out ή άρνηση - και πριν από το initialize(), είτε η απόφαση πάρθηκε σε αυτή την εκκίνηση είτε αποθηκεύτηκε από προηγούμενη - και ένα μεταγενέστερο optIn() ή updateConsent('granted') δεν τις στέλνει. Το identify απορρίπτεται μόνο από το wipeData(). Ένα προηγούμενο setSdkAuthenticationToken() δεν μεταφέρεται ποτέ στον επόμενο επισκέπτη: σε iOS και Android η διαγραφή το κρατά μόνο για τις ανακλήσεις του προσώπου που διαγράφηκε, ή το απορρίπτει. Μετά από optOut() ή άρνηση το user id κρατιέται στη συσκευή, χωρίς να σταλεί, μόνο ώστε μια απεγγραφή να φτάσει στο σωστό πρόσωπο. Οι ανακλήσεις αποτελούν εξαίρεση: τα setSubscription(channel, 'unsubscribed'), removeFromSubscriptionGroup και unregisterPush() που έγιναν νωρίτερα κρατούνται και στέλνονται.
Μια απόφαση που λαμβάνεται ενώ τρέχει ένα initialize() που τελικά αποτυγχάνει εφαρμόζεται τη στιγμή της αποτυχίας, πριν από το επόμενο initialize(): η νέα προσπάθεια ξεκινά με αυτήν σε ισχύ.
Τα isUserOptedOut() και getTrackingConsent() μπορούν επίσης να κληθούν πριν από το initialize(). Όσο τρέχει το initialize() το περιμένουν· σε κάθε άλλη περίπτωση - πριν από το initialize() και μετά από ένα που απέτυχε - απαντούν αμέσως από ό,τι είναι αποθηκευμένο στη συσκευή, οπότε μια εξαίρεση ή ένα denied από προηγούμενη εκκίνηση φαίνεται αμέσως. Αν δεν έχει ληφθεί απόφαση και δεν υπάρχει τίποτα αποθηκευμένο, το getTrackingConsent() απαντά 'granted', την κατάσταση στην οποία λειτουργεί το SDK, και στις δύο πλατφόρμες.
Συνδρομή μάρκετινγκ
Αν επιτρέπεται να στέλνουμε μηνύματα σε αυτό το άτομο σε ένα κανάλι. Διαφορετική συναίνεση από το optOut(), που αφορά αν επιτρέπεται να το παρακολουθούμε - καμία δεν συνεπάγεται την άλλη.
Αυτό γράφει ένα κέντρο προτιμήσεων μέσα στην εφαρμογή.
Joryio.setSubscription('email', 'unsubscribed');
Οι ομάδες συνδρομής είναι λίστες στις οποίες ένα άτομο μπορεί να μπει ή από τις οποίες μπορεί να βγει, ανά κανάλι:
Joryio.addToSubscriptionGroup('list_abc123', 'email');
Joryio.removeFromSubscriptionGroup('list_abc123', 'email');
Κανάλια: email, sms, whatsapp, push, viber. Καταστάσεις: optedIn, subscribed, unsubscribed.
Απαιτείται αναγνωριστικό - η κλήση παραλείπεται, με καταγραφή σφάλματος, αν δεν υπάρχει ούτε user id ούτε anonymous id.
SDK Authentication
Προαιρετικό. Όταν είναι ενεργό, ένα αίτημα που φέρει user id πρέπει να φέρει και ένα JWT που εξέδωσε ο backend σας για αυτόν τον χρήστη· οι κλήσεις για ανώνυμους επισκέπτες γίνονται δεκτές χωρίς αυτό.
await Joryio.initialize(sdkKey, apiHost, {
enableSdkAuthentication: true,
sdkAuthenticationToken: initialToken,
});
const stop = Joryio.onSdkAuthenticationError(async (error) => {
// error.reason: 'missing' | 'invalid' | 'expired' | 'sub_mismatch' | 'unknown'
// error.refreshExhausted: true μόλις το SDK σταματήσει να ξαναδοκιμάζει αυτό το αίτημα
Joryio.setSdkAuthenticationToken(await fetchFreshToken());
});
Καλέστε το setSdkAuthenticationToken(token) μετά τη σύνδεση και όποτε ο handler σας έχει νέο token· επισυνάπτεται σε κάθε επόμενο αίτημα. Το onSdkAuthenticationError επιστρέφει συνάρτηση κατάργησης εγγραφής.
Διαγνωστικά
const { apiEndpoint, lastError } = await Joryio.getDiagnostics();
// lastError: { message, isUnauthorized, isRetryable, at } - ξανά null μόλις μια κλήση πετύχει
Χρησιμοποιήστε το όταν μια ενσωμάτωση δεν συμπεριφέρεται σωστά: ένα λάθος SDK key φαίνεται αρχικοποιημένο ενώ κάθε αίτημα αποτυγχάνει με isUnauthorized: true.
Ασφαλές με null και πρόωρες κλήσεις
- Κάθε κλήση είναι ασφαλής πριν ολοκληρωθεί το
initialize(): έως 1.000 κλήσεις κρατούνται και εκτελούνται με τη σειρά, και οι getters περιμένουν έως 5 δευτερόλεπτα πριν επιστρέψουν μια προεπιλογή. Πέρα από τις 1.000 απορρίπτονται οι παλαιότερες, πρώτα οι κλήσεις δεδομένων: μια απεγγραφή, τοunregisterPush()ή μια απόφαση απορρήτου απορρίπτεται μόνο όταν δεν έχει μείνει τίποτε άλλο. - Το
nullή τοundefinedδεν ρίχνει ποτέ την εφαρμογή σας. Μια τιμή ρύθμισης null σημαίνει την προεπιλογή· μια κλήση χωρίς υποχρεωτικό όρισμα (όνομα συμβάντος, user id, token) καταγράφει προειδοποίηση και δεν κάνει τίποτα· μια τιμή γνωρίσματος null αφαιρεί το γνώρισμα. - Αν το
initialize()αποτύχει, οι κλήσεις κρατούνται με τον ίδιο τρόπο και στέλνονται μόλις πετύχει ένα επόμενοinitialize()- μπορείτε να το καλέσετε ξανά με διορθωμένες τιμές. Οι listeners που καταχωρίσατε (onInAppMessage,onSdkAuthenticationError) και οι απεγγραφές που έγιναν στο μεταξύ διατηρούνται, δεν χάνονται. Μια απόφαση απορρήτου που λήφθηκε ενώ τοinitialize()έτρεχε ακόμη εφαρμόζεται τη στιγμή της αποτυχίας, οπότε η νέα προσπάθεια ξεκινά με αυτήν. - Δύο επικαλυπτόμενες κλήσεις
initialize()- το React StrictMode εκτελεί τα effects δύο φορές - μοιράζονται μία εκκίνηση. Μια μεταγενέστερη κλήση αγνοείται και το SDK συνεχίζει να λειτουργεί· για αλλαγμένες ρυθμίσεις χρειάζεται επανεκκίνηση της εφαρμογής. - Τα
NaNκαιInfinityδεν στέλνονται ποτέ: μια τιμή γνωρίσματος ή ιδιότητα συμβάντος που περιέχει ένα από αυτά παραλείπεται με προειδοποίηση, και η υπόλοιπη κλήση συνεχίζεται. ΤοsetAttribute(key, NaN)αγνοείται αντί να αφαιρέσει το γνώρισμα. Ελέγχονται και οι τιμές μέσα σε instances δικών σας κλάσεων - για παράδειγμα μια γραμμή καλαθιού φτιαγμένη από κλάση. - Ένα callback που περνάτε στο
onInAppMessageή στοonSdkAuthenticationErrorκαι πετάει σφάλμα (ή επιστρέφει promise που απορρίπτεται) πιάνεται και καταγράφεται. Δεν ρίχνει ποτέ την εφαρμογή σας και δεν σταματά άλλους listeners.
Αναφορά API
| Περιοχή | Μέθοδοι |
|---|---|
| Ρύθμιση | initialize(sdkKey, apiHost, config?) |
| Συμβάντα | track(eventName, properties?), trackScreen(screenName, properties?), flush() |
| Ταυτότητα | identify(userId), addAlias(aliasLabel, aliasName), reset(), getUserId(), getAnonymousId(), getSessionId() |
| Γνωρίσματα | setAttributes(attributes), setAttribute(key, value), incrementAttribute(key, by?), unsetAttribute(key) |
| Push | registerPushToken(token), unregisterPush(), reportPushDelivered(trackingId), trackPushClick(trackingId), getPushPermissionStatus(), requestPushPermission(), isPushEnabled() |
| Εντός εφαρμογής | onInAppMessage(callback, options?), trackInAppImpression(campaignId, action, elementId?), submitInAppForm(campaignId, values), syncInAppCampaigns(), resetDisplayedCampaigns(), enableInAppMessages(capabilities?), disableInAppMessages() |
| Συναίνεση | optOut(), optIn(), isUserOptedOut(), getTrackingConsent(), updateConsent(consent), wipeData() |
| Συνδρομές | setSubscription(channel, status), addToSubscriptionGroup(groupId, channel), removeFromSubscriptionGroup(groupId, channel) |
| SDK Authentication | setSdkAuthenticationToken(token), onSdkAuthenticationError(callback) |
| E-commerce | Joryio.ecommerce.* - δείτε E-Commerce |
| Διαγνωστικά | getDiagnostics() |
Δοκιμές με Jest
Το main του πακέτου είναι μεταγλωττισμένο JavaScript, οπότε η ρύθμιση του Jest δεν χρειάζεται καταχώριση transformIgnorePatterns γι' αυτό. Χωρίς mock του NativeModules.JoryioModule κάθε κλήση είναι no-op, οι getters επιστρέφουν τις προεπιλεγμένες τιμές τους και καμία κλήση δεν πετά σφάλμα.