@freshworks/react-native-freshdesk-sdk
Version:
React Native wrapper for Freshdesk Android and iOS SDKs
512 lines (363 loc) • 22.7 kB
Markdown
---
name: freshdesk-react-native-integration
description: Integrate, debug, verify, and answer questions about the Freshdesk React Native SDK (@freshworks/react-native-freshdesk-sdk) in a host React Native app for Android and iOS. Use for greenfield integration, integration Q&A (knowledge base), diagnostics-driven debugging, FreshdeskSDK.initialize/openSupport/openKnowledgeBase, JWT, push notifications, ContentConfiguration, or any customer question about wiring the SDK.
---
# Freshdesk React Native SDK Integration
This skill teaches an AI agent how to integrate, debug, verify, and **answer integration questions** for the Freshdesk React Native SDK in a host app.
**Three modes:**
- **Mode A — Greenfield integration**: SDK not yet in the app. Follow the phased workflow below.
- **Mode B — Diagnostics-driven debugging**: SDK already integrated. Use `FreshdeskSDK.runDiagnostics()` as source of truth and apply each check's `fixHint`.
- **Mode C — Integration Q&A (knowledge base)**: Customer asks a question about integration (setup, APIs, push, JWT, errors, platform differences). **Read [integration-knowledge-base.md](integration-knowledge-base.md) first**, answer directly from it, and cite [platform-apis.md](platform-apis.md) when platforms differ. Escalate to Mode A (full wiring) or Mode B (diagnostics) only when the question requires it.
> **Consumer apps only.** Do not edit `sdk_src` or files inside `node_modules/@freshworks/react-native-freshdesk-sdk`. Only change the target app's files.
**References:**
- [integration-faq.md](integration-faq.md) — prerequisites, app changes, post-integration checklist
- [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A for any integration question
- [platform-apis.md](platform-apis.md) — Android vs iOS API and native differences
- [examples.md](examples.md) — worked scenarios
## When to use
Apply when integrating, auditing, debugging, or **answering questions about** `@freshworks/react-native-freshdesk-sdk` in a React Native app.
Examples of Mode C questions:
- "How do I open the knowledge base?"
- "Do I need Firebase for chat?"
- "What's the difference between Android and iOS push setup?"
- "Why does openSupport show a spinner?"
- "Where do I put my Freshdesk token?"
Do NOT use for Freshdesk web/dashboard config unrelated to the mobile SDK, generic RN questions with no Freshdesk involvement, or SDK wrapper maintenance.
## Prerequisites
- React Native **0.75.0+**. Backward-compatible with both the New Architecture
(TurboModule) and the classic bridge — no consumer-facing choice to make;
`runDiagnostics()` reports which one is active (`architecture: 'old'|'new'`).
On **React Native 0.79+** (Kotlin 2.1.x toolchain) use wrapper **2.0.1+** —
earlier builds fail to compile `FreshdeskModule.kt` against RN 0.79's nullable
`ReadableMap.toHashMap()` (see [troubleshooting.md](troubleshooting.md), Issue 5).
- iOS deployment target **15.0+**. The native SDK ships as a vendored,
statically-linked `FreshdeskSDK.xcframework` — **no `use_frameworks!`,
Swift Package Manager, or `FRESHDESK_IOS_USE_VENDORED` env var required**
(2.0.0+; older 1.4.x used an SPM path that needed those — see
[troubleshooting.md](troubleshooting.md) if the target app is still on 1.4.x).
- Android `minSdkVersion 26+`. The wrapper reads `compileSdkVersion`/`targetSdkVersion` from your
app's own root `build.gradle` `ext` block if set; otherwise it falls back to **35**, which
requires AGP **8.6+**. Apps that set `compileSdkVersion 36` (Android 16) in their own `ext`
block should use AGP **8.9.1+** (9.x recommended).
- CocoaPods **1.12+** (iOS).
- Freshdesk portal access: **Admin Settings → Mobile Chat SDK**.
---
## Step 0 — Detect mode
1. Search `package.json` for `@freshworks/react-native-freshdesk-sdk`.
2. Search source for `FreshdeskSDK.initialize(` or imports from the package.
3. Classify the user's request:
| Request type | Mode |
|--------------|------|
| Question about integration (how-to, what-if, error meaning, API usage) | **Mode C** → [integration-knowledge-base.md](integration-knowledge-base.md) |
| "Integrate Freshdesk" / greenfield / SDK not in app | **Mode A** → Phase 1 |
| Bug report / something broken / verify existing integration | **Mode B** → Step B1 |
| Question + broken symptom | **Mode C** answer first, then **Mode B** if needed |
If unsure between A and B, ask: "Is the Freshdesk React Native SDK already in your app, or is this a new integration?"
---
## Mode C — Integration Q&A (knowledge base)
**When the customer asks any integration question**, act as a knowledgeable support agent:
1. **Search** [integration-knowledge-base.md](integration-knowledge-base.md) for the topic (credentials, init, push, JWT, APIs, errors, platform differences).
2. **Answer directly** — concise, accurate, with code snippets when they help. Do not start a full greenfield workflow unless they ask to integrate.
3. **Platform-specific?** Cross-check [platform-apis.md](platform-apis.md) and state Android vs iOS differences explicitly.
4. **Symptom / bug?** After answering, suggest `runDiagnostics()` and offer Mode B triage if they share the report.
5. **Full integration requested?** Hand off to Mode A.
### Mode C response format
1. Direct answer to the question (2–5 sentences or a short code block).
2. Related gotchas (platform differences, common mistakes) — only if relevant.
3. Optional: "If you want me to wire this into your app, say so and I'll integrate it."
Never invent credentials. Never paste secrets in chat.
---
## Mode A — Greenfield integration (phased workflow)
### Phase 1 — Interactive setup (host & language)
**Ask the user directly** (do not invent values):
1. **Host** — Freshdesk instance URL from Admin → Mobile Chat SDK. Accepts **either** `yourcompany.freshdesk.com` **or** `https://yourcompany.freshdesk.com` — the SDK auto-prefixes `https://` when omitted.
2. **Language / locale** — BCP-47 code for widget UI (default `en` if unspecified).
Record answers for use in `.env`, `initialize({ locale })`, and native credential files.
Also confirm in one batch:
| Question | Why |
|----------|-----|
| Target platforms (Android, iOS, both)? | Scopes native work |
| Android `applicationId` / iOS bundle id? | Push portal setup |
| Is JWT enforced on the widget? | JWT wiring vs `setUserProperties` |
| Push notifications needed? | Native init mandatory |
### Phase 2 — Secrets via file paths (never paste in chat)
**Do not ask the user to paste token, SDK ID, or JWT in the chat.**
Discover paths in the host app, then tell the user exactly which files to edit:
#### 2a — Create or update `.env` (app root, gitignored)
```bash
FRESHDESK_HOST=<value from Phase 1>
FRESHDESK_LOCALE=<value from Phase 1>
FRESHDESK_TOKEN= # ← user fills from portal App Keys
FRESHDESK_SDK_ID= # ← user fills from portal
FRESHDESK_JWT= # ← user fills if JWT enforced; leave empty otherwise
```
If the app uses `react-native-dotenv` / `@env`, ensure `babel.config.js` includes the plugin and `src/types/env.d.ts` declares the keys.
#### 2b — Android native credentials (required when push is enabled)
Point to `android/app/build.gradle` → `defaultConfig`:
```gradle
buildConfigField "String", "FRESHDESK_TOKEN", "\"...\""
buildConfigField "String", "FRESHDESK_HOST", "\"...\""
buildConfigField "String", "FRESHDESK_SDK_ID", "\"...\""
buildConfigField "String", "FRESHDESK_JWT", "\"...\""
buildConfigField "String", "FRESHDESK_LOCALE", "\"en\""
```
Prefer reading from `.env` via a helper (see SDK sample app `freshdeskEnvValue()`).
#### 2c — iOS native credentials (required when push is enabled)
Point to `ios/<AppName>/Info.plist`:
```xml
<key>FreshdeskHost</key><string>...</string>
<key>FreshdeskLocale</key><string>en</string>
<key>FreshdeskToken</key><string>...</string>
<key>FreshdeskSdkId</key><string>...</string>
<key>FreshdeskJwt</key><string>...</string> <!-- if JWT enforced -->
```
**Stop and wait** until the user confirms credentials are filled. Do not proceed with init testing while placeholders remain.
### Phase 3 — Install package
```bash
npm install @freshworks/react-native-freshdesk-sdk
```
Autolinking handles native linking (RN 0.60+).
### Phase 4 — Integration inventory (existing code vs agent creates)
For **each area below**, ask: **"Do you already have code for this in your app?"**
- **Yes** → show the exposed API(s), inspect their file(s), wire SDK calls into their existing code.
- **No** → agent implements the integration from scratch (minimal, idiomatic to their app structure).
Process areas in this order:
#### 4.1 SDK initialization
**API:**
```typescript
await FreshdeskSDK.initialize({
token, host, sdkId,
locale: FRESHDESK_LOCALE || 'en',
jwt: FRESHDESK_JWT, // JWT-enforced only
debugMode: __DEV__, // Android Logcat only
});
```
**If no existing code:** create a `FreshdeskProvider` (or init in root `App.tsx` / `useEffect`) that:
- Reads credentials from `@env` or config module.
- Calls `initialize()` once on mount.
- Sets `isInitialized` state; guards all SDK calls until true.
- On failure: log error, do not silently continue.
**If existing code:** merge init params (host, locale from Phase 1); ensure single init, awaited before other calls.
#### 4.2 Support entry points
**APIs:**
| Method | Purpose |
|--------|---------|
| `openSupport()` | Support home / chat |
| `openKnowledgeBase()` | FAQ / KB directly |
| `openTopic({ topicName, topicId? })` | Specific topic |
**If no existing code:** add a support button (settings, profile, or tab) calling `openSupport()` with try/catch and init guard.
**If existing code:** connect their button/navigation handler to the appropriate API.
#### 4.3 User identity
**JWT enforced** (from Phase 1):
| API | When |
|-----|------|
| `initialize({ jwt })` | At startup |
| `authenticateAndUpdate(jwt)` | After token refresh |
| `addUserStateListener(cb)` | Handle `authExpired`, `notAuthenticated` |
| `resetUser()` | On logout |
Do **not** call `setUserProperties` for identity when JWT is enforced.
**Non-JWT:**
| API | When |
|-----|------|
| `setUserProperties({ name, email, phone, ... })` | After login |
| `resetUser()` | On logout |
**If no existing code:** add listener in provider; hook login/logout flows if auth exists in app.
#### 4.4 Push notifications (native — per platform)
**No JS push API.** Ask if they have existing FCM/APNs wiring.
**If yes:** integrate Freshdesk into their existing `FirebaseMessagingService` (Android) and `AppDelegate` push handlers (iOS). See [platform-apis.md](platform-apis.md).
**If no:** create native wiring mirroring SDK sample app:
| Platform | Files to create/modify |
|----------|------------------------|
| Android | `FreshdeskMessagingService.kt` (headless init), `AndroidManifest.xml`, `google-services.json`, `build.gradle` |
| iOS | `AppDelegate.mm`/`.swift`, `FreshdeskPush.swift` (if needed), `Info.plist`, Xcode Push + Background Modes |
> **Critical (Android):** Do **not** call native `FreshdeskSDK.initialize()` in `MainApplication.onCreate()` — it conflicts with JS init and breaks `openSupport()`. Use JS init for in-app support; native init **only** inside `FirebaseMessagingService` for headless push.
Android headless init (inside `FreshdeskMessagingService`, via `FreshdeskInitializer` pattern — not `MainApplication`):
```kotlin
FreshdeskInitializer.ensureInitializedBlocking(applicationContext)
FreshdeskSDK.handleFCMNotification(data)
```
iOS native init (in `AppDelegate` early, before RN bridge):
```objc
[FreshdeskNativeModuleBridge initializeSDKWithToken:... host:... sdkId:... locale:... jwt:...];
```
Forward tokens and handle all three iOS notification delivery paths.
#### 4.5 Content configuration & localization
**API:**
```typescript
await FreshdeskSDK.setContentConfiguration({
headers: { chat: '...', faq: '...' },
placeholders: { replyField: '...', searchField: '...' },
actions: { tabChat: '...' },
privacyPolicySetting: { ... },
});
```
Pass `{}` to reset to widget defaults.
**If no existing code:** call after successful init with strings matching Phase 1 locale if custom copy is needed.
#### 4.6 Event listeners
| API | Platform | Purpose |
|-----|----------|---------|
| `addUnreadCountListener(cb)` | Both | Badge / tab count |
| `addUserStateListener(cb)` | Both | JWT auth state |
| `addUserCreatedListener(cb)` | **iOS only** | New anonymous user |
| `setLinkHandler(cb)` | Both | Custom in-widget URLs |
**If no existing code:** register in provider; `.remove()` on unmount; call `removeAllListeners()` in cleanup.
#### 4.7 Analytics (optional)
**API:** `trackEvent(name, properties?)`
Wire only if user requests or already has analytics hooks.
### Phase 5 — Platform native baseline
Apply even when push is disabled:
**Android (all apps):**
- `mavenCentral()` in repositories.
- `minSdkVersion 26`. Set `compileSdkVersion`/`targetSdkVersion` explicitly in the app's own `ext`
block — the wrapper falls back to **35** (AGP 8.6+) if unset, so apps targeting **36**
(Android 16) should set it explicitly and use AGP **8.9.1+**.
- JDK 17–21 for Gradle.
- Apply `android/freshdesk-consumer.gradle` from the npm package (Kotlin metadata fix — see [troubleshooting.md](troubleshooting.md)).
- Set `kotlinOptions { freeCompilerArgs += ["-Xskip-metadata-version-check"] }` on the app module.
- RN 0.79+ (Kotlin 2.1.x): keep the wrapper at **2.0.1+**. Older wrapper builds do not compile
against RN 0.79's nullable `ReadableMap.toHashMap()` ([troubleshooting.md](troubleshooting.md), Issue 5).
**iOS (all apps, 2.0.0+):**
Nothing Freshdesk-specific to add beyond the deployment target — the native SDK
is a vendored static xcframework, so it does not force `use_frameworks!` and
needs no `post_install` hook of its own:
```ruby
platform :ios, '15.0'
```
```bash
cd ios && pod install
```
Keep `use_frameworks!` only if some *other* dependency in the app needs it —
prefer `:linkage => :static` if so. If the target app's `package.json` still
pins `@freshworks/react-native-freshdesk-sdk@~1.4.x`, it needs the older SPM
path instead — see [troubleshooting.md](troubleshooting.md).
### Phase 6 — Verify initialization & debug failures
**Mandatory before declaring success:**
1. Build and run each targeted platform.
2. Confirm init completes (no `FRESHDESK_INVALID_CONFIG` / `FRESHDESK_INIT_ERROR` in logs).
3. Open support entry point once.
4. Run diagnostics:
```typescript
await FreshdeskSDK.enableDebugLogs(true);
const report = await FreshdeskSDK.runDiagnostics();
console.log(report.prettyPrinted);
```
5. Triage any non-`pass` check — apply `fixHint` verbatim (hand off to Mode B).
6. Confirm `runtime.sdkInitialized: pass`.
7. **Output the Integration Summary** and link [integration-faq.md](integration-faq.md) (see Output format).
**Android extra signal:** `debugMode: true` in `initialize()` + Logcat tag `Freshdesk`.
**iOS extra signal:** full native report with masked secrets — safe to share.
**iOS `initialize()` normally takes ≥2 seconds — this is expected, not a bug.**
The native SDK has no readiness signal of its own, so the wrapper holds
`initialize()`'s promise until a fixed settle delay has passed (see
[platform-apis.md](platform-apis.md)). Do not "fix" a 2+ second `initialize()`
call on iOS; do flag it as a real bug if `openSupport()`/`trackEvent()`/
`setUserProperties()` fail or no-op **after** `initialize()` has resolved —
that combination means either an SDK version without this fix (check
`CHANGELOG.md` for the "iOS `initialize()` settle delay" entry), or a
genuine credentials/network problem worth diagnostics.
Do not declare integration complete until diagnostics and the user's symptom both confirm success.
---
## Mode B — Diagnostics-driven debugging
### Step B1 — Run diagnostics first
```typescript
await FreshdeskSDK.enableDebugLogs(true);
const report = await FreshdeskSDK.runDiagnostics();
console.log(report.prettyPrinted);
```
Do not change code without a diagnostic signal.
Each check: `id`, `status` (`pass|warn|fail|skipped`), `details`, `fixHint`.
### Step B2 — Triage (priority order)
1. `fail` — fix first.
2. `warn` — likely symptom cause.
3. `skipped` — informational (Android `runtime.diagnostics` until native parity).
| Check / symptom | Action |
|-----------------|--------|
| `config.token` empty | User must fill `.env` / native files (Phase 2) |
| `network.configEndpoint` 401/403/404 | Wrong token, host, or sdkId |
| `config.hostScheme` warn (Android) | Bare domain — auto-normalized on 1.2.2+; prefer `https://` in `.env` |
| `runtime.doubleInit` warn (Android) | Remove `MainApplication.onCreate()` native init; use JS init |
| `runtime.sdkInitialized` fail | Ensure `initialize()` awaited before other calls |
| `runtime.nativeModule` fail | `pod install`, Gradle clean, rebuild native app |
| `push.sdkToken` not set (iOS) | Native init + APNs forwarding |
| `push.messagingService` warn (Android) | Register FCM messaging service |
| Init throws `FRESHDESK_INVALID_CONFIG` | Empty token/host/sdkId in env wiring |
| iOS: `openSupport()`/`trackEvent()`/`setUserProperties()` silently no-op or fail right after `initialize()` resolves | Confirm the SDK version includes the `initialize()` settle-delay fix (see `CHANGELOG.md` / [platform-apis.md](platform-apis.md)). On a version without it, add a short delay after `initialize()` resolves before the first other call, or upgrade. |
Always cite exact `fixHint` from the report.
### Step B3 — JWT troubleshooting
If `jwt.*` fails or `UserState` not `authenticated`/`identifierUpdated`:
1. Check `remoteConfig.jwtEnforced` in iOS report.
2. Pass `jwt` at init; refresh with `authenticateAndUpdate(jwt)`.
3. `addUserStateListener` for `authExpired`.
4. Verify server signing key matches widget encryption key.
Reference: https://support.freshdesk.com/en/support/solutions/articles/50000011580-enable-jwt-authentication
### Step B4 — Validate fix
Re-run diagnostics after each change. Confirm previously failing checks are `pass` and symptom resolved.
---
## Output format
### Mode C must include
1. Direct answer sourced from [integration-knowledge-base.md](integration-knowledge-base.md) or [integration-faq.md](integration-faq.md).
2. Platform callouts when Android and iOS differ.
3. Code snippet only when it clarifies the answer.
4. Diagnostics suggestion if the question implies a failure.
5. For "what do I need before integrating?" questions → point to [integration-faq.md](integration-faq.md) **Before you integrate** section.
### Mode A must include
1. Mode confirmation (greenfield).
2. Host + locale collected; credential file paths listed with placeholders for token/sdkId/jwt.
3. Integration inventory results (existing vs created per area).
4. **Integration Summary** — mandatory section at the end (see template below).
5. Link to **[integration-faq.md](integration-faq.md)** for post-integration checklist and common questions.
6. Diagnostics hand-off: build, run, open support, share report.
#### Integration Summary template (required output)
After all code changes, output this section so the customer knows exactly what changed:
```markdown
## Freshdesk integration summary
### Credentials — you update manually
- List each file path (`.env`, `build.gradle`, `Info.plist`) and which keys need portal values
### Files changed
| Area | File | What changed |
|------|------|--------------|
| npm | package.json | Added @freshworks/react-native-freshdesk-sdk |
| JS | ... | Init provider, support button, listeners |
| Android | ... | (list each file or "none") |
| iOS | ... | (list each file or "none") |
| Push | ... | (if applicable) |
| JWT | ... | (if applicable) |
### APIs wired
- List each FreshdeskSDK method integrated (initialize, openSupport, listeners, push, JWT, etc.)
### Manual steps for you
1. Fill credentials in listed files
2. pod install / rebuild commands
3. Test: open support, run diagnostics
### Docs & FAQ
- [Integration FAQ](ai/skills/freshdesk-react-native-integration/integration-faq.md) — prerequisites, what changed, post-integration checklist
- [Knowledge base](ai/skills/freshdesk-react-native-integration/integration-knowledge-base.md) — answer any follow-up questions
- [Platform APIs](ai/skills/freshdesk-react-native-integration/platform-apis.md) — Android vs iOS differences
```
Populate every row with **actual files touched** in the host app — do not leave generic placeholders.
### Mode B must include
1. `overallStatus` + first non-pass check (`id`, `details`, `fixHint`).
2. Minimal fix per check using `fixHint` verbatim.
3. Re-run diagnostics verification step.
4. If files were modified: brief **Integration Summary** (files changed + what was fixed) and link [integration-faq.md](integration-faq.md).
Never invent token, host, sdkId, or JWT. Never ask users to paste secrets in chat.
---
## Reference links
- [integration-faq.md](integration-faq.md) — prerequisites, what changes in your app, post-integration checklist
- [integration-knowledge-base.md](integration-knowledge-base.md) — Q&A knowledge base for any integration question
- [platform-apis.md](platform-apis.md) — Android vs iOS differences
- [troubleshooting.md](troubleshooting.md) — Kotlin metadata mismatch, iOS FreshdeskSDK embed, common build/launch fixes
- [examples.md](examples.md) — worked scenarios
- `PLATFORM_DIFFERENCES.md` (ships in the npm package root) — every method whose
runtime behavior, not just error surface, differs by platform: `resetUser()`,
`enableDebugLogs()`, `getUnreadCount()`, `trackEvent()`, and the iOS
`initialize()` settle delay.
- Installation: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/installation.md
- Initialization: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/initialization.md
- API reference: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/api_reference.md
- Troubleshooting: https://github.com/freshworks/freshdesk_react_native_sdk/blob/main/docs/integration/troubleshooting.md
## Do not
- Do not edit `sdk_src` or `node_modules/@freshworks/react-native-freshdesk-sdk` in consumer apps.
- Do not commit `.env`, `google-services.json`, APNs keys, or real credentials.
- Do not use JS-only init for push.
- Do not set iOS deployment target below `15.0` or Android `minSdkVersion` below `26`.
- Do not invent credentials or paste secrets into chat.