Skip to content
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
85e28d7
feat: introduce IterableAuthManager for authentication handling
lposen Oct 7, 2025
86d9b41
refactor: initialize defaults for logger, config, authManager, and in…
lposen Oct 7, 2025
6b84340
fix: enhance error handling and logging for JWT authentication failures
lposen Oct 7, 2025
4b40861
feat: implement IterableTracking and session management for embedded …
lposen Oct 7, 2025
26ddabd
feat: implement IterableApi class for enhanced tracking and user mana…
lposen Oct 7, 2025
f2aa18d
Merge branch 'jwt/authManager' into loren/embedded/all
lposen Oct 7, 2025
2f19aef
refactor: update Iterable classes to use static logger
lposen Oct 7, 2025
7aef30a
refactor: replace RNIterableAPI calls with IterableApi methods
lposen Oct 7, 2025
8e781df
Merge branch 'MOB-12231-refactor-classes-to-reduce-circular-dependenc…
lposen Oct 7, 2025
0adbc44
feat: introduce tracking manager in Iterable class and refactor track…
lposen Oct 7, 2025
e04f41f
feat: implement embedded messaging functionality with new classes and…
lposen Oct 7, 2025
2106df0
feat: add getEmbeddedMessages method to IterableApi for retrieving em…
lposen Oct 7, 2025
09f371e
feat: add support for enabling embedded messaging and update Iterable…
lposen Oct 7, 2025
1846e74
feat: implement IterableEmbeddedView and related types for embedded m…
lposen Oct 7, 2025
1408854
feat: enhance IterableApi with new tracking methods for embedded sess…
lposen Oct 7, 2025
452444a
feat: update Iterable class tracker with new embedded tracking methods
lposen Oct 7, 2025
a6a45ed
feat: implement getEmbeddedMessages method and enhance serialization …
lposen Oct 7, 2025
d67c1ed
feat: add getEmbeddedMessages method to RNIterableAPIModule for embed…
lposen Oct 7, 2025
a4fe2ac
fix: update enableEmbeddedMessaging configuration to use configReadab…
lposen Oct 7, 2025
bae7dbf
feat: update getEmbeddedMessages method to accept multiple placement IDs
lposen Oct 7, 2025
ec940a9
feat: synchronize embedded messages on initialization
lposen Oct 7, 2025
b24ca2e
feat: add syncEmbeddedMessages and getEmbeddedPlacementIds
lposen Oct 7, 2025
33a9498
feat: add embedded update listener support to RNIterableAPIModule and…
lposen Oct 8, 2025
f31dd72
feat: add start and end session methods for embedded messaging
lposen Oct 8, 2025
76a1ca3
feat: add start and pause impression methods for embedded messaging
lposen Oct 8, 2025
1e349df
feat: add handleEmbeddedClick and trackEmbeddedClick methods
lposen Oct 8, 2025
0e53674
fix: import missing IterableEmbeddedMessage
lposen Oct 8, 2025
3466661
refactor: giving up on the callbacks
lposen Oct 8, 2025
95b8085
refactor: remove embedded update listener methods from RNIterableAPIM…
lposen Oct 8, 2025
7421938
feat: add Embedded component and integrate into navigation
lposen Oct 8, 2025
595560c
feat: enhance Embedded component with new styles and message handling
lposen Oct 8, 2025
22fa618
feat: initial implementation of IterableEmbeddedBanner and IterableEm…
lposen Oct 8, 2025
371fad9
feat: added buttons to banner
lposen Oct 8, 2025
e6c1132
feat: enhance IterableEmbedded components with button click handling …
lposen Oct 8, 2025
14922e0
feat: fix error on embedded button click
lposen Oct 8, 2025
297ae51
feat: improve Embedded component with enhanced message fetching and s…
lposen Oct 9, 2025
13fc4a5
feat: implemented IterableEmbeddedNotification
lposen Oct 9, 2025
56d8dfc
feat: initial card view
lposen Oct 9, 2025
f9b22b7
feat: completed styles for IterableEmbeddedCard
lposen Oct 9, 2025
383e308
feat: refactor embedded click handling and introduce action prefix ut…
lposen Oct 9, 2025
1115268
feat: refactor IterableEmbedded components to utilize useEmbeddedView…
lposen Oct 9, 2025
4732925
feat: add visibility tracking and refactor image dimensions in Iterab…
lposen Oct 9, 2025
8149ed0
feat: request notification permission for Android 13+ in App component
lposen Oct 9, 2025
0ce8ecb
refactor: trying to get session start and end to work
lposen Oct 9, 2025
e0c27e0
refactor: reorganize IterableEmbedded types and interfaces for better…
lposen Oct 9, 2025
24e55d1
feat: consolidate other hooks into the usembedded hook
lposen Oct 9, 2025
0b147e8
feat: add TODOs for tracking session and impression events in Iterabl…
lposen Oct 9, 2025
4b71391
Merge branch 'MOB-12231-refactor-classes-to-reduce-circular-dependenc…
lposen Oct 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = {
],
rules: {
'react/react-in-jsx-scope': 'off',
'no-bitwise': 'off',
},
overrides: [
{
Expand Down
88 changes: 68 additions & 20 deletions src/core/classes/Iterable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,39 @@ import { Linking, NativeEventEmitter, Platform } from 'react-native';
import { buildInfo } from '../../itblBuildInfo';

import { RNIterableAPI } from '../../api';
// TODO: Organize these so that there are no circular dependencies
// See https://github.com/expo/expo/issues/35100

import { IterableInAppManager } from '../../inApp/classes/IterableInAppManager';
import { IterableInAppMessage } from '../../inApp/classes/IterableInAppMessage';
import { IterableInAppCloseSource } from '../../inApp/enums/IterableInAppCloseSource';
import { IterableInAppDeleteSource } from '../../inApp/enums/IterableInAppDeleteSource';
import { IterableInAppLocation } from '../../inApp/enums/IterableInAppLocation';
import {
defaultAuthManager,
defaultConfig,
defaultInAppManager,
defaultLogger,
} from '../constants/defaults';
import { IterableAuthResponseResult } from '../enums/IterableAuthResponseResult';
import { IterableEventName } from '../enums/IterableEventName';

// Add this type-only import to avoid circular dependency
import { IterableInAppManager } from '../../inApp/classes/IterableInAppManager';

import type { IterableAuthFailure } from '../types/IterableAuthFailure';
import {
trackEmbeddedSession,
trackEvent,
trackInAppClick,
trackInAppClose,
trackInAppOpen,
trackPurchase,
trackPushOpenWithCampaignId,
} from '../utils';
import { IterableAction } from './IterableAction';
import { IterableActionContext } from './IterableActionContext';
import { IterableApi } from './IterableApi';
import { IterableAttributionInfo } from './IterableAttributionInfo';
import { IterableAuthManager } from './IterableAuthManager';
import { IterableAuthResponse } from './IterableAuthResponse';
import type { IterableCommerceItem } from './IterableCommerceItem';
import { IterableConfig } from './IterableConfig';
import { IterableLogger } from './IterableLogger';
import type { IterableAuthFailure } from '../types/IterableAuthFailure';
import {
defaultAuthManager,
defaultConfig,
defaultInAppManager,
defaultLogger,
} from '../constants/defaults';
import { IterableApi } from './IterableApi';
import { IterableAuthManager } from './IterableAuthManager';

const RNEventEmitter = new NativeEventEmitter(RNIterableAPI);

Expand Down Expand Up @@ -96,6 +101,26 @@ export class Iterable {
*/
static authManager: IterableAuthManager = defaultAuthManager;

/**
* Tracking manager for the current user.
*
* This property provides access to tracking functionality including
* tracking purchases, in-app messages, and more.
*
* @example
* ```typescript
* Iterable.tracker.trackPurchase(100, [new IterableCommerceItem('item1', 'Item 1', 10.0, 1)], { key: 'value' });
* ```
*/
static tracker = {
trackPushOpenWithCampaignId,
trackPurchase,
trackInAppOpen,
trackInAppClick,
trackInAppClose,
trackEvent,
trackEmbeddedSession,
};
/**
* Initializes the Iterable React Native SDK in your app's Javascript or Typescript code.
*
Expand Down Expand Up @@ -391,6 +416,9 @@ export class Iterable {
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackPushOpenWithCampaignId` instead.
*
* Create a `pushOpen` event on the current user's Iterable profile, populating
* it with data provided to the method call.
*
Expand Down Expand Up @@ -480,6 +508,9 @@ export class Iterable {
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackPurchase` instead.
*
* Create a purchase event on the current user's Iterable profile.
*
* Represent each item in the purchase event with an {@link IterableCommerceItem} object.
Expand Down Expand Up @@ -508,10 +539,13 @@ export class Iterable {
items: IterableCommerceItem[],
dataFields?: unknown
) {
return IterableApi.trackPurchase(total, items, dataFields);
return Iterable.tracker.trackPurchase(total, items, dataFields);
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackInAppOpen` instead.
*
* Create an `inAppOpen` event for the specified message on the current user's profile
* for manual tracking purposes. Iterable's SDK automatically tracks in-app message opens when you use the
* SDK's default rendering.
Expand All @@ -534,10 +568,13 @@ export class Iterable {
message: IterableInAppMessage,
location: IterableInAppLocation
) {
return IterableApi.trackInAppOpen(message, location);
return Iterable.tracker.trackInAppOpen(message, location);
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackInAppClick` instead.
*
* Create an `inAppClick` event for the specified message on the current user's profile
* for manual tracking purposes. Iterable's SDK automatically tracks in-app message clicks when you use the
* SDK's default rendering. Click events refer to click events within the in-app message to distinguish
Expand All @@ -563,10 +600,13 @@ export class Iterable {
location: IterableInAppLocation,
clickedUrl: string
) {
return IterableApi.trackInAppClick(message, location, clickedUrl);
return Iterable.tracker.trackInAppClick(message, location, clickedUrl);
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackInAppClose` instead.
*
* Create an `inAppClose` event for the specified message on the current
* user's profile for manual tracking purposes. Iterable's SDK automatically
* tracks in-app message close events when you use the SDK's default
Expand Down Expand Up @@ -594,7 +634,12 @@ export class Iterable {
source: IterableInAppCloseSource,
clickedUrl?: string
) {
return IterableApi.trackInAppClose(message, location, source, clickedUrl);
return Iterable.tracker.trackInAppClose(
message,
location,
source,
clickedUrl
);
}

/**
Expand Down Expand Up @@ -642,6 +687,9 @@ export class Iterable {
}

/**
* @deprecated -- This method is deprecated and may be removed in a future
* release. Use `Iterable.tracker.trackEvent` instead.
*
* Create a custom event to the current user's Iterable profile.
*
* Pass in the name of the event stored in eventName key and the data associated with the event.
Expand All @@ -662,7 +710,7 @@ export class Iterable {
* ```
*/
static trackEvent(name: string, dataFields?: unknown) {
return IterableApi.trackEvent(name, dataFields);
return Iterable.tracker.trackEvent(name, dataFields);
}

/**
Expand Down
15 changes: 13 additions & 2 deletions src/core/classes/IterableApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { IterableInAppDeleteSource } from '../../inApp/enums/IterableInAppD
import type { IterableHtmlInAppContent } from '../../inApp/classes/IterableHtmlInAppContent';
import type { IterableInAppShowResponse } from '../../inApp/enums/IterableInAppShowResponse';
import type { IterableInboxImpressionRowInfo } from '../../inbox/types/IterableInboxImpressionRowInfo';
import type { IterableEmbeddedSession } from '../../embedded/classes/IterableEmbeddedSession';

export class IterableApi {
static logger: IterableLogger = defaultLogger;
Expand Down Expand Up @@ -105,8 +106,8 @@ export class IterableApi {
/**
* Associate the current user with the passed in `userId` parameter.
*
* WARNING: specify a user by calling `Iterable.setEmail` or
* `Iterable.setUserId`, but **NOT** both.
* WARNING: specify a user by calling `IterableApi.setEmail` or
* `IterableApi.setUserId`, but **NOT** both.
*
* @param userId - User ID to associate with the current user
* @param authToken - Valid, pre-fetched JWT the SDK
Expand Down Expand Up @@ -298,6 +299,16 @@ export class IterableApi {
return RNIterableAPI.trackEvent(name, dataFields);
}

/**
* Track an embedded session.
*
* @param session - The session to track
*/
static trackEmbeddedSession(session: IterableEmbeddedSession) {
IterableApi.logger.log('trackEmbeddedSession: ', session);
return RNIterableAPI.trackEmbeddedSession(session);
}

// ---- End TRACKING ---- //

// ====================================================== //
Expand Down
30 changes: 30 additions & 0 deletions src/core/classes/IterableUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,34 @@ export class IterableUtil {
return false;
}
}

static generateUUID(): string {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const g: any = typeof global !== 'undefined' ? (global as any) : undefined;

if (g?.crypto?.getRandomValues) {
const bytes = new Uint8Array(16);
g.crypto.getRandomValues(bytes);

// RFC 4122 compliance
bytes[6] = (bytes[6] ?? 0 & 0x0f) | 0x40; // version 4
bytes[8] = (bytes[8] ?? 0 & 0x3f) | 0x80; // variant 10

const hex = Array.from(bytes, (b) =>
b.toString(16).padStart(2, '0')
).join('');
return `${hex.substring(0, 8)}-${hex.substring(8, 12)}-${hex.substring(12, 16)}-${hex.substring(16, 20)}-${hex.substring(20)}`;
}

// Fallback using Math.random (not cryptographically strong)
const hexDigits = '0123456789abcdef';
const s: string[] = Array(36);
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.charAt(Math.floor(Math.random() * 16));
}
s[14] = '4';
s[19] = hexDigits.charAt((parseInt(s[19] ?? '0', 16) & 0x3) | 0x8);
s[8] = s[13] = s[18] = s[23] = '-';
return s.join('');
}
}
1 change: 1 addition & 0 deletions src/core/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './trackingUtils';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error loading TSDoc config file:
Error encountered for /home/runner/work/react-native-sdk/tsdoc.json:
Unable to resolve "extends" reference to "typedoc/tsdoc.json": Cannot find module 'typedoc/tsdoc.json' from '/home/runner/work/react-native-sdk'
[eslint:tsdoc/syntax]

Loading
Loading