PageSense iOS SDK React Native Bridge Integration Guide

PageSense iOS SDK React Native Bridge Integration Guide

Introduction

This document explains how to integrate the PageSense iOS SDK into a React Native application using the React Native Native Bridge.

The guide covers:

  • React Native Native Bridge architecture
  • Integrating the PageSense iOS SDK
  • Creating a Swift native module
  • Exposing native functions to React Native
  • Creating a JavaScript wrapper
  • Running experiments and tracking goals
  • Best practices for production environments

The final result allows React Native applications to call PageSense SDK functions directly from React Native code such as:

  • createNewPageSenseClient
  • activateExperiment
  • getVariationName
  • trackGoal

What is the React Native Native Bridge

The React Native Native Bridge allows JavaScript code to communicate with platform-specific native code.

This enables React Native applications to use:

  • iOS SDKs
  • Android SDKs
  • Device APIs
  • Native libraries

How it Works

a. JavaScript calls a function in NativeModules
b. React Native sends the request across the bridge
c. Native code executes the request
d. Native code returns the result as a Promise

Architecture Overview — iOS SDK Integration with React Native Applications

React Native applications primarily execute JavaScript code, whereas the PageSense SDK for iOS is implemented in Swift. Since JavaScript cannot directly interact with Swift code, React Native provides a Native Bridge mechanism. This bridge enables communication between the JavaScript layer and native modules, allowing the app to call SDK functions, retrieve experiment variations, and track goals seamlessly from the React Native code.

PageSense iOS SDK React Native – Native Bridge Architecture

React Native UI
        ↓
React Native Wrapper (TypeScript/JavaScript)
        ↓
React Native Native Bridge
        ↓
Objective-C Bridge Module (.m)
        ↓
Swift Native Module (.swift)
        ↓
PageSense iOS SDK

PageSense SDK Capabilities

The PageSense SDK exposes the following functions.

Feature

Function

Description

Initialize SDK

createNewPageSenseClient

Creates and initialises a PageSense client instance in the application. This client instance is responsible for communicating with the PageSense service and managing experiments for the user session.

Activate Experiment

activateExperiment

Activates a specific experiment for the user and allocates them to an appropriate variation based on the experiment configuration.

Get Variation Name

getVariationName

Retrieves the name of the variation assigned to the current user for a particular experiment, allowing the application to apply the corresponding UI or behaviour changes.

Track Goal

trackGoal

Records and tracks conversion events or goals defined in the experiment, helping measure the effectiveness and performance of different variations.

Integration Prerequisites

Ensure that the following tools are installed in the development environment to enable the use of the React Native Native Bridge for integrating the PageSense iOS SDK with React Native applications.

Packages Required:

  • Node.js
  • npm
  • React Native CLI
  • Xcode
  • CocoaPods

Verify installation:

# Check the installed Node.js version
node -v

# Verify the installed npm version
npm -v

# Check the installed CocoaPods version
pod --version

Installing the PageSense iOS SDK in the React Native Applications

PageSense iOS SDK can be distributed using XCFramework.

a. PageSense iOS SDK (PageSenseFramework.xcframework) can be downloaded from the following repository:
https://github.com/zoho/ZohoPageSenseSDK

b. Navigate to the above repository and open the Frameworks folder.

c. Download the file PageSenseFramework.xcframework.zip and extract its contents.

d. Place the extracted PageSense XCFramework in the iOS project folder at the location:
/ProjectRoot/ios/Frameworks/PageSenseFramework.xcframework

e. Open the workspace in Xcode and add the PageSenseFramework.xcframework to the project.

f. In Xcode, navigate to the project Target settings.

g. Go to: Target → General → Frameworks, Libraries and Embedded Content

h. Add the PageSenseFramework.xcframework to this section.

i. Set the framework option to: Embed & Sign

iOS React Native Libraries

Ensure that the required React Native libraries are installed in the iOS project using CocoaPods. These libraries are automatically installed when running the command pod install from the ios directory. The following React Native libraries must be available in the project as part of the CocoaPods installation:

  • React-Core
  • React-RCTBridge
  • React-RCTNetwork
  • React-RCTText
  • React-RCTImage

In addition, ensure that the following iOS framework dependencies required for implementing the React Native Native Bridge are available:

  • React
  • RCTBridgeModule
  • Foundation

These libraries enable the implementation of native modules in Swift or Objective-C and allow the PageSense iOS SDK to be exposed to the React Native application through the React Native Native Bridge.

Creating the Native Bridge Module

React Native native modules are implemented in two parts:

a. Swift Implementation
b. Objective-C Bridge

The Objective-C layer exposes Swift methods to React Native.

i. Creating the Swift Native Module

Create the native module file for the PageSense iOS SDK using Swift. This file should be placed within the iOS application directory located inside the iOS folder of the React Native project's root directory.

Example: /ProjectRoot/ios/SampleApp/PageSenseSDKModule.swift

  1. import Foundation
  2. import React
  3. import PageSenseFramework
  4. /**
  5.  React Native Native Module for integrating the PageSense iOS SDK with a React Native application.
  6.  This module maintains a single PageSenseClient instance which is reused across multiple experiment
  7.  operations during the app lifecycle.
  8.  */
  9. @objc(PageSenseSDKModule)
  10. class PageSenseSDKModule: NSObject {
  11.     // Holds the instance of the PageSense Client
  12.     private var client: PageSenseClient?
  13.     // Indicates whether the PageSense SDK has already been initialized
  14.     private var isInitialized: Bool = false
  15.     // Prevent React Native from forcing initialization on main thread
  16.     @objc
  17.     static func requiresMainQueueSetup() -> Bool {
  18.         return false
  19.     }
  20.     /**
  21.      Initializes the PageSense SDK and creates a PageSenseClient instance.
  22.      Parameters:
  23.      - accountId: PageSense account ID.
  24.      - sdkKey: SDK key used for authentication.
  25.      - projectName: Name of the PageSense project.
  26.      - resolve: Promise resolver to return success or failure to React Native layer.
  27.      - reject: Promise rejecter (not used as failures return `false`).
  28.      Returns:
  29.      - `true` if SDK initialization is successful or already initialized.
  30.      - `false` if SDK initialization fails.
  31.      */
  32.     @objc
  33.     func initialiseSDK(
  34.         _ accountId: String,
  35.         sdkKey: String,
  36.         projectName: String,
  37.         resolver resolve: @escaping RCTPromiseResolveBlock,
  38.         rejecter reject: @escaping RCTPromiseRejectBlock
  39.     ) {
  40.         // Prevent duplicate initialization attempts.
  41.         if self.isInitialized {
  42.             print("PageSenseClient already initialized")
  43.             resolve(true)
  44.             return
  45.         }
  46.         // Configure the PageSense SDK Options
  47.         let pageSenseSDKOptions = PageSenseSDKOptions()
  48.         pageSenseSDKOptions.logLevel = .DEBUG
  49.         pageSenseSDKOptions.pollingInterval = 5 // Polling interval in minutes
  50.         // Create a new PageSense client instance
  51.         PageSense.shared.createNewPageSenseClient(
  52.             sdkAccountIDForDC: accountId,
  53.             sdkKey: sdkKey,
  54.             projectname: projectName,
  55.             sdkOptions: pageSenseSDKOptions
  56.         ) { pagesenseclient in
  57.             // Validate the returned client instance
  58.             guard let client = pagesenseclient else {
  59.                 print("PageSenseClient initialization failed")
  60.                 resolve(false)
  61.                 return
  62.             }
  63.             // Store the PageSense client instance
  64.             self.client = client
  65.             self.isInitialized = true
  66.             print("PageSenseClient initialized successfully")
  67.             // Notify the React Native layer that initialization succeeded
  68.             resolve(true)
  69.         }
  70.     }
  71.     /**
  72.      Activates an experiment for the given user and returns the assigned variation.
  73.      Parameters:
  74.      - experimentName: Name of the experiment configured in PageSense.
  75.      - userId: Unique identifier for the user.
  76.      - attributes: Optional user attributes used for audience targeting.
  77.      - resolve: Promise resolver returning the assigned variation name or `nil`.
  78.      - reject: Promise rejecter (not used as failures return `nil`).
  79.      Returns:
  80.      - Variation name if assigned.
  81.      - `nil` if no variation is assigned or SDK is not initialized.
  82.      */
  83.     @objc
  84.     func activateExperiment(
  85.         _ experimentName: String,
  86.         userId: String,
  87.         attributes: NSDictionary,
  88.         resolver resolve: @escaping RCTPromiseResolveBlock,
  89.         rejecter reject: @escaping RCTPromiseRejectBlock
  90.     ) {
  91.         // Ensure the SDK has been initialized before attempting experiment activation
  92.         guard let client = self.client else {
  93.             print("PageSenseSDK - activateExperiment called before SDK initialization")
  94.             resolve(nil)
  95.             return
  96.         }
  97.         // Convert React Native NSDictionary to Swift Dictionary
  98.         var attrs = attributes as? [String: String] ?? [:]
  99.         // Add the user attribute values
  100.         attrs["DeviceType"] = "Tablet"
  101.         attrs["OS"] = "iOS"
  102.         attrs["OSVersion"] = "17.0"
  103.         attrs["DeviceModel"] = "iPhone 15 Pro"
  104.         // Activate experiment for the specified user
  105.         client.activateExperiment(
  106.             experimentName: experimentName,
  107.             userId: userId,
  108.             userAttributes: attrs
  109.         ) { variationName in
  110.             if let variation = variationName {
  111.                 print("PageSenseSDK - Variation activated:", variation)
  112.                 resolve(variation)
  113.             } else {
  114.                 print("PageSenseSDK - No variation assigned")
  115.                 resolve(nil)
  116.             }
  117.         }
  118.     }
  119.     /**
  120.      Retrieves the variation name assigned to the user for the given experiment.
  121.      Parameters:
  122.      - experimentName: Name of the experiment.
  123.      - userId: Unique identifier for the user.
  124.      - attributes: Optional user attributes used for audience targeting.
  125.      - resolve: Promise resolver returning the variation name or `nil`.
  126.      - reject: Promise rejecter (not used as failures return `nil`).
  127.      Returns:
  128.      - Variation name if available.
  129.      - `nil` if variation is not found or SDK is not initialized.
  130.      */
  131.     @objc
  132.     func getVariationName(
  133.         _ experimentName: String,
  134.         userId: String,
  135.         attributes: NSDictionary,
  136.         resolver resolve: @escaping RCTPromiseResolveBlock,
  137.         rejecter reject: @escaping RCTPromiseRejectBlock
  138.     ) {
  139.         // Ensure SDK initialization before retrieving variation
  140.         guard let client = self.client else {
  141.             print("PageSenseSDK - getVariationName called before SDK initialization")
  142.             resolve(nil)
  143.             return
  144.         }
  145.         // Convert React Native NSDictionary to Swift Dictionary
  146.         let attrs = attributes as? [String: String] ?? [:]
  147.         // Retrieve variation for the user
  148.         let variationName = client.getVariationName(
  149.             experimentName: experimentName,
  150.             userId: userId,
  151.             userAttributes: attrs
  152.         )
  153.         if let variation = variationName {
  154.             print("PageSenseSDK - Variation retrieved:", variation)
  155.             resolve(variation)
  156.         } else {
  157.             print("PageSenseSDK - Variation not found")
  158.             resolve(nil)
  159.         }
  160.     }
  161.     /**
  162.      Tracks a goal conversion event for the specified experiment.
  163.      Parameters:
  164.      - experimentName: Name of the experiment.
  165.      - userId: Unique identifier for the user.
  166.      - goalName: Name of the goal configured in PageSense.
  167.      - attributes: Optional user attributes for audience targeting.
  168.      */
  169.     @objc
  170.     func trackGoal(
  171.         _ experimentName: String,
  172.         userId: String,
  173.         goalName: String,
  174.         attributes: NSDictionary
  175.     ) {
  176.         // Ensure SDK initialization before tracking goals
  177.         guard let client = self.client else {
  178.             print("PageSenseSDK - trackGoal called before SDK initialization")
  179.             return
  180.         }
  181.         // Convert React Native NSDictionary into Swift dictionary
  182.         var attrs = attributes as? [String: String] ?? [:]
  183.         // Add the user attribute values
  184.         attrs["DeviceType"] = "Phone"
  185.         attrs["OS"] = "iOS"
  186.         attrs["OSVersion"] = "17.0"
  187.         attrs["DeviceModel"] = "iPhone 15 Pro"
  188.         // Track goal event
  189.         client.trackGoal(
  190.             experimentName: experimentName,
  191.             userId: userId,
  192.             goalName: goalName,
  193.             userAttributes: attrs
  194.         )
  195.         print("PageSenseSDK - Goal tracked:", goalName)
  196.     }
  197. }

Adding Objective-C Bridging Header

a. To enable communication between Swift and Objective-C, create a bridging header at the following location:
/ProjectRoot/ios/SampleApp/SampleApp-Bridging-Header.h

b. Open the project in Xcode and navigate to Build Settings.

c. Locate Objective-C Bridging Header.

d. Set its value to: SampleApp/SampleApp-Bridging-Header.h

Creating the React Native Wrapper

Create the React Native wrapper file to enable interaction between the React Native application and the native PageSense SDK implementation. This wrapper acts as an interface layer that exposes the native module methods to the JavaScript code in the React Native application.

The JavaScript wrapper file should be created at the following path within the project structure:
src/sdk/PageSenseSDKWrapper.js

  1. import { NativeModules } from 'react-native';
  2. // Extract the native module exposed through the React Native bridge.
  3. const { PageSenseSDKModule } = NativeModules;
  4. /**
  5.  * PageSenseSDKWrapper provides a JavaScript interface for interacting
  6.  * with the PageSense SDK through the React Native Native Bridge.
  7.  */
  8. class PageSenseSDKWrapper {
  9.     /**
  10.      * Initialise the PageSense SDK. Should be called once during application startup.
  11.      *
  12.      * @param {string} accountId - PageSense account identifier.
  13.      * @param {string} sdkKey - SDK key used for authentication.
  14.      * @param {string} projectName - Name of the PageSense project.
  15.      *
  16.      * @returns {Promise<boolean>}
  17.      * Returns:
  18.      * - true → SDK initialized successfully
  19.      * - false → initialization failed
  20.      */
  21.     async initialiseSDK(accountId, sdkKey, projectName) {
  22.         try {
  23.             this._validateString(accountId, 'accountId');
  24.             this._validateString(sdkKey, 'sdkKey');
  25.             this._validateString(projectName, 'projectName');
  26.             const result = await PageSenseSDKModule.initialiseSDK(
  27.                 accountId,
  28.                 sdkKey,
  29.                 projectName,
  30.             );
  31.             return result === true;
  32.         } catch (error) {
  33.             console.log('[PageSenseSDK] initialiseSDK error:', error);
  34.             return false;
  35.         }
  36.     }
  37.     /**
  38.      * Activates an experiment and returns the assigned variation.
  39.      *
  40.      * @param {string} experimentName - Name of the experiment.
  41.      * @param {string} userId - Unique user identifier.
  42.      * @param {Object.<string, string>} [attributes] - Optional user attributes.
  43.      *
  44.      * @returns {Promise<string|null>}
  45.      * Returns:
  46.      * - variation name → if assigned
  47.      * - null → if no variation or error
  48.      */
  49.     async activateExperiment(experimentName, userId, attributes) {
  50.         try {
  51.             this._validateString(experimentName, 'experimentName');
  52.             this._validateString(userId, 'userId');
  53.             this._validateAttributes(attributes);
  54.             const safeAttributes = attributes || {};
  55.             const variation = await PageSenseSDKModule.activateExperiment(
  56.                 experimentName,
  57.                 userId,
  58.                 safeAttributes,
  59.             );
  60.             return variation ?? null;
  61.         } catch (error) {
  62.             console.log('[PageSenseSDK] activateExperiment error:', error);
  63.             return null;
  64.         }
  65.     }
  66.     /**
  67.      * Retrieves the variation name without activating the experiment.
  68.      *
  69.      * @param {string} experimentName - Name of the experiment.
  70.      * @param {string} userId - Unique user identifier.
  71.      * @param {Object.<string, string>} [attributes] - Optional user attributes.
  72.      *
  73.      * @returns {Promise<string|null>}
  74.      * Returns:
  75.      * - variation name → if available
  76.      * - null → if not available or error
  77.      */
  78.     async getVariationName(experimentName, userId, attributes) {
  79.         try {
  80.             this._validateString(experimentName, 'experimentName');
  81.             this._validateString(userId, 'userId');
  82.             this._validateAttributes(attributes);
  83.             const safeAttributes = attributes || {};
  84.             const variation = await PageSenseSDKModule.getVariationName(
  85.                 experimentName,
  86.                 userId,
  87.                 safeAttributes,
  88.             );
  89.             return variation ?? null;
  90.         } catch (error) {
  91.             console.log('[PageSenseSDK] getVariationName error:', error);
  92.             return null;
  93.         }
  94.     }
  95.     /**
  96.      * Tracks a goal event for an experiment.
  97.      *
  98.      * @param {string} experimentName - Name of the experiment.
  99.      * @param {string} userId - Unique user identifier.
  100.      * @param {string} goalName - Name of the goal.
  101.      * @param {Object.<string, string>} [attributes] - Optional goal attributes.
  102.      *
  103.      * @returns {void}
  104.      */
  105.     trackGoal(experimentName, userId, goalName, attributes) {
  106.         try {
  107.             this._validateString(experimentName, 'experimentName');
  108.             this._validateString(userId, 'userId');
  109.             this._validateString(goalName, 'goalName');
  110.             this._validateAttributes(attributes);
  111.             const safeAttributes = attributes || {};
  112.             PageSenseSDKModule.trackGoal(
  113.                 experimentName,
  114.                 userId,
  115.                 goalName,
  116.                 safeAttributes,
  117.             );
  118.         } catch (error) {
  119.             console.log('[PageSenseSDK] trackGoal error:', error);
  120.         }
  121.     }
  122.     /**
  123.      * Validates whether the given parameter is a non-empty string.
  124.      * @private
  125.      * @throws {Error} if param is not a non-empty string
  126.      */
  127.     _validateString(param, paramName) {
  128.         if (typeof param !== 'string' || param.trim() === '') {
  129.             throw new Error(
  130.                 `[PageSenseSDK] Invalid ${paramName}: must be a non-empty string`,
  131.             );
  132.         }
  133.     }
  134.     /**
  135.      * Validates the attributes object to ensure it is a valid key-value pair structure.
  136.      * @private
  137.      * @throws {Error} if attributes is invalid
  138.      */
  139.     _validateAttributes(attributes) {
  140.         if (attributes === undefined || attributes == null) return;
  141.         if (typeof attributes !== 'object' || Array.isArray(attributes)) {
  142.             throw new Error('[PageSenseSDK] attributes must be a key-value object');
  143.         }
  144.         for (const key in attributes) {
  145.             if (typeof key !== 'string' || key.trim() === '') {
  146.                 throw new Error(
  147.                     '[PageSenseSDK] Invalid attribute key: must be a non-empty string',
  148.                 );
  149.             }
  150.             const value = attributes[key];
  151.             if (typeof value !== 'string') {
  152.                 throw new Error(
  153.                     `[PageSenseSDK] Invalid value for attribute "${key}". Allowed type: string`,
  154.                 );
  155.             }
  156.         }
  157.     }
  158. }
  159. // Export a singleton instance
  160. export default new PageSenseSDKWrapper();

Initializing the SDK

PageSense SDK must be initialised a single time during the application's lifecycle, ideally when the app launches. For example, you can initialise the SDK in the main entry point of the React Native application, such as App.jsx or App.js, before rendering any components or executing experiment-related logic. This approach guarantees that the SDK is fully set up and available whenever it is needed within the app.

  1. /**
  2.  * Root application component is responsible for initializing the PageSense SDK when the React Native
  3.  * application starts. The application UI is rendered only after the SDK initialization process is completed
  4.  * to ensure experiments can run immediately when screens are loaded.
  5.  *
  6.  * @returns {JSX.Element}
  7.  */
  8. export default function App() {
  9.     /**
  10.      * Tracks whether the PageSense SDK initialization is complete.
  11.      * @type {[boolean, Function]}
  12.      */
  13.     const [sdkReady, setSdkReady] = useState(false);
  14.     /**
  15.      * Runs once when the component mounts.
  16.      * Initializes the PageSense SDK via the wrapper.
  17.      */
  18.     useEffect(() => {
  19.         /**
  20.          * Initializes the PageSense SDK client.
  21.          * @returns {Promise<void>}
  22.          */
  23.         async function initializeSDK() {
  24.             try {
  25.                 // Call the SDK wrapper to initialize the native PageSense client
  26.                 const result = await PageSenseSDKWrapper.initialiseSDK(
  27.                     'PAGESENSE_ACCOUNT_ID',    // PageSense Account ID
  28.                     'PAGESENSE_SDK_KEY',        // SDK Key
  29.                     'PAGESENSE_PROJECT_NAME',   // Project Name
  30.                 );
  31.                 console.log('PageSense SDK initialized successfully:', result);
  32.                 setSdkReady(true);
  33.             } catch (error) {
  34.                 console.log('PageSense SDK initialization error:', error);
  35.                 // Still allow app to proceed even if SDK fails
  36.                 setSdkReady(true);
  37.             }
  38.         }
  39.         initializeSDK();
  40.     }, []);
  41.     if (!sdkReady) {
  42.         return (
  43.             <View style={styles.loadingContainer}>
  44.                 <ActivityIndicator size="large" />
  45.                 <Text style={styles.loadingText}>Initializing App...</Text>
  46.             </View>
  47.         );
  48.     }
  49.     return (
  50.         ....Application UI Implementation
  51.     );
  52. }

Activating an Experiment

The experiment should be executed when the screen is loaded to ensure that users are allocated to the correct variation and any relevant changes in the user interface or functionality are applied immediately. This ensures that the experiment is triggered as soon as the screen becomes active, providing consistent behaviour and accurate variation assignment. For example, in a React Native component, you can call the experiment inside a lifecycle method such as useEffect in App.jsx or App.js or any relevant screen component, so it runs once when the screen mounts:

  1. /**
  2.  * Executes the experiment for the current screen and applies the appropriate UI
  3.  * variation based on the variation assigned by the PageSense SDK.
  4.  */
  5. try {
  6.     // Activate the experiment for the current user.
  7.     const variation = await PageSenseSDKWrapper.activateExperiment(
  8.         'EXPERIMENT_NAME',  // Experiment name
  9.         'USER_ID',          // Unique user identifier
  10.         USER_ATTRIBUTES     // Optional user attributes passed to the PageSense SDK - (Key/Value Pair)
  11.     );
  12.     console.log('Experiment Variation:', variation);
  13.     /**
  14.      * Apply UI variations based on the variation name.
  15.      */
  16.     switch (variation) {
  17.         // Original control variation
  18.         case 'Original':
  19.             setButtonColor('#4F46E5'); // Default purple color
  20.             break;
  21.         // Variation 1
  22.         case 'Variation 1':
  23.             setButtonColor('#EF4444'); // Red button
  24.             break;
  25.         // Variation 2
  26.         case 'Variation 2':
  27.             setButtonColor('#16A34A'); // Green button
  28.             break;
  29.         // Variation 3
  30.         case 'Variation 3':
  31.             setButtonColor('#F59E0B'); // Orange button
  32.             break;
  33.         /**
  34.          * Fallback variation applied when no variation is returned by the SDK, the experiment is
  35.          * not active, or the user does not fall into any experiment group.
  36.          */
  37.         default:
  38.             setButtonColor('#6B7280'); // Neutral grey fallback color
  39.     }
  40. } catch (e) {
  41.     console.log('Experiment error', e);
  42.     setButtonColor('#6B7280');
  43. }

Tracking Goals

Goal tracking should be performed immediately after a user completes a specific action or event within the application. This ensures that conversions, interactions, or other key performance indicators are recorded in real time, providing accurate and timely data for analysis of experiment effectiveness. For example, after a user taps a button, submits a form, or completes a purchase, the corresponding goal should be sent to the PageSense SDK for tracking.

  1. /**
  2.  * Tracks a goal event for the specified experiment.
  3.  */
  4. PageSenseSDKWrapper.trackGoal(
  5.     'EXPERIMENT_NAME',  // Experiment associated with the goal event
  6.     'USER_ID',          // Unique user identifier
  7.     'GOAL_NAME',        // Goal name defined in PageSense
  8.     USER_ATTIBUTES);    // Optional user attributes passed to the PageSense SDK - (Key/Value Pair)

Best Practices

  • SDK initialization should occur only once for a project per app launch.
  • SDK initialization should happen before experiments are activated.
  • Applications should not block UI rendering if SDK initialization fails.
  • Use a fallback UI if the SDK initialization fails.
  • PageSenseClient instance should exist for the entire lifetime of the application session.
  • Create a unique user ID for each user for the mobile devices and reuse it globally.
  • Cache experiment results to avoid repeated activate experiment API calls.
  • Handle Null Variations. Always fallback to a safe default UI.
  • Native modules should not store UI state and should only store SDK-related objects.
  • Goals should be triggered after the specific user action or events completes successfully.
  • Use structured logging to assist with debugging during development.

Summary

After following this guide, your React Native application will be able to:

  • Initialise the PageSense SDK
  • Activate experiments
  • Retrieve variations
  • Track conversion goals
  • Dynamically modify UI based on experiments

This integration enables FullStack A/B experimentation capabilities inside React Native applications using the PageSense iOS SDK.


We’ve designed this documentation to guide you every step of the way. If you need further assistance or have any questions, don’t hesitate to contact us at support@zohopagesense.com - we’re always here to help!