Skip to content

Commit 00cb553

Browse files
authored
Merge branch 'main' into update-intercom-sdks-20251004-090258
2 parents de1e22e + 56b8b16 commit 00cb553

File tree

14 files changed

+454
-34
lines changed

14 files changed

+454
-34
lines changed

README.md

Lines changed: 126 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
## Installation
4646

4747
```sh
48-
$ npm install @intercom/intercom-react-native
48+
npm install @intercom/intercom-react-native
4949
```
5050

5151
or
@@ -61,7 +61,7 @@ If you're using React Native v0.60 or above, the library will be linked automati
6161
#### Android: Automatic linking with React Native v0.59 and below
6262

6363
```
64-
$ react-native link @intercom/intercom-react-native
64+
react-native link @intercom/intercom-react-native
6565
```
6666

6767
#### Android: Manual linking with React Native v0.59 and below
@@ -81,6 +81,16 @@ implementation project(':intercom-react-native')
8181

8282
#### Android: Setup
8383

84+
You have two options for initializing Intercom:
85+
86+
**Option 1: Native Initialization (Recommended)**
87+
Initialize at app startup in your native code for the best user experience.
88+
89+
**Option 2: JavaScript Initialization**
90+
Initialize manually from JavaScript for more control over timing. If you choose this option, skip the native initialization code below and see the [`initialize` method documentation](#intercomintializeapikey-appid) for implementation details.
91+
92+
**For Native Initialization:**
93+
8494
- Add below lines to `android/app/src/main/java/com/YOUR_APP/app/MainApplication.java` inside `onCreate` method, replacing `apiKey` and `appId` which can be found in your [workspace settings](https://app.intercom.com/a/apps/_/settings/android).
8595

8696
```java
@@ -340,6 +350,16 @@ See [How to manually link IOS Intercom SDK](docs/IOS-MANUAL-LINKING.md)
340350

341351
#### iOS: Setup
342352

353+
You have two options for initializing Intercom:
354+
355+
**Option 1: Native Initialization (Recommended)**
356+
Initialize at app startup in your native code for the best user experience.
357+
358+
**Option 2: JavaScript Initialization**
359+
Initialize manually from JavaScript for more control over timing. If you choose this option, skip the native initialization code below and see the [`initialize` method documentation](#intercomintializeapikey-appid) for implementation details with platform-specific API key handling.
360+
361+
**For Native Initialization:**
362+
343363
- Open `ios/AppDelegate.m` then add below code:
344364

345365
- At the top of file add the following:
@@ -359,7 +379,7 @@ See [How to manually link IOS Intercom SDK](docs/IOS-MANUAL-LINKING.md)
359379
// ...
360380
self.window.rootViewController = rootViewController;
361381

362-
[IntercomModule initialize:@"apiKey" withAppId:@"appId"]; // <-- Add this (Remember to replace strings with your api keys)
382+
[IntercomModule initialize:@"apiKey" withAppId:@"appId"]; // <-- Add this
363383

364384
return YES;
365385
}
@@ -383,8 +403,8 @@ func application(_ application: UIApplication, didFinishLaunchingWithOptions lau
383403
Intercom.setApiKey("<Your iOS API Key>", forAppId: "<Your App ID>")
384404
....
385405
}
386-
387-
```
406+
407+
```
388408

389409
#### iOS: Permissions
390410

@@ -518,6 +538,7 @@ The plugin provides props for extra customization. Every time you change the pro
518538
- `androidApiKey` (_string_): Android API Key from Intercom.
519539
- `iosApiKey` (_string_): iOS API Key from Intercom.
520540
- `intercomRegion` (_string_): Region for Intercom `US`, `EU`, `AU`. Optional. Defaults to `US`.
541+
- `useManualInit` (_boolean_): Set to `true` to manually initialize Intercom from JavaScript instead of at app startup. Optional. Defaults to `false`.
521542

522543
```json
523544
{
@@ -537,6 +558,41 @@ The plugin provides props for extra customization. Every time you change the pro
537558
}
538559
```
539560

561+
#### Manual Initialization with Expo
562+
563+
If you want to delay Intercom initialization and manually initialize it from JavaScript, you set the `useManualInit` option to `true`:
564+
565+
```json
566+
{
567+
"expo": {
568+
"plugins": [
569+
[
570+
"@intercom/intercom-react-native",
571+
{
572+
"useManualInit": true
573+
}
574+
]
575+
]
576+
}
577+
}
578+
```
579+
580+
Then initialize Intercom manually in your JavaScript code with the platform-specific API keys:
581+
582+
```javascript
583+
import Intercom from '@intercom/intercom-react-native';
584+
import { Platform } from 'react-native';
585+
586+
// You can find your API keys in your Intercom workspace settings
587+
// https://app.intercom.com/a/apps/<your-app-id>/settings/channels/messenger/install?tab=ios
588+
const apiKey = Platform.select({
589+
ios: 'ios_sdk-abc123',
590+
android: 'android_sdk-abc123',
591+
});
592+
593+
await Intercom.initialize(apiKey, 'abc123');
594+
```
595+
540596
#### Expo: Push notifications
541597

542598
Add the following configurations into your `app.json` or `app.config.js`:
@@ -697,6 +753,38 @@ Sets the user hash necessary for validation when Identity Verification is enable
697753

698754
---
699755

756+
### `Intercom.initialize(apiKey, appId)`
757+
758+
Initialize the Intercom SDK manually. This is useful when you want to delay initialization until after your app has started, or when using Expo with the `useManualInit` plugin option.
759+
760+
**Important:** This method configures the SDK but does NOT validate your credentials with Intercom's servers. Invalid API keys or App IDs will only be detected when you attempt to use Intercom features (e.g., login, show messenger). The method will return `true` if the SDK is successfully configured, regardless of credential validity.
761+
762+
### Options
763+
764+
| Name | Type | Required | Description |
765+
| ------ | ------ | -------- | --------------------------------------- |
766+
| apiKey | string | yes | Your Platform-specific Intercom API key |
767+
| appId | string | yes | Your Intercom App ID |
768+
769+
### Examples
770+
771+
```javascript
772+
import { Platform } from 'react-native';
773+
774+
const apiKey = Platform.select({
775+
ios: 'ios_sdk-abc123',
776+
android: 'android_sdk-xyz789',
777+
});
778+
779+
await Intercom.initialize(apiKey, 'your_app_id');
780+
```
781+
782+
### Returns
783+
784+
`Promise<boolean>`
785+
786+
---
787+
700788
### `Intercom.loginUnidentifiedUser()`
701789

702790
Login a unidentified user.
@@ -1206,6 +1294,39 @@ This should be called before any user login takes place.
12061294
12071295
---
12081296
1297+
### `Intercom.setAuthTokens(authTokens)`
1298+
1299+
Provide Intercom with your auth tokens which can be used for functionality such as Custom Actions with Data Connectors. You can provide multiple
1300+
tokens at once. To create tokens:
1301+
1. Go to Settings > Integrations > Authentication in your Intercom workspace
1302+
2. Create a new token with "User" type
1303+
3. Configure the token prefix and header as needed
1304+
1305+
Learn more: https://www.intercom.com/help/en/articles/6615543-setting-up-data-connectors-authentication
1306+
1307+
This should be called after any user login takes place.
1308+
1309+
**Note:** This is separate from `setUserJwt()` which is for Messenger Security. `setAuthTokens()` passes JWT tokens to
1310+
Data Connectors (e.g., Fin Actions), which use these in `Authorization: Bearer <token>` headers for API requests.
1311+
1312+
### Options
1313+
1314+
| Name | Type | Required | Description |
1315+
| ---------- | --------------------------- | -------- | ------------------------------------------------------------ |
1316+
| authTokens | `{ [key: string]: string }` | yes | An object with token names as keys and JWT strings as values |
1317+
1318+
### Example
1319+
1320+
```typescript
1321+
Intercom.setAuthTokens({ security_token: "jwt_here" });
1322+
```
1323+
1324+
### Returns
1325+
1326+
`Promise<boolean>`
1327+
1328+
---
1329+
12091330
## Author
12101331

12111332
👤 **Intercom (https://www.intercom.com/)**

android/src/main/java/com/intercom/reactnative/IntercomErrorCodes.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public class IntercomErrorCodes {
1010
public static final String SET_LOG_LEVEL = "107";
1111
public static final String GET_UNREAD_CONVERSATION = "108";
1212
public static final String SET_USER_JWT = "109";
13+
public static final String SET_AUTH_TOKENS = "110";
14+
public static final String INITIALIZE_ERROR = "111";
1315
public static final String DISPLAY_MESSENGER = "201";
1416
public static final String DISPLAY_MESSENGER_COMPOSER = "202";
1517
public static final String DISPLAY_CONTENT = "203";

android/src/main/java/com/intercom/reactnative/IntercomHelpers.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.List;
1616
import java.util.Map;
1717

18+
import io.intercom.android.sdk.AuthToken;
1819
import io.intercom.android.sdk.Company;
1920
import io.intercom.android.sdk.Intercom;
2021
import io.intercom.android.sdk.UserAttributes;
@@ -255,4 +256,23 @@ public static WritableMap deconstructRegistration(Registration registration) {
255256
}
256257
return registrationMap;
257258
}
259+
260+
public static List<AuthToken> buildAuthTokensList(ReadableMap readableMap) {
261+
List<AuthToken> authTokens = new ArrayList<>();
262+
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
263+
264+
while (iterator.hasNextKey()) {
265+
String key = iterator.nextKey();
266+
ReadableType type = readableMap.getType(key);
267+
268+
if (type == ReadableType.String) {
269+
String value = readableMap.getString(key);
270+
if (key != null && value != null && !key.isEmpty() && !value.isEmpty()) {
271+
authTokens.add(new AuthToken(key, value));
272+
}
273+
}
274+
}
275+
276+
return authTokens;
277+
}
258278
}

android/src/newarch/IntercomModule.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,46 @@ public void setUserJwt(String jwt, Promise promise) {
603603
}
604604
}
605605

606+
@ReactMethod
607+
public void setAuthTokens(ReadableMap authTokens, Promise promise) {
608+
try {
609+
List<io.intercom.android.sdk.AuthToken> authTokensList = IntercomHelpers.buildAuthTokensList(authTokens);
610+
Intercom.client().setAuthTokens(authTokensList, new IntercomStatusCallback() {
611+
@Override
612+
public void onSuccess() {
613+
promise.resolve(true);
614+
}
615+
616+
@Override
617+
public void onFailure(@NonNull IntercomError intercomError) {
618+
Log.e("ERROR", intercomError.getErrorMessage());
619+
promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage());
620+
}
621+
});
622+
} catch (Exception err) {
623+
Log.e(NAME, "setAuthTokens error:");
624+
Log.e(NAME, err.toString());
625+
promise.reject(IntercomErrorCodes.SET_AUTH_TOKENS, err.toString());
626+
}
627+
}
628+
629+
@ReactMethod
630+
public void initialize(String apiKey, String appId, Promise promise) {
631+
try {
632+
Activity activity = getCurrentActivity();
633+
if (activity != null && activity.getApplication() != null) {
634+
IntercomModule.initialize(activity.getApplication(), apiKey, appId);
635+
promise.resolve(true);
636+
} else {
637+
promise.reject(IntercomErrorCodes.INITIALIZE_ERROR, "Activity is null");
638+
}
639+
} catch (Exception err) {
640+
Log.e(NAME, "initialize error:");
641+
Log.e(NAME, err.toString());
642+
promise.reject(IntercomErrorCodes.INITIALIZE_ERROR, err.toString());
643+
}
644+
}
645+
606646
@ReactMethod
607647
public void setNeedsStatusBarAppearanceUpdate(Promise promise) {
608648
// iOS-only method, no-op on Android

android/src/oldarch/IntercomModule.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,46 @@ public void setUserJwt(String jwt, Promise promise) {
580580
}
581581
}
582582

583+
@ReactMethod
584+
public void setAuthTokens(ReadableMap authTokens, Promise promise) {
585+
try {
586+
List<io.intercom.android.sdk.AuthToken> authTokensList = IntercomHelpers.buildAuthTokensList(authTokens);
587+
Intercom.client().setAuthTokens(authTokensList, new IntercomStatusCallback() {
588+
@Override
589+
public void onSuccess() {
590+
promise.resolve(true);
591+
}
592+
593+
@Override
594+
public void onFailure(@NonNull IntercomError intercomError) {
595+
Log.e("ERROR", intercomError.getErrorMessage());
596+
promise.reject(String.valueOf(intercomError.getErrorCode()), intercomError.getErrorMessage());
597+
}
598+
});
599+
} catch (Exception err) {
600+
Log.e(NAME, "setAuthTokens error:");
601+
Log.e(NAME, err.toString());
602+
promise.reject(IntercomErrorCodes.SET_AUTH_TOKENS, err.toString());
603+
}
604+
}
605+
606+
@ReactMethod
607+
public void initialize(String apiKey, String appId, Promise promise) {
608+
try {
609+
Activity activity = getCurrentActivity();
610+
if (activity != null && activity.getApplication() != null) {
611+
IntercomModule.initialize(activity.getApplication(), apiKey, appId);
612+
promise.resolve(true);
613+
} else {
614+
promise.reject(IntercomErrorCodes.INITIALIZE_ERROR, "Activity is null");
615+
}
616+
} catch (Exception err) {
617+
Log.e(NAME, "initialize error:");
618+
Log.e(NAME, err.toString());
619+
promise.reject(IntercomErrorCodes.INITIALIZE_ERROR, err.toString());
620+
}
621+
}
622+
583623
public static synchronized void initialize(Application application, String apiKey, String appId) {
584624
String sdkVersion = BuildConfig.INTERCOM_VERSION_NAME;
585625
ReactNativeHeaderInterceptor.setReactNativeVersion(application.getApplicationContext(), sdkVersion);

examples/expo-example/app.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@
3939
[
4040
"@intercom/intercom-react-native",
4141
{
42-
"appId": "YOUR_APP_ID",
43-
"androidApiKey": "android_sdk-YOUR_ANDROID_API_KEY",
44-
"iosApiKey": "ios_sdk-YOUR_IOS_API_KEY"
42+
"useManualInit": true
4543
}
4644
],
4745
"expo-router",

0 commit comments

Comments
 (0)