Overview
This document covers the JavaScript wrapper (PageSenseSDKWrapper.js) which is shared across both the Android and iOS React Native integrations. The wrapper provides a unified JavaScript interface for interacting with the PageSense SDK through the React Native Native Bridge, abstracting away platform-specific native module differences.
Creating the JavaScript Wrapper
Create the wrapper file at the following path from the project root:
- src/sdk/PageSenseSDKWrapper.js
- javascript
- import { NativeModules } from 'react-native';
- const { PageSenseSDKModule } = NativeModules;
- export const GoalProperty = Object.freeze({
- REVENUE: 'revenue',
- });
- const VALID_GOAL_PROPERTIES = new Set(Object.values(GoalProperty));
- class PageSenseSDKWrapper {
- constructor() {}
- async initialiseSDK(accountId, sdkKey, projectName) {
- try {
- this._validateString(accountId, 'accountId');
- this._validateString(sdkKey, 'sdkKey');
- this._validateString(projectName, 'projectName');
- const result = await PageSenseSDKModule.initialiseSDK(accountId, sdkKey, projectName);
- return result === true;
- } catch (error) {
- console.log('[PageSenseSDK] initialiseSDK error:', error);
- return false;
- }
- }
- async activateExperimentByContext(experimentName, userContext) {
- try {
- this._validateString(experimentName, 'experimentName');
- this._validateUserContext(userContext);
- const safeUserContext = {
- userId: userContext.userId,
- userAttributes: userContext.userAttributes || {},
- };
- const variation = await PageSenseSDKModule.activateExperimentByContext(
- experimentName,
- safeUserContext,
- );
- return variation ?? null;
- } catch (error) {
- console.log('[PageSenseSDK] activateExperimentByContext error:', error);
- return null;
- }
- }
- async getVariationNameByContext(experimentName, userContext) {
- try {
- this._validateString(experimentName, 'experimentName');
- this._validateUserContext(userContext);
- const safeUserContext = {
- userId: userContext.userId,
- userAttributes: userContext.userAttributes || {},
- };
- const variation = await PageSenseSDKModule.getVariationNameByContext(
- experimentName,
- safeUserContext,
- );
- return variation ?? null;
- } catch (error) {
- console.log('[PageSenseSDK] getVariationNameByContext error:', error);
- return null;
- }
- }
- trackGoalByContext(goalName, userContext, goalProperties) {
- try {
- this._validateString(goalName, 'goalName');
- this._validateUserContext(userContext);
- const safeUserContext = {
- userId: userContext.userId,
- userAttributes: userContext.userAttributes || {},
- };
- if (goalProperties === undefined) {
- PageSenseSDKModule.trackGoalByContext(goalName, safeUserContext);
- } else {
- this._validateGoalPropertiesNonEmpty(goalProperties);
- PageSenseSDKModule.trackGoalWithPropertiesByContext(
- goalName,
- safeUserContext,
- goalProperties,
- );
- }
- } catch (error) {
- console.log('[PageSenseSDK] trackGoalByContext error:', error);
- }
- }
- _validateString(param, paramName) {
- if (typeof param !== 'string' || param.trim() === '') {
- throw new Error(`[PageSenseSDK] Invalid ${paramName}: must be a non-empty string`);
- }
- }
- _validateAttributes(attributes) {
- if (attributes === undefined || attributes === null) return;
- if (typeof attributes !== 'object' || Array.isArray(attributes)) {
- throw new Error('[PageSenseSDK] attributes must be a key-value object');
- }
- for (const key in attributes) {
- if (typeof key !== 'string' || key.trim() === '') {
- throw new Error('[PageSenseSDK] Invalid attribute key: must be a non-empty string');
- }
- const value = attributes[key];
- if (typeof value !== 'string') {
- throw new Error(`[PageSenseSDK] Invalid value for attribute "${key}". Allowed type: string`);
- }
- }
- }
- _validateUserContext(userContext) {
- if (
- userContext === undefined ||
- userContext === null ||
- typeof userContext !== 'object' ||
- Array.isArray(userContext)
- ) {
- throw new Error('[PageSenseSDK] userContext must be a valid object');
- }
- this._validateString(userContext.userId, 'userContext.userId');
- if (userContext.userAttributes !== undefined && userContext.userAttributes !== null) {
- this._validateAttributes(userContext.userAttributes);
- }
- }
- _validateGoalPropertiesNonEmpty(goalProperties) {
- if (goalProperties === null) {
- throw new Error(
- '[PageSenseSDK] goalProperties cannot be null. Omit the argument for goals without properties.',
- );
- }
- if (typeof goalProperties !== 'object' || Array.isArray(goalProperties)) {
- throw new Error('[PageSenseSDK] goalProperties must be a key-value object');
- }
- const keys = Object.keys(goalProperties);
- if (keys.length === 0) {
- throw new Error(
- '[PageSenseSDK] goalProperties cannot be empty. Omit the argument for goals without properties.',
- );
- }
- for (const key of keys) {
- if (!VALID_GOAL_PROPERTIES.has(key)) {
- throw new Error(
- `[PageSenseSDK] Invalid goal property key "${key}". ` +
- `Must be one of: ${Array.from(VALID_GOAL_PROPERTIES).join(', ')}`,
- );
- }
- const value = goalProperties[key];
- if (typeof value !== 'string') {
- throw new Error(
- `[PageSenseSDK] Invalid value for goal property "${key}". Allowed type: string`,
- );
- }
- }
- }
- }
- export default new PageSenseSDKWrapper();
SDK Functions
initialiseSDK
Initialises the PageSense SDK and creates the PageSenseClient instance. Must be called once during application startup before any other SDK function is used.
Method Signature
javascript
async initialiseSDK(accountId, sdkKey, projectName)
Parameters
Parameter | Type | Required | Description |
accountId | string | Yes | PageSense account identifier. |
sdkKey | string | Yes | SDK key used for authentication. |
projectName | string | Yes | Name of the PageSense project. |
Return Type
Promise<boolean> — Returns true if the SDK initialised successfully, false if initialisation failed.
Example
- javascript
- useEffect(() => {
- async function initializeSDK() {
- try {
- const result = await PageSenseSDKWrapper.initialiseSDK(
- 'PAGESENSE_ACCOUNT_ID',
- 'PAGESENSE_SDK_KEY',
- 'PAGESENSE_PROJECT_NAME',
- );
- setSdkReady(true);
- } catch (error) {
- setSdkReady(true);
- }
- }
- initializeSDK();
- }, []);
Notes
activateExperimentByContext
Activates a FullStack experiment for the user using PageSenseUserContext and returns the variation assigned to the user. Sends an impression event to PageSense and persists the visitor assignment.
Method Signature
javascript
async activateExperimentByContext(experimentName, userContext)
Parameters
Parameter | Type | Required | Description |
experimentName | string | Yes | Name of the experiment configured in PageSense. |
userContext | object | Yes | User context object containing userId and optional userAttributes. |
userContext.userId | string | Yes | Unique identifier for the user. |
userContext.userAttributes | object | No | Key-value pairs of user attributes used for audience targeting. All keys and values must be strings. |
Return Type
Promise<string|null> — Returns the variation name assigned to the user, or null if no variation is assigned or an error occurs.
Example
- javascript
- const userContext = {
- userId: 'USER_ID',
- userAttributes: {
- DeviceType: 'Phone',
- OS: 'Android',
- OSVersion: '14',
- DeviceModel: 'Pixel 8 Pro',
- },
- };
- const variation = await PageSenseSDKWrapper.activateExperimentByContext(
- 'EXPERIMENT_NAME',
- userContext,
- );
- switch (variation) {
- case 'Original': setButtonColor('#4F46E5'); break;
- case 'Variation 1': setButtonColor('#EF4444'); break;
- case 'Variation 2': setButtonColor('#16A34A'); break;
- default: setButtonColor('#6B7280');
- }
Notes
getVariationNameByContext
Retrieves the variation assigned to a user using PageSenseUserContext without activating the experiment. Does not send an impression event and does not persist the visitor assignment.
Use this function when you need to check the variation without recording the visit, for example in logging or conditional logic outside of the main experiment flow.
Method Signature
javascript
async getVariationNameByContext(experimentName, userContext)
Parameters
Parameter | Type | Required | Description |
experimentName | string | Yes | Name of the experiment configured in PageSense. |
userContext | object | Yes | User context object containing userId and optional userAttributes. |
userContext.userId | string | Yes | Unique identifier for the user. |
userContext.userAttributes | object | No | Key-value pairs of user attributes. All keys and values must be strings. |
Return Type
Promise<string|null> — Returns the variation name assigned to the user, or null if no variation is found or an error occurs.
Example
- javascript
- const variation = await PageSenseSDKWrapper.getVariationNameByContext(
- 'EXPERIMENT_NAME',
- userContext,
- );
- console.log('Variation Name:', variation);
Notes
trackGoalByContext
Tracks a goal event using PageSenseUserContext. Supports two calling styles depending on whether the goal has associated properties.
Without goal properties — use for FullStack Custom Event Goals:
javascript
trackGoalByContext(goalName, userContext)
With goal properties — use for Revenue Goals:
javascript
trackGoalByContext(goalName, userContext, goalProperties)
Parameters
Parameter | Type | Required | Description |
goalName | string | Yes | Name of the goal configured in PageSense. |
userContext | object | Yes | User context object containing userId and optional userAttributes. |
userContext.userId | string | Yes | Unique identifier for the user. |
userContext.userAttributes | object | No | Key-value pairs of user attributes. All keys and values must be strings. |
goalProperties | object | No | Goal properties object. Keys must be from GoalProperty constants. Must be non-empty if provided. |
Return Type
void
Example — Tracking a Goal Without Properties
- javascript
- function handleSubmitButton() {
- const userContext = {
- userId: 'USER_ID',
- userAttributes: { DeviceType: 'Phone', OS: 'Android' },
- };
- PageSenseSDKWrapper.trackGoalByContext('GOAL_NAME', userContext);
- }
Example — Tracking a Revenue Goal
- javascript
- import PageSenseSDKWrapper, { GoalProperty } from './src/sdk/PageSenseSDKWrapper';
- function handleCompletePurchase(purchaseAmountInDollars) {
- const userContext = {
- userId: 'USER_ID',
- userAttributes: { DeviceType: 'Phone', OS: 'Android' },
- };
- // Convert dollars to cents: $100.50 → "10050"
- const revenueInCents = String(Math.round(purchaseAmountInDollars * 100));
- const goalProperties = {
- [GoalProperty.REVENUE]: revenueInCents,
- };
- PageSenseSDKWrapper.trackGoalByContext('PURCHASE_GOAL_NAME', userContext, goalProperties);
- }
- handleCompletePurchase(100.50);
Notes
If goalProperties is provided, it must be a non-empty object. For goals without properties, omit the argument entirely — do not pass null or an empty object.
Revenue values must be passed as a string in cents. Multiply the dollar amount by 100 and round to the nearest integer.
Trigger goal tracking immediately after the specific user action or event completes successfully.
GoalProperty Constants
The GoalProperty constants are exported from PageSenseSDKWrapper.js and must be used as keys in the goalProperties object instead of hard-coded strings.
javascript
import { GoalProperty } from './src/sdk/PageSenseSDKWrapper';
JS Constant | String Value | Android Native Constant | iOS Native Enum Case | Purpose |
GoalProperty.REVENUE | "revenue" | GoalProperty.REVENUE | GoalProperty.revenue | Revenue amount in cents, used for Revenue Goals |
How GoalProperty Keys Travel Across the Bridge
Android — The native Kotlin module maps each string key to the matching GoalProperty enum constant using a lookup against GoalProperty.<CONSTANT>.value, producing a HashMap<GoalProperty, String> that is passed to the SDK.
iOS — The native Swift module maps each string key to the matching GoalProperty enum case using GoalProperty(rawValue:), producing a [GoalProperty: String] dictionary that is passed to the SDK.
JavaScript: { [GoalProperty.REVENUE]: "10050" }
↓
String key "revenue" travels across bridge
↓
Android: HashMap { GoalProperty.REVENUE → "10050" }
iOS: [GoalProperty.revenue: "10050"]
PageSenseUserContext Structure
- javascript
- const userContext = {
- userId: 'USER_ID', // Required — non-empty string
- userAttributes: { // Optional — all keys and values must be strings
- DeviceType: 'Phone',
- OS: 'Android',
- OSVersion: '14',
- DeviceModel: 'Pixel 8 Pro',
- },
- };
Field | Type | Required | Description |
userId | string | Yes | Unique identifier for the user. Must be a non-empty string. |
userAttributes | object | No | Key-value pairs used for audience targeting. All keys and values must be strings. If omitted, defaults to an empty object. |
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!